完成app更新功能
This commit is contained in:
parent
91678fdfef
commit
1361e36be3
|
@ -1,38 +1,35 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:device_info/device_info.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:news_getx/config/storage.dart';
|
import 'package:news_getx/config/storage.dart';
|
||||||
import 'package:news_getx/data/services/storage.dart';
|
import 'package:news_getx/data/services/storage.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:device_info/device_info.dart';
|
|
||||||
|
|
||||||
class ConfigService extends GetxService {
|
class ConfigService extends GetxService {
|
||||||
|
/// 静态变量
|
||||||
static ConfigService get to => Get.find();
|
static ConfigService get to => Get.find();
|
||||||
|
|
||||||
bool isFirstOpen = false;
|
// 发布渠道
|
||||||
RxBool isGrayFilter = false.obs;
|
|
||||||
|
|
||||||
PackageInfo? _platform;
|
|
||||||
|
|
||||||
/// 发布渠道
|
|
||||||
static String channel = "xxx";
|
static String channel = "xxx";
|
||||||
|
|
||||||
/// 是否 ios
|
// 是否 ios
|
||||||
static bool isIOS = Platform.isIOS;
|
static bool isIOS = Platform.isIOS;
|
||||||
|
|
||||||
/// android 设备信息
|
// android 设备信息
|
||||||
static AndroidDeviceInfo? androidDeviceInfo;
|
static AndroidDeviceInfo? androidDeviceInfo;
|
||||||
|
|
||||||
/// ios 设备信息
|
// ios 设备信息
|
||||||
static IosDeviceInfo? iosDeviceInfo;
|
static IosDeviceInfo? iosDeviceInfo;
|
||||||
|
|
||||||
|
/// 响应式成员变量
|
||||||
|
RxBool isGrayFilter = false.obs;
|
||||||
|
|
||||||
String get version => _platform?.version ?? "-";
|
/// 成员变量
|
||||||
|
bool isFirstOpen = false;
|
||||||
|
PackageInfo? _platform;
|
||||||
|
|
||||||
bool get isRelease => bool.fromEnvironment("dart.vm.product");
|
|
||||||
|
|
||||||
// Locale locale = Locale("en", "US");
|
|
||||||
Locale locale = Locale("zh", "CN");
|
Locale locale = Locale("zh", "CN");
|
||||||
|
|
||||||
List<Locale> languages = [
|
List<Locale> languages = [
|
||||||
|
@ -40,6 +37,11 @@ class ConfigService extends GetxService {
|
||||||
Locale('zh', 'CN'),
|
Locale('zh', 'CN'),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/// Getter
|
||||||
|
String get version => _platform?.version ?? "-";
|
||||||
|
|
||||||
|
bool get isRelease => bool.fromEnvironment("dart.vm.product");
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onInit() async {
|
void onInit() async {
|
||||||
super.onInit();
|
super.onInit();
|
||||||
|
@ -62,6 +64,7 @@ class ConfigService extends GetxService {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> getPlatform() async {
|
Future<void> getPlatform() async {
|
||||||
|
// 获取包信息
|
||||||
_platform = await PackageInfo.fromPlatform();
|
_platform = await PackageInfo.fromPlatform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +73,7 @@ class ConfigService extends GetxService {
|
||||||
return StorageService.to.setBool(StorageDeviceFirstOpenKey, false);
|
return StorageService.to.setBool(StorageDeviceFirstOpenKey, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始化语言环境 暂未使用
|
||||||
void onInitLocale() {
|
void onInitLocale() {
|
||||||
String langCode = StorageService.to.getString(StorageLanguageCode);
|
String langCode = StorageService.to.getString(StorageLanguageCode);
|
||||||
if (langCode.isEmpty) return;
|
if (langCode.isEmpty) return;
|
||||||
|
@ -81,6 +85,7 @@ class ConfigService extends GetxService {
|
||||||
locale = languages[index];
|
locale = languages[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 改变语言环境
|
||||||
void onLocaleUpdate(Locale value) {
|
void onLocaleUpdate(Locale value) {
|
||||||
locale = value;
|
locale = value;
|
||||||
// 更新app的语言
|
// 更新app的语言
|
||||||
|
|
|
@ -4,8 +4,12 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:news_getx/data/provider/app.dart';
|
||||||
|
import 'package:news_getx/data/services/config.dart';
|
||||||
import 'package:news_getx/theme/app_colors.dart';
|
import 'package:news_getx/theme/app_colors.dart';
|
||||||
import 'package:news_getx/utils/iconfont.dart';
|
import 'package:news_getx/utils/iconfont.dart';
|
||||||
|
import 'package:news_getx/utils/update.dart';
|
||||||
|
import 'package:permission_handler/permission_handler.dart';
|
||||||
import 'package:uni_links/uni_links.dart';
|
import 'package:uni_links/uni_links.dart';
|
||||||
|
|
||||||
class ApplicationController extends GetxController {
|
class ApplicationController extends GetxController {
|
||||||
|
@ -150,6 +154,24 @@ class ApplicationController extends GetxController {
|
||||||
];
|
];
|
||||||
|
|
||||||
pageController = PageController(initialPage: page);
|
pageController = PageController(initialPage: page);
|
||||||
|
|
||||||
|
// 系统更新检查
|
||||||
|
if (ConfigService.to.isRelease) {
|
||||||
|
doAppUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future doAppUpdate() async {
|
||||||
|
// 延迟三秒 用户体验好些
|
||||||
|
await Future.delayed(Duration(seconds: 3), () async {
|
||||||
|
if (ConfigService.isIOS == false &&
|
||||||
|
await Permission.storage.isGranted == false) {
|
||||||
|
await [Permission.storage].request();
|
||||||
|
}
|
||||||
|
if (await Permission.storage.isGranted) {
|
||||||
|
AppUpdateUtil().run();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -15,4 +15,3 @@ class BookmarksPage extends GetView<BookmarksController> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,72 +1,15 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:install_plugin/install_plugin.dart';
|
import 'package:install_plugin/install_plugin.dart';
|
||||||
import 'package:news_getx/data/model/app.dart';
|
import 'package:news_getx/data/model/app.dart';
|
||||||
import 'package:news_getx/data/repository/app_repository.dart';
|
import 'package:news_getx/data/repository/app_repository.dart';
|
||||||
import 'package:news_getx/data/services/config.dart';
|
import 'package:news_getx/data/services/config.dart';
|
||||||
|
import 'package:news_getx/modules/widgets/toast.dart';
|
||||||
|
import 'package:news_getx/utils/http.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
// todo 如何用完一次就消失
|
|
||||||
class DownloadController extends GetxController {
|
|
||||||
// 进度条
|
|
||||||
var _progressValue = 0.0.obs;
|
|
||||||
|
|
||||||
double get progressValue => _progressValue.value;
|
|
||||||
|
|
||||||
set progressValue(double value) {
|
|
||||||
_progressValue.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 下载文件 & 安装
|
|
||||||
Future<void> _downloadAPKAndSetup(fileUrl) async {
|
|
||||||
_progressValue.value = 0.0;
|
|
||||||
|
|
||||||
// 下载
|
|
||||||
Directory? externalDir = await getExternalStorageDirectory();
|
|
||||||
|
|
||||||
if (externalDir == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 存储路径
|
|
||||||
String fullPath = "${externalDir.path}/release.apk";
|
|
||||||
|
|
||||||
// Dio dio = Dio(BaseOptions(
|
|
||||||
// responseType: ResponseType.bytes,
|
|
||||||
// followRedirects: false,
|
|
||||||
// validateStatus: (status) {
|
|
||||||
// return status! < 500;
|
|
||||||
// }
|
|
||||||
// ));
|
|
||||||
//
|
|
||||||
// // 获取APP文件
|
|
||||||
// Response response = await dio.get(fileUrl);
|
|
||||||
//
|
|
||||||
// // 文件写入
|
|
||||||
// File file = File(fullPath);
|
|
||||||
// var raf = file.openSync(mode: FileMode.write);
|
|
||||||
// raf.writeByteSync(response.data);
|
|
||||||
// await raf.close();
|
|
||||||
|
|
||||||
await Dio().download(fileUrl, fullPath, onReceiveProgress: (count, total) {
|
|
||||||
final value = count / total;
|
|
||||||
if (_progressValue.value != value) {
|
|
||||||
if (_progressValue.value < 1.0) {
|
|
||||||
_progressValue.value = count / total;
|
|
||||||
} else {
|
|
||||||
_progressValue.value = 0.0;
|
|
||||||
}
|
|
||||||
print("${(_progressValue * 100).toStringAsFixed(0)}%");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// 安装
|
|
||||||
await InstallPlugin.installApk(fullPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// App 更新
|
/// App 更新
|
||||||
class AppUpdateUtil {
|
class AppUpdateUtil {
|
||||||
static AppUpdateUtil _instance = AppUpdateUtil._internal();
|
static AppUpdateUtil _instance = AppUpdateUtil._internal();
|
||||||
|
@ -97,30 +40,77 @@ class AppUpdateUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 检查是否有新版
|
/// 检查是否有新版
|
||||||
Future _runAppUpdate() async {
|
Future<void> _runAppUpdate() async {
|
||||||
// 比较版本
|
// 比较版本
|
||||||
final isNewVersion =
|
final isNewVersion =
|
||||||
_appUpdateInfo!.latestVersion!.compareTo(ConfigService.to.version) > 0;
|
_appUpdateInfo!.latestVersion!.compareTo(ConfigService.to.version) > 0;
|
||||||
|
|
||||||
// 发现新版本
|
// 发现新版本
|
||||||
if (isNewVersion) {
|
if (isNewVersion) {
|
||||||
// todo 确认弹窗 确认完成下载并显示进度条
|
_appUpdateConformDialog(() {
|
||||||
Get.defaultDialog(
|
Get.back(); // 手动关闭对话框
|
||||||
title: "发现新版本 ${_appUpdateInfo!.latestVersion}",
|
if (ConfigService.isIOS) {
|
||||||
content: GetBuilder<DownloadController>(
|
// 前往AppStore
|
||||||
init: DownloadController(),
|
InstallPlugin.gotoAppStore(_appUpdateInfo!.shopUrl!);
|
||||||
builder: (controller) {
|
} else {
|
||||||
return LinearProgressIndicator(value: controller.progressValue);
|
// 下载APK
|
||||||
},
|
toastInfo(msg: "开始下载升级包");
|
||||||
),
|
_downloadAPKAndSetup(
|
||||||
);
|
_appUpdateInfo!.fileUrl!, _appUpdateInfo!.latestVersion!);
|
||||||
|
}
|
||||||
// _appUpdateConformDialog(
|
});
|
||||||
//
|
|
||||||
// );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 下载文件 & 安装
|
||||||
|
Future<void> _downloadAPKAndSetup(String fileUrl, String version) async {
|
||||||
|
// 下载
|
||||||
|
Directory? externalDir = await getExternalStorageDirectory();
|
||||||
|
|
||||||
|
if (externalDir == null) {
|
||||||
|
toastInfo(msg: "获取文件夹信息失败");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String filename = "release-{$version}.apk";
|
||||||
|
// 存储路径
|
||||||
|
String fullPath = "${externalDir.path}/$filename";
|
||||||
|
bool isFileFound = false;
|
||||||
|
|
||||||
|
final files = externalDir.listSync();
|
||||||
|
for (FileSystemEntity file in files) {
|
||||||
|
if (file is File && file.path.endsWith(filename)) {
|
||||||
|
isFileFound = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isFileFound) {
|
||||||
|
await HttpUtil().dio.download(fileUrl, fullPath);
|
||||||
|
}
|
||||||
|
// 安装
|
||||||
|
await InstallPlugin.installApk(fullPath);
|
||||||
|
}
|
||||||
|
|
||||||
/// 升级确认对话框
|
/// 升级确认对话框
|
||||||
void _appUpdateConformDialog(VoidCallback onPressed) {}
|
void _appUpdateConformDialog(VoidCallback onPressed) {
|
||||||
|
Get.dialog(
|
||||||
|
AlertDialog(
|
||||||
|
title: Text('发现新版本 ${_appUpdateInfo!.latestVersion}'),
|
||||||
|
content: Text(_appUpdateInfo!.latestDescription ?? ''),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
child: Text('取消'),
|
||||||
|
onPressed: () {
|
||||||
|
Get.back(); // 手动关闭对话框
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
child: Text('同意'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue