提交 a0569e3b authored 作者: 史晓晨's avatar 史晓晨

feat:优化代码

上级 f01f7c6d
import 'package:apk_update/apk_update.dart'; import 'package:apk_update/app_upgrade_factory.dart';
import 'package:apk_update/utils/toast_util.dart'; import 'package:apk_update/core/common/app_upgrade_config.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
...@@ -26,53 +26,93 @@ class _MyAppState extends State<MyApp> { ...@@ -26,53 +26,93 @@ class _MyAppState extends State<MyApp> {
children: [ children: [
TextButton( TextButton(
onPressed: () { onPressed: () {
ApkUpdate().checkAppVersion( var appUpgrade = AppUpgradeFactory.create(
config: AppUpgradeConfig(
baseUrl: "https://api.clxkj.cn:8088", baseUrl: "https://api.clxkj.cn:8088",
productCode: "",
token: "a0b6655571e0412787c9e0dd113ded74",
onceDay: false,
appleId: "1585610919",
versionNumber: 1, versionNumber: 1,
productNo: 27, productNo: 27,
onceDay: false, ),
appleId: "1585610919"); );
appUpgrade.checkUpdate();
// ApkUpdate().checkAppVersion(
// baseUrl: "https://api.clxkj.cn:8088",
// versionNumber: 1,
// productNo: 27,
// onceDay: false,
// appleId: "1585610919");
}, },
child: const Text('升级应用(旧)'), child: const Text('升级应用(旧)'),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
var map = { var appUpgrade = AppUpgradeFactory.create(
'token': "20502a804a784bc1a21681e26aa14cb8", config: AppUpgradeConfig(
'objectKey': 'msl.apk', baseUrl: "https://gateway.testclx.cn",
'bucketName': 'mslapp-download', productCode: "carrier-driver-app",
'endpoint': 'oss-cn-beijing.aliyuncs.com', token: "a0b6655571e0412787c9e0dd113ded74",
"baseUrl": "https://gateway.testclx.cn"
};
ApkUpdate().updateApp(
url:
"https://gateway.testclx.cn/clx-user/app/version/getSystemVersionByNumber",
params: {
"versionNumber": 1,
"productNo": 1,
"productCode": "carrier-driver-app",
},
onceDay: false, onceDay: false,
downloadApkError: () { appleId: "1585610919",
ToastUtil.showToast('下载Apk错误'); versionNumber: 1,
}, ),
paramsOSS: map, );
appleId: "1585610919");
appUpgrade.checkUpdate();
// var map = {
// 'token': "20502a804a784bc1a21681e26aa14cb8",
// 'objectKey': 'msl.apk',
// 'bucketName': 'mslapp-download',
// 'endpoint': 'oss-cn-beijing.aliyuncs.com',
// "baseUrl": "https://gateway.testclx.cn"
// };
// ApkUpdate().updateApp(
// url:
// "https://gateway.testclx.cn/clx-user/app/version/getSystemVersionByNumber",
// params: {
// "versionNumber": 1,
// "productNo": 1,
// "productCode": "carrier-driver-app",
// },
// onceDay: false,
// downloadApkError: () {
// ToastUtil.showToast('下载Apk错误');
// },
// paramsOSS: map,
// appleId: "1585610919");
}, },
child: const Text('升级应用(新)'), child: const Text('升级应用(新)'),
), ),
TextButton( TextButton(
onPressed: () { onPressed: () {
var map = {
'token': "a0b6655571e0412787c9e0dd113ded74", var appUpgrade = AppUpgradeFactory.create(
}; config: AppUpgradeConfig(
ApkUpdate().updateAppByPM(
baseUrl: "https://gateway.91msl.com", baseUrl: "https://gateway.91msl.com",
productCode: "carrier-driver-app", productCode: "carrier-driver-app",
versionNumber: 1, token: "a0b6655571e0412787c9e0dd113ded74",
onceDay: false, onceDay: false,
paramsOSS: map, appleId: "1585610919",
appleId: "1585610919"); versionNumber: 1,
),
);
appUpgrade.checkUpdate();
// var map = {
// 'token': "a0b6655571e0412787c9e0dd113ded74",
// };
// ApkUpdate().updateAppByPM(
// baseUrl: "https://gateway.91msl.com",
// productCode: "carrier-driver-app",
// versionNumber: 1,
// onceDay: false,
// paramsOSS: map,
// appleId: "1585610919");
}, },
child: const Text('升级应用(项目管理工具)'), child: const Text('升级应用(项目管理工具)'),
), ),
......
import 'dart:io'; library apk_update;
import 'package:apk_update/utils/dio_update_util.dart'; export 'app_upgrade_factory.dart';
import 'package:apk_update/utils/toast_util.dart'; export 'core/common/app_upgrade_config.dart';
import 'package:apk_update/utils/utils.dart';
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
import 'apk_update_platform_interface.dart';
import 'core/common/constants.dart';
import 'core/common/servier_api.dart';
import 'utils/check_version/check_version.dart';
class ApkUpdate {
/// 检测应用版本(老版本方法)
/// baseUrl
/// versionNumber 当前应用版本号(versionCode)
/// productNo 产品号
/// onceDay 一天提示一次(应用首页设置true)
/// appleId 苹果应用id
/// 产品号:1.司机App(Android) 2.vipApp(Android) 4.马上富通App(Android) 9.马上来车App(Android)
/// 27.司机App(iOS) 28.vipApp(iOS) 30.马上富通App(iOS) 29.马上来车App(iOS)
void checkAppVersion({
required String baseUrl,
required int versionNumber,
required int productNo,
Map<String, dynamic>? paramsOSS,
bool onceDay = false,
required String appleId,
Function()? downloadApkError, // 下载Apk错误
}) {
//App2.vipApp,3,vip-pc。4,马上富通。5,马上富通pc。6,微信货主。7,货主pc。8,马上审。默认为1
// checkVersion(
// url: "$baseUrl${ServerApi.getSystemVersionByNumber}",
// method: Method.get,
// params: {"versionNumber": versionNumber, "productNo": productNo},
// isOssDownload: paramsOSS != null ? 1 : 0,
// onceDay: onceDay,
// jumpAppStore: () {
// // 跳转AppStore
// debugPrint("===== jumpAppStore");
// jumpAppStore(appleId);
// },
// installApk: (String? path) {
// // 安装Apk
// debugPrint("===== installApk");
// ApkUpdatePlatform.instance.installApk(path);
// },
// downloadApkError: () {
// // 下载Apk错误
// debugPrint("===== downloadApkError");
// // 项目中没有依赖toast,自己项目中实现
// downloadApkError?.call();
// },
// );
}
/// 升级版本(新)
/// url 全路径
/// appleId 苹果应用id
/// params {"versionNumber": 1, "product-code": "carrier-driver-app"}
/// paramsOSS {"ak": "ak", "sk": "sk", "token": "token", "objectKey": "objectKey", "endpoint": "endpoint", "bucketName": "bucketName", }
void updateApp({
required String url,
required Map<String, dynamic> params,
bool onceDay = false,
required String appleId,
Map<String, dynamic>? paramsOSS,
Function()? downloadApkError, // 下载Apk错误
}) {
// checkVersion(
// url: url,
// method: Method.post,
// params: params,
// isOssDownload: paramsOSS != null ? 1 : 0,
// header: {"product-code": params["productCode"]},
// onceDay: onceDay,
// jumpAppStore: () {
// // 跳转AppStore
// debugPrint("===== jumpAppStore");
// jumpAppStore(appleId);
// },
// installApk: (String? path) {
// // 安装Apk
// debugPrint("===== installApk");
// ApkUpdatePlatform.instance.installApk(path);
// },
// downloadApk: (String? path, String? apkPath) async {
// DioUpdateUtil.getDio()
// .get("${paramsOSS?['baseUrl']}${ServerApi.generateByExt}",
// queryParameters: {
// "extension": "apk",
// "bucketName": paramsOSS?["bucketName"]
// },
// options: Options(headers: {
// "token": paramsOSS?['token'],
// "product-code": params["productCode"]
// }))
// .then((res) {
// if (res.data == null || res.data is String) {
// debugPrint('获取OSS授权失败: ${res.data}');
// downloadApkError?.call();
// return;
// }
// var map = res.data['data'];
// // 使用OSS下载
// var ak = map?['onceAccessKeyId'];
// var sk = map?["onceAccessKeySecret"];
// var token = map?["onceSecurityToken"];
// var objectKey = apkPath ?? "";
// // apkPath https://mslapp-download.oss-cn-beijing.aliyuncs.com/msl-chengyun.apk 截取后:msl-chengyun.apk
// objectKey = objectKey.substring(objectKey.lastIndexOf("/") + 1);
//
// var endpoint = paramsOSS?["endpoint"];
// var bucketName = paramsOSS?["bucketName"];
// var localPath = path;
// if (localPath == null) {
// // 项目中没有依赖toast,自己项目中实现
// downloadApkError?.call();
// return;
// }
// ApkUpdatePlatform.instance.downloadApk(ak, sk, token, objectKey,
// endpoint, bucketName, localPath, "fileName");
// }).catchError((e) {
// debugPrint('获取OSS授权失败');
// downloadApkError?.call();
// return;
// });
// },
// downloadApkError: () {
// // 下载Apk错误
// debugPrint("===== downloadApkError");
// // 项目中没有依赖toast,自己项目中实现
// downloadApkError?.call();
// },
// );
}
/// 对接项目管理工具升级功能
/// baseUrl:
void updateAppByPM({
required String baseUrl,
required String productCode,
required int versionNumber,
required String appleId,
bool onceDay = false,
Map<String, dynamic>? paramsOSS,
}) {
// var params = {
// "productCode": productCode,
// "currentVersion": versionNumber,
// "sideType": Platform.isIOS ? 2 : 1
// };
// checkVersionPM(
// baseUrl: baseUrl,
// params: params,
// onceDay: onceDay,
// isOssDownload: paramsOSS != null ? 1 : 0,
// jumpAppStore: () {
// // 跳转AppStore
// debugPrint("===== jumpAppStore");
// jumpAppStore(appleId);
// },
// installApk: (String? path) {
// // 安装Apk
// debugPrint("===== installApk");
// ApkUpdatePlatform.instance.installApk(path);
// },
// downloadApk: (String? path, String? apkPath) async {
// var objectKey = apkPath ?? "";
//
// objectKey = getObjectKey(objectKey);
// DioUpdateUtil.getDio()
// .get("$baseUrl${ServerApi.generateByExt}",
// queryParameters: {
// "extension": "apk",
// "bucketName": paramsOSS?["bucketName"] ?? Constants.ossBucketName
// },
// options: Options(headers: {
// "token": paramsOSS?['token'],
// "product-code": params["productCode"]
// }))
// .then((res) {
// if (res.data == null || res.data is String) {
// debugPrint('获取OSS授权失败: ${res.data}');
// ToastUtil.showToast("获取OSS授权失败,请稍后重新");
// return;
// }
// var map = res.data['data'];
// // 使用OSS下载
// var ak = map?['onceAccessKeyId'];
// var sk = map?["onceAccessKeySecret"];
// var token = map?["onceSecurityToken"];
//
// var localPath = path;
// if (localPath == null) {
// ToastUtil.showToast("下载路径错误,请稍后重新");
// return;
// }
// var localPathFileName = getFileName(objectKey);
// ApkUpdatePlatform.instance.downloadApk(
// ak,
// sk,
// token,
// objectKey,
// paramsOSS?["endpoint"] ?? Constants.ossEndpoint,
// paramsOSS?["bucketName"] ?? Constants.ossBucketName,
// localPath,
// localPathFileName);
// }).catchError((e) {
// debugPrint('获取OSS授权失败');
// ToastUtil.showToast("获取OSS授权失败,请稍后重新");
// return;
// });
// },
// downloadApkError: () {
// // 下载Apk错误
// debugPrint("===== downloadApkError");
// ToastUtil.showToast("应用更新失败,请稍后重新");
// },
// );
}
}
import 'dart:async';
import 'dart:io';
import 'package:apk_update/core/common/version_info.dart';
import 'package:apk_update/utils/toast_util.dart';
import 'package:apk_update/utils/utils.dart';
import 'package:get/get.dart';
import 'apk_update_platform_interface.dart';
import 'core/common/app_upgrade_config.dart';
import 'core/services/download_service/download_service.dart';
import 'core/services/version_service/version_service.dart';
import 'widget/update_dialog.dart';
/// 升级逻辑
class AppUpgradeControl {
/// 版本
final VersionService versionService;
/// 下载
final DownloadService downloadService;
/// 配置
final AppUpgradeConfig config;
AppUpgradeControl({
required this.versionService,
required this.downloadService,
required this.config,
});
/// 检查更新
Future<void> checkUpdate() async {
// 检查更新,获取新版本详情
final versionInfo = await versionService.checkVersion();
if (versionInfo == null) return;
// 升级弹框提示
_showUpgradeDialog(versionInfo, config.appleId);
}
/// 检查下载
void _showUpgradeDialog(VersionInfo versionInfo, String? appleId) async {
Get.dialog(
AppUpgradeDialog(
title: versionInfo.name,
content: versionInfo.content,
versionForce: versionInfo.versionForce == true,
onAppMarket: (String? url) {
if (Platform.isIOS) {
jumpAppStore(appleId ?? "");
} else {
openBrowser(url ?? "");
}
},
onDownLoad: () {
if (versionInfo.versionPath == null) {
ToastUtil.showToast("下载地址错误,请稍后重新");
return;
}
_downloadApk(versionInfo.versionPath ?? "");
},
),
);
}
/// 下载apk
void _downloadApk(String downloadUrl) {
findOtherLogic<AppUpgradeDialogLogic>()?.updateDownload(true);
downloadService.download(
url: downloadUrl,
onProgress: (progress) {
findOtherLogic<AppUpgradeDialogLogic>()?.updateProgress(progress);
},
onSuccess: (path) {
// 下载完成,去安装
findOtherLogic<AppUpgradeDialogLogic>()?.updateDownload(false);
ApkUpdatePlatform.instance.installApk(path);
},
onError: (error) {
findOtherLogic<AppUpgradeDialogLogic>()?.updateDownload(false);
ToastUtil.showToast("下载失败,请稍后重新");
},
);
}
}
import 'package:apk_update/app_upgrade_control.dart';
import 'package:apk_update/core/services/download_service/download_service.dart';
import 'package:apk_update/core/services/download_service/download_service_factory.dart';
import 'package:apk_update/core/services/version_service/version_service_factory.dart';
import 'core/common/app_upgrade_config.dart';
import 'core/services/version_service/version_service.dart';
class AppUpgradeFactory {
static AppUpgradeControl create({required AppUpgradeConfig config}) {
assert(config.baseUrl.isNotEmpty, "请传递baseUrl参数");
assert(config.token != null && config.token!.isNotEmpty, "请传递token参数");
assert(config.productCode != null, "请传递productCode参数");
// 配置版本服务
VersionService versionService = VersionServiceFactory.create(
config: config,
type: config.type ?? "pm",
);
// 配置下载服务
DownloadService downloadService = DownloadServiceFactory.create(
baseUrl: config.baseUrl,
token: config.token!,
productCode: config.productCode!,
);
return AppUpgradeControl(
versionService: versionService,
downloadService: downloadService,
config: config,
);
}
}
/// 配置类
class AppUpgradeConfig {
/// 域名
final String baseUrl;
/// 一天提示一次升级标识
final bool onceDay;
/// token
final String? token;
/// 产品编码
final String? productCode;
/// appleId
final String? appleId;
/// 当前版本code
final int? versionNumber;
/// App2.vipApp,3,vip-pc。4,马上富通。5,马上富通pc。6,微信货主。7,货主pc。8,马上审。默认为1
final int? productNo;
/// 类型 msl carrier pm
final String? type;
const AppUpgradeConfig({
required this.baseUrl,
this.onceDay = false,
this.token,
this.productCode,
this.appleId,
this.versionNumber,
this.productNo,
this.type,
});
}
...@@ -4,6 +4,11 @@ class ServerApi { ...@@ -4,6 +4,11 @@ class ServerApi {
static const String getSystemVersionByNumber = static const String getSystemVersionByNumber =
"/user-service/system/version/getSystemVersionByNumber"; "/user-service/system/version/getSystemVersionByNumber";
/// ==================== 承运 ====================
// 获取版本号
static const String getSystemVersionByNumberCarrier =
"/clx-user/app/version/getSystemVersionByNumber";
/// ==================== 项目管理工具 ==================== /// ==================== 项目管理工具 ====================
// 项目管理工 具 版本检测接口 // 项目管理工 具 版本检测接口
static const getLatestByProductCodePM = static const getLatestByProductCodePM =
......
/// 下载
typedef DownloadProgressCallback = void Function(double progress);
typedef DownloadSuccessCallback = void Function(String filePath);
typedef DownloadErrorCallback = void Function(Exception error);
abstract class DownloadService {
Future<void> download({
required String url,
DownloadProgressCallback? onProgress,
DownloadSuccessCallback? onSuccess,
DownloadErrorCallback? onError,
});
void cancel();
}
import 'package:apk_update/core/services/download_service/impl/normal_download_impl.dart';
import 'package:apk_update/core/services/download_service/impl/oss_download_impl.dart';
import 'download_service.dart';
/// 下载服务工厂
class DownloadServiceFactory {
static DownloadService create({
required String baseUrl,
required String token,
required String productCode,
}) {
if (baseUrl.startsWith("https://gateway.")) {
// oss
return OSSDownloadImpl(
baseUrl: baseUrl, token: token, productCode: productCode);
} else {
return NormalDownloadImpl();
}
}
}
import 'dart:io';
import 'package:apk_update/core/services/download_service/download_service.dart';
import 'package:apk_update/utils/dio_update_util.dart';
import 'package:dio/dio.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart';
/// 普通下载
class NormalDownloadImpl implements DownloadService {
CancelToken? _cancelToken;
@override
Future<void> download({
required String url,
DownloadProgressCallback? onProgress,
DownloadSuccessCallback? onSuccess,
DownloadErrorCallback? onError,
}) async {
_cancelToken = CancelToken();
var localPath = await createDownloadPath();
try {
await DioUpdateUtil.dio.download(
url,
localPath,
cancelToken: _cancelToken,
onReceiveProgress: (int count, int total) {
if (total != -1) {
final progress = count / total;
onProgress?.call(progress);
}
},
);
onSuccess?.call(localPath);
} on DioException catch (e) {
if (e.type != DioExceptionType.cancel) {
onError?.call(e);
}
} catch (e) {
onError?.call(Exception('下载失败: $e'));
} finally {
_cancelToken = null;
}
}
@override
void cancel() {
_cancelToken?.cancel('用户取消下载');
_cancelToken = null;
}
/// 创建下载路径
Future<String> createDownloadPath() async {
setInitDir(initStorageDir: true);
await DirectoryUtil.getInstance();
DirectoryUtil.createStorageDirSync(category: 'Download');
String path = DirectoryUtil.getStoragePath(
fileName: 'clx_update', category: 'Download', format: 'apk')!;
File file = File(path);
return file.path;
}
}
import 'dart:async';
import 'dart:io';
import 'package:apk_update/core/services/download_service/download_service.dart';
import 'package:apk_update/utils/dio_update_util.dart';
import 'package:flutter/cupertino.dart';
import '../../../../apk_update_platform_interface.dart';
import '../../../../utils/toast_util.dart';
import '../../../../utils/utils.dart';
import '../../../common/constants.dart';
import 'package:path/path.dart' as p;
import '../../../common/servier_api.dart';
/// OSS下载
class OSSDownloadImpl implements DownloadService {
final String baseUrl;
final String token;
final String productCode;
StreamSubscription<Map<String, Object>>? _subscription;
OSSDownloadImpl({
required this.baseUrl,
required this.token,
required this.productCode,
});
@override
Future<void> download({
required String url,
DownloadProgressCallback? onProgress,
DownloadSuccessCallback? onSuccess,
DownloadErrorCallback? onError,
}) async {
try {
String? path = await createDir();
if (path == null) {
ToastUtil.showToast("下载路径错误,请稍后重新");
return;
}
File apkFile = File("$path/${getFileName(url)}");
File apkFileTmp = File("$path/${getFileName(url)}.tmp");
// 判断localPath 下有没有下载完成的文件
if (apkFile.existsSync() && !apkFileTmp.existsSync()) {
onSuccess?.call(apkFile.path);
return;
}
var ossInfo = await getOssInfo();
// 使用OSS下载
var ak = ossInfo?['onceAccessKeyId'];
var sk = ossInfo?["onceAccessKeySecret"];
var token = ossInfo?["onceSecurityToken"];
var objectKey = getObjectKey(url);
var localPathFileName = getFileName(objectKey);
_subscription =
ApkUpdatePlatform.instance.addDownloadListener().listen((event) {
var count = event['currentSize'] as num;
var total = event['totalSize'] as num;
var isDownloadSuccess = event['isDownloadSuccess'] == "1";
var isDownloadFailed = event['isDownloadSuccess'] == "0";
if (isDownloadFailed) {
// 下载失败
onError?.call(Exception('下载失败: oss'));
return;
}
if (isDownloadSuccess) {
// 下载成功
onSuccess?.call(apkFile.path);
}
final progress = count / total;
onProgress?.call(progress); // 下载进度
});
ApkUpdatePlatform.instance.downloadApk(
ak,
sk,
token,
objectKey,
Constants.ossEndpoint,
Constants.ossBucketName,
path,
localPathFileName);
} catch (e) {
debugPrint(e.toString());
ToastUtil.showToast(e.toString());
}
}
@override
void cancel() {
_subscription?.cancel();
}
/// 获取oss信息
Future<dynamic> getOssInfo() async {
var params = {"extension": "apk", "bucketName": Constants.ossBucketName};
var headers = {"token": token, "product-code": productCode};
var result = await DioUpdateUtil.get("$baseUrl${ServerApi.generateByExt}",
queryParameters: params, headers: headers);
return result;
}
/// 处理apk下载url 获取 objectKey
String getObjectKey(String url) {
int startIndex = url.indexOf("aliyuncs.com/") + "aliyuncs.com/".length;
return url.substring(startIndex);
}
/// 获取下载url文件名
String getFileName(String url) {
return p.basename(url);
}
/// 获取objectKey中的文件夹字符 “msl/common/prod/video/2025-06-20/app-release11.apk” 中获取 “msl/common/prod/video/2025-06-20”
String getPathByObjectKey(String url) {
return p.dirname(url);
}
}
import 'dart:convert';
import 'package:apk_update/core/common/version_info.dart'; import 'package:apk_update/core/common/version_info.dart';
import 'package:apk_update/core/services/version_service/version_service.dart'; import 'package:apk_update/core/services/version_service/version_service.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart'; import 'package:flustars_flutter3/flustars_flutter3.dart';
import '../../../utils/dio_update_util.dart'; import '../../../../utils/dio_update_util.dart';
import '../../../utils/toast_util.dart'; import '../../../../utils/toast_util.dart';
import '../../common/constants.dart'; import '../../../common/app_upgrade_config.dart';
import '../../../common/constants.dart';
import '../../../common/servier_api.dart';
/// 承运 /// 承运
class CarrierVersionServices implements VersionService { class CarrierVersionImpl implements VersionService {
/// 网络全路径 final AppUpgradeConfig config;
final String url;
/// 请求头
final Map<String, dynamic>? header;
/// 请求参数
final Map<String, dynamic>? params;
/// 一天提示一次升级标识 const CarrierVersionImpl({required this.config});
final bool onceDay;
const CarrierVersionServices({
required this.url,
this.params,
this.header,
this.onceDay = false,
});
@override @override
Future<VersionInfo?> checkVersion() async { Future<VersionInfo?> checkVersion() async {
var result = var result = await DioUpdateUtil.get(
await DioUpdateUtil.get(url, queryParameters: params, headers: header); "${config.baseUrl}${ServerApi.getSystemVersionByNumberCarrier}",
queryParameters: {
"versionNumber": config.versionNumber,
"productCode": config.productCode,
},
headers: {"product-code": config.productCode},
);
if (result == null) return null;
//获取当前时间 //获取当前时间
String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? ""; String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? "";
String current = String current =
DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat); DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
//一天提示一次升级 & 非强升 & 当天已提示 => 不再提示 //一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
if (onceDay && result?['versionForce'] == 0 && spCurrent == current) { if (config.onceDay &&
result?['versionForce'] == 0 &&
spCurrent == current) {
// 不再提示 // 不再提示
return null; return null;
} }
//缓存当前时间 //缓存当前时间
SpUtil.putString(Constants.spCurrentDay, current); SpUtil.putString(Constants.spCurrentDay, current);
// 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast // 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
if (!onceDay && result == null) { if (!config.onceDay && result == null) {
// 当前已经是最新版本 // 当前已经是最新版本
ToastUtil.showToast("已经是最新版本了!"); ToastUtil.showToast("已经是最新版本了!");
return null; return null;
......
import 'dart:convert'; import 'package:apk_update/core/common/app_upgrade_config.dart';
import 'package:apk_update/core/common/version_info.dart'; import 'package:apk_update/core/common/version_info.dart';
import 'package:apk_update/core/services/version_service/version_service.dart'; import 'package:apk_update/core/services/version_service/version_service.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart'; import 'package:flustars_flutter3/flustars_flutter3.dart';
import '../../../utils/dio_update_util.dart'; import '../../../../utils/dio_update_util.dart';
import '../../../utils/toast_util.dart'; import '../../../../utils/toast_util.dart';
import '../../common/constants.dart'; import '../../../common/constants.dart';
import '../../../common/servier_api.dart';
/// 老马上来 /// 老马上来
class MSLVersionServices implements VersionService { class MSLVersionImpl implements VersionService {
/// 网络全路径 final AppUpgradeConfig config;
final String url;
/// 请求头
final Map<String, dynamic>? header;
/// 请求参数
final Map<String, dynamic>? params;
/// 一天提示一次升级标识 const MSLVersionImpl({required this.config});
final bool onceDay;
const MSLVersionServices({
required this.url,
this.params,
this.header,
this.onceDay = false,
});
@override @override
Future<VersionInfo?> checkVersion() async { Future<VersionInfo?> checkVersion() async {
var result = var result = await DioUpdateUtil.get(
await DioUpdateUtil.get(url, queryParameters: params, headers: header); "${config.baseUrl}${ServerApi.getSystemVersionByNumber}",
queryParameters: {
"versionNumber": config.versionNumber,
"productNo": config.productNo
},
);
if (result == null) return null;
//获取当前时间 //获取当前时间
String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? ""; String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? "";
String current = String current =
DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat); DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
//一天提示一次升级 & 非强升 & 当天已提示 => 不再提示 //一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
if (onceDay && result?['versionForce'] == 0 && spCurrent == current) { if (config.onceDay &&
result?['versionForce'] == 0 &&
spCurrent == current) {
// 不再提示 // 不再提示
return null; return null;
} }
//缓存当前时间 //缓存当前时间
SpUtil.putString(Constants.spCurrentDay, current); SpUtil.putString(Constants.spCurrentDay, current);
// 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast // 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
if (!onceDay && result == null) { if (!config.onceDay && result == null) {
// 当前已经是最新版本 // 当前已经是最新版本
ToastUtil.showToast("已经是最新版本了!"); ToastUtil.showToast("已经是最新版本了!");
return null; return null;
......
import 'dart:convert'; import 'dart:io';
import 'package:apk_update/core/common/version_info.dart'; import 'package:apk_update/core/common/version_info.dart';
import 'package:apk_update/core/services/version_service/version_service.dart'; import 'package:apk_update/core/services/version_service/version_service.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart';
import '../../../utils/dio_update_util.dart'; import '../../../../utils/dio_update_util.dart';
import '../../../utils/toast_util.dart'; import '../../../../utils/toast_util.dart';
import '../../common/constants.dart'; import '../../../common/app_upgrade_config.dart';
import '../../common/servier_api.dart'; import '../../../common/servier_api.dart';
/// 项目管理工具 /// 项目管理工具
class PMVersionServices implements VersionService { class PMVersionImpl implements VersionService {
/// 域名 final AppUpgradeConfig config;
final String baseUrl;
/// 请求头 const PMVersionImpl({required this.config});
final Map<String, dynamic>? header;
/// 请求参数
final Map<String, dynamic>? params;
/// 一天提示一次升级标识
final bool onceDay;
const PMVersionServices({
required this.baseUrl,
this.params,
this.header,
this.onceDay = false,
});
@override @override
Future<VersionInfo?> checkVersion() async { Future<VersionInfo?> checkVersion() async {
...@@ -48,16 +32,22 @@ class PMVersionServices implements VersionService { ...@@ -48,16 +32,22 @@ class PMVersionServices implements VersionService {
/// 版本检测 /// 版本检测
Future<dynamic> checkVersionPM() async { Future<dynamic> checkVersionPM() async {
var checkResult = await DioUpdateUtil.get( var checkResult = await DioUpdateUtil.get(
"$baseUrl${ServerApi.getLatestByProductCodePM}", "${config.baseUrl}${ServerApi.getLatestByProductCodePM}",
queryParameters: params, queryParameters: {
headers: header); "productCode": config.productCode,
"currentVersion": config.versionNumber,
"sideType": Platform.isIOS ? 2 : 1
},
headers: {"productGroupCode": "common"},
);
if (checkResult == null) return null;
// 是否是最新版本提示 // 是否是最新版本提示
final newVersion = final newVersion =
int.tryParse(checkResult?['version']?.toString() ?? '') ?? 0; int.tryParse(checkResult?['version']?.toString() ?? '') ?? 0;
final currentVersion = final currentVersion =
int.tryParse(params?["currentVersion"]?.toString() ?? '') ?? 0; int.tryParse(config.versionNumber?.toString() ?? '') ?? 0;
if (newVersion <= currentVersion) { if (newVersion <= currentVersion) {
if (!onceDay) { if (!config.onceDay) {
ToastUtil.showToast('已经是最新版本了!'); ToastUtil.showToast('已经是最新版本了!');
} }
return null; return null;
...@@ -68,16 +58,17 @@ class PMVersionServices implements VersionService { ...@@ -68,16 +58,17 @@ class PMVersionServices implements VersionService {
/// 获取版本详情 /// 获取版本详情
Future<dynamic> getVersionDetailPM(int? id) async { Future<dynamic> getVersionDetailPM(int? id) async {
var detailResult = await DioUpdateUtil.get( var detailResult = await DioUpdateUtil.get(
"$baseUrl${ServerApi.getDetailPM}", "${config.baseUrl}${ServerApi.getDetailPM}",
queryParameters: {'id': id}, queryParameters: {'id': id},
headers: header); headers: {"productGroupCode": "common"});
if (detailResult == null) return null;
// 是否是最新版本提示 // 是否是最新版本提示
final newVersion = final newVersion =
int.tryParse(detailResult?['version']?.toString() ?? '') ?? 0; int.tryParse(detailResult?['version']?.toString() ?? '') ?? 0;
final currentVersion = final currentVersion =
int.tryParse(params?["currentVersion"]?.toString() ?? '') ?? 0; int.tryParse(config.versionNumber?.toString() ?? '') ?? 0;
if (newVersion <= currentVersion) { if (newVersion <= currentVersion) {
if (!onceDay) { if (!config.onceDay) {
ToastUtil.showToast('已经是最新版本了!'); ToastUtil.showToast('已经是最新版本了!');
} }
return null; return null;
......
import 'package:apk_update/core/common/version_info.dart'; import 'package:apk_update/core/common/version_info.dart';
import '../../../utils/connectivity_util.dart'; /// 版本检测
import '../../../utils/toast_util.dart';
/// 版本检测接口
abstract class VersionService { abstract class VersionService {
/// 版本检测
Future<VersionInfo?> _checkVersion() async {
// 判断网络是否连接
var resList = await connectivity.checkConnectivity();
if (resList.isNotEmpty && resList[0] == ConnectivityResult.none) {
ToastUtil.showToast("网络异常,请检查网络");
return null;
}
return await checkVersion();
}
Future<VersionInfo?> checkVersion(); Future<VersionInfo?> checkVersion();
} }
import 'package:apk_update/core/common/app_upgrade_config.dart';
import 'package:apk_update/core/services/version_service/impl/carrier_version_Impl.dart';
import 'package:apk_update/core/services/version_service/impl/msl_version_Impl.dart';
import 'package:apk_update/core/services/version_service/impl/pm_version_Impl.dart';
import 'version_service.dart';
/// 版本服务工厂
class VersionServiceFactory {
static VersionService create(
{required AppUpgradeConfig config, required String type}) {
switch (type) {
case "msl":
return MSLVersionImpl(config: config);
case "carrier":
return CarrierVersionImpl(config: config);
case "pm":
return PMVersionImpl(config: config);
default:
throw UnsupportedError("暂不支持该平台下发移动端升级");
}
}
}
// import 'dart:convert';
//
// import 'package:apk_update/utils/connectivity_util.dart';
// import 'package:apk_update/utils/toast_util.dart';
// import 'package:apk_update/widget/update_dialog.dart';
// import 'package:dio/dio.dart';
// import 'package:flustars_flutter3/flustars_flutter3.dart';
// import 'package:get/route_manager.dart';
// import '../../core/common/constants.dart';
// import '../../core/common/servier_api.dart';
//
// /// 获取更新版本信息
// /// url 请求地址
// /// versionNumber 当前应用versionCode
// /// productNo 产品号
// /// onceDay 一天提示一次(应用首页设置true)
// void checkVersion(
// {required String url,
// required Method method,
// Map<String, dynamic>? params,
// Map<String, dynamic>? header,
// bool onceDay = false,
// Function()? jumpAppStore, // 跳转AppStore
// Function(String? path)? installApk, // 安装Apk
// Function()? downloadApkError, // 下载Apk错误
// Function(String? path, String? apkPath)? downloadApk, // 使用OSS下载Apk
// int? isOssDownload //1 使用OSS下载
// }) async {
//
//
// try {
// final Response response = await DioUpdateUtil.getDio().request(
// url,
// options: Options(method: method.value, headers: header),
// queryParameters: params,
// data: params,
// );
// // 网络请求成功
// printLog(response); // 打印日志
// var responseData = response.data;
// if (responseData.runtimeType == String) {
// // 兼容后端数据返回string
// responseData = json.decode(responseData);
// }
// if (responseData?["code"] != 0) {
// ToastUtil.showToast(responseData?["msg"]);
// return;
// }
// var result = responseData?["data"];
// //获取当前时间
// String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? "";
// String current = DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
// //一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
// if (onceDay && result?['versionForce'] == 0 && spCurrent == current) {
// // 不再提示
// return;
// }
// //缓存当前时间
// SpUtil.putString(Constants.spCurrentDay, current);
// // 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
// if (!onceDay && result == null) {
// // 当前已经是最新版本
// ToastUtil.showToast("已经是最新版本了!");
// return;
// }
// if (result == null) {
// // 无升级任务,拦截
// return;
// }
// // 升级弹框提示
// Get.dialog(
// UpdateDialog(
// title: result['versionName'],
// content: result['tipContent'] ?? result['versionContent'],
// versionForce: result['versionForce'] == 1,
// versionPath: result['versionPath'],
// jumpAppStore: jumpAppStore,
// installApk: installApk,
// isOssDownload: isOssDownload,
// downloadApk: downloadApk,
// downloadApkError: downloadApkError,
// ),
// );
// } on DioException catch (e) {
// printLog(e.response); // 打印日志
// ToastUtil.showToast("服务器请求错误");
// }
// }
//
// /// 检查版本(项目管理工具)
// void checkVersionPM(
// {required String baseUrl,
// Map<String, dynamic>? params,
// bool onceDay = false,
// Function()? jumpAppStore, // 跳转AppStore
// Function(String? path)? installApk, // 安装Apk
// Function()? downloadApkError, // 下载Apk错误
// Function(String? path, String? apkPath)? downloadApk, // 使用OSS下载Apk
// int? isOssDownload //1 使用OSS下载
// }) async {
// // 判断网络是否连接
// var resList = await connectivity.checkConnectivity();
//
// if (resList.isNotEmpty && resList[0] == ConnectivityResult.none) {
// ToastUtil.showToast("网络异常,请检查网络");
// return;
// }
//
// try {
// final Response response = await DioUpdateUtil.getDio().request(
// "$baseUrl${ServerApi.getLatestByProductCodePM}",
// options: Options(
// method: Method.get.value, headers: {"productGroupCode": "common"}),
// queryParameters: params,
// );
// // 网络请求成功
// printLog(response); // 打印日志
// var responseData = response.data;
// if (responseData.runtimeType == String) {
// // 兼容后端数据返回string
// responseData = json.decode(responseData);
// }
// if (responseData?["code"] != 0) {
// ToastUtil.showToast(responseData?["msg"]);
// return;
// }
// var result = responseData?["data"];
// // 是否是最新版本提示
// final newVersion = int.tryParse(result?['version']?.toString() ?? '') ?? 0;
// final currentVersion =
// int.tryParse(params?["currentVersion"]?.toString() ?? '') ?? 0;
// if (newVersion <= currentVersion) {
// if (!onceDay) {
// ToastUtil.showToast('已经是最新版本了!');
// }
// return;
// }
// // 获取新版本详情
// getVersionDetailPM(
// baseUrl: baseUrl,
// id: result?['id'],
// onceDay: onceDay,
// versionNumber: params?["currentVersion"],
// jumpAppStore: jumpAppStore,
// installApk: installApk,
// downloadApkError: downloadApkError,
// downloadApk: downloadApk,
// isOssDownload: isOssDownload,
// );
// } on DioException catch (e) {
// printLog(e.response); // 打印日志
// ToastUtil.showToast("服务器请求错误");
// }
// }
//
// /// 获取版本详情(项目管理工具)
// void getVersionDetailPM({
// required String baseUrl,
// required int? id,
// required bool onceDay,
// required int? versionNumber,
// Function()? jumpAppStore, // 跳转AppStore
// Function(String? path)? installApk, // 安装Apk
// Function()? downloadApkError, // 下载Apk错误
// Function(String? path, String? apkPath)? downloadApk, // 使用OSS下载Apk
// int? isOssDownload, //1 使用OSS下载
// }) async {
// // 判断网络是否连接
// var resList = await connectivity.checkConnectivity();
//
// if (resList.isNotEmpty && resList[0] == ConnectivityResult.none) {
// ToastUtil.showToast("网络异常,请检查网络");
// return;
// }
//
// try {
// final Response response = await DioUpdateUtil.getDio().request(
// "$baseUrl${ServerApi.getDetailPM}",
// options: Options(method: Method.get.value, headers: {
// 'productGroupCode': 'common',
// }),
// queryParameters: {'id': id},
// );
// // 网络请求成功
// printLog(response); // 打印日志
// var responseData = response.data;
// if (responseData.runtimeType == String) {
// // 兼容后端数据返回string
// responseData = json.decode(responseData);
// }
// if (responseData?["code"] != 0) {
// ToastUtil.showToast(responseData?["msg"]);
// return;
// }
// var result = responseData?["data"];
// //获取当前时间
// String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? "";
// String current = DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
// // 是否是强升
// final versionForce = result?['forceUpgradeStatus'] == 1;
// //一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
// if (onceDay && !versionForce && spCurrent == current) {
// // 不再提示
// return;
// }
// //缓存当前时间
// SpUtil.putString(Constants.spCurrentDay, current);
// // 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
// if (!onceDay && result == null) {
// // 当前已经是最新版本
// ToastUtil.showToast("已经是最新版本了!");
// return;
// }
// // 是否是最新版本提示
// final newVersion = int.tryParse(result?['version']?.toString() ?? '') ?? 0;
// final currentVersion = int.tryParse(versionNumber?.toString() ?? '') ?? 0;
// if (newVersion <= currentVersion) {
// if (!onceDay) {
// ToastUtil.showToast('已经是最新版本了!');
// }
// return;
// }
//
// // 升级弹框提示
// Get.dialog(
// UpdateDialog(
// title: result['name'],
// content: result['popContent'],
// versionForce: result['forceUpgradeStatus'] == 1,
// versionPath: result['versionPath'],
// jumpAppStore: jumpAppStore,
// installApk: installApk,
// isOssDownload: isOssDownload,
// downloadApk: downloadApk,
// downloadApkError: downloadApkError,
// ),
// );
// } on DioException catch (e) {
// printLog(e.response); // 打印日志
// ToastUtil.showToast("服务器请求错误");
// }
// }
\ No newline at end of file
...@@ -3,6 +3,8 @@ import 'package:apk_update/utils/toast_util.dart'; ...@@ -3,6 +3,8 @@ import 'package:apk_update/utils/toast_util.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'connectivity_util.dart';
class DioUpdateUtil { class DioUpdateUtil {
static final Dio _dio = _initDio(); static final Dio _dio = _initDio();
...@@ -31,6 +33,9 @@ class DioUpdateUtil { ...@@ -31,6 +33,9 @@ class DioUpdateUtil {
Map<String, dynamic>? queryParameters, Map<String, dynamic>? queryParameters,
Map<String, dynamic>? headers, Map<String, dynamic>? headers,
}) async { }) async {
if (!await checkNetWorker()) {
return null;
}
try { try {
final Response response = await _dio.get( final Response response = await _dio.get(
path, path,
...@@ -40,6 +45,7 @@ class DioUpdateUtil { ...@@ -40,6 +45,7 @@ class DioUpdateUtil {
return successCallbackHandler(response); return successCallbackHandler(response);
} on DioException catch (e) { } on DioException catch (e) {
debugPrint(e.message); debugPrint(e.message);
ToastUtil.showToast(e.message);
return null; return null;
} }
} }
...@@ -51,6 +57,9 @@ class DioUpdateUtil { ...@@ -51,6 +57,9 @@ class DioUpdateUtil {
Map<String, dynamic>? queryParameters, Map<String, dynamic>? queryParameters,
Map<String, dynamic>? headers, Map<String, dynamic>? headers,
}) async { }) async {
if (!await checkNetWorker()) {
return null;
}
try { try {
final Response response = await _dio.post( final Response response = await _dio.post(
path, path,
...@@ -61,6 +70,7 @@ class DioUpdateUtil { ...@@ -61,6 +70,7 @@ class DioUpdateUtil {
return successCallbackHandler(response); return successCallbackHandler(response);
} on DioException catch (e) { } on DioException catch (e) {
debugPrint(e.message); debugPrint(e.message);
ToastUtil.showToast(e.message);
return null; return null;
} }
} }
...@@ -80,18 +90,14 @@ class DioUpdateUtil { ...@@ -80,18 +90,14 @@ class DioUpdateUtil {
} }
} }
// /// 日志打印 /// 网络检测
// void printLog(Response? response) { Future<bool> checkNetWorker() async {
// var responseData = response?.data; // 判断网络是否连接
// var requestOptions = response?.requestOptions; var resList = await connectivity.checkConnectivity();
// var headers = response?.headers;
// debugPrint("========== 网络请求响应 ==========\n" if (resList.isNotEmpty && resList[0] == ConnectivityResult.none) {
// "statusCode:${response?.statusCode} \n" ToastUtil.showToast("网络异常,请检查网络");
// "statusMessage:${response?.statusMessage}\n" return false;
// "method:${requestOptions?.method}\n" }
// "path:${requestOptions?.path}\n" return true;
// "headers:${headers?.map}\n\n" }
// "queryParameters:${requestOptions?.queryParameters}\n"
// "data:${requestOptions?.data}\n"
// "responseData:$responseData\n");
// }
import 'package:flustars_flutter3/flustars_flutter3.dart'; import 'package:flustars_flutter3/flustars_flutter3.dart';
import 'package:path/path.dart' as p; import 'package:get/get.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
/// 处理apk下载url 获取 objectKey
String getObjectKey(String url) {
int startIndex = url.indexOf("aliyuncs.com/") + "aliyuncs.com/".length;
return url.substring(startIndex);
}
/// 获取下载url文件名
String getFileName(String url) {
return p.basename(url);
}
/// 获取objectKey中的文件夹字符 “msl/common/prod/video/2025-06-20/app-release11.apk” 中获取 “msl/common/prod/video/2025-06-20”
String getPathByObjectKey(String url) {
return p.dirname(url);
}
/// 创建下载目录 /// 创建下载目录
Future<String?> createDir() async { Future<String?> createDir() async {
setInitDir(initStorageDir: true); setInitDir(initStorageDir: true);
...@@ -50,3 +33,10 @@ void jumpAppStore(String id) async { ...@@ -50,3 +33,10 @@ void jumpAppStore(String id) async {
return; return;
} }
} }
S? findOtherLogic<S>({String? tag}) {
if (Get.isRegistered<S>(tag: tag)) {
return Get.find<S>(tag: tag);
}
return null;
}
\ No newline at end of file
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:apk_update/utils/connectivity_util.dart';
import 'package:apk_update/utils/image_utils.dart'; import 'package:apk_update/utils/image_utils.dart';
import 'package:apk_update/utils/toast_util.dart';
import 'package:apk_update/utils/utils.dart';
import 'package:dio/dio.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart'; import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:get/get.dart';
import '../apk_update_platform_interface.dart'; /// 升级弹框(①强制升级不关闭弹框)
class AppUpgradeDialog extends StatelessWidget {
final logic = Get.put(AppUpgradeDialogLogic());
class UpdateDialog extends StatefulWidget { /// 升级版本
final String? title; // 升级版本 final String? title;
final String? content; // 升级内容
final bool versionForce; // 是否强升
final String? versionPath; // apk 路径
final Function()? jumpAppStore; // 跳转AppStore
final Function(String? path)? installApk; // 安装Apk
final int? isOssDownload; //1 使用OSS下载
final Function(String? path, String? apkPath)? downloadApk; // 使用OSS下载Apk
final Function()? downloadApkError; // 下载Apk错误
const UpdateDialog({ /// 升级内容
final String? content;
/// 是否强升
final bool versionForce;
/// 下载apk
final VoidCallback? onDownLoad;
/// 跳转应用市场
final ValueChanged<String?>? onAppMarket;
AppUpgradeDialog({
Key? key, Key? key,
this.title, this.title,
this.content, this.content,
this.versionForce = false, this.versionForce = false,
this.versionPath, this.onDownLoad,
this.jumpAppStore, this.onAppMarket,
this.installApk,
this.downloadApk,
this.downloadApkError,
this.isOssDownload,
}) : super(key: key); }) : super(key: key);
@override
State<UpdateDialog> createState() => _UpdateDialogState();
}
class _UpdateDialogState extends State<UpdateDialog> {
final CancelToken _cancelToken = CancelToken();
StreamSubscription<Map<String, Object>>? _subscription;
bool _isDownload = false;
double _value = 0;
@override
void dispose() {
if (!_cancelToken.isCancelled && _value != 1) {
_cancelToken.cancel();
}
_subscription?.cancel();
super.dispose();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return WillPopScope( return GetBuilder<AppUpgradeDialogLogic>(builder: (logic) {
onWillPop: () => Future.value(false), //使用false禁止返回键返回,达到强制升级目的 return WillPopScope(
child: Scaffold( onWillPop: () => Future.value(false), //使用false禁止返回键返回,达到强制升级目的
resizeToAvoidBottomInset: false, child: Scaffold(
backgroundColor: Colors.transparent, resizeToAvoidBottomInset: false,
body: Center( backgroundColor: Colors.transparent,
child: SizedBox( body: Center(
width: 280.0, child: SizedBox(
child: Column( width: 280.0,
mainAxisSize: MainAxisSize.min, child: Column(
children: <Widget>[ mainAxisSize: MainAxisSize.min,
// 顶部图片 children: <Widget>[
_topImage(), // 顶部图片
Container( _topImage(),
padding: const EdgeInsets.symmetric(horizontal: 15.0), Container(
decoration: const BoxDecoration( padding: const EdgeInsets.symmetric(horizontal: 15.0),
color: Colors.white, decoration: const BoxDecoration(
borderRadius: BorderRadius.only( color: Colors.white,
bottomLeft: Radius.circular(8.0), borderRadius: BorderRadius.only(
bottomRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0),
bottomRight: Radius.circular(8.0),
),
), ),
), child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ // 标题
// 标题 _content(title: title, content: content),
_content(title: widget.title, content: widget.content), logic.isDownload
_isDownload // 下载进度
// 下载进度 ? LinearProgressIndicator(
? LinearProgressIndicator( backgroundColor: const Color(0xFFF2F3F3),
backgroundColor: const Color(0xFFF2F3F3), value: logic.downloadProgress,
value: _value, )
) // 按钮
// 按钮 : Column(
: Column( children: <Widget>[
children: <Widget>[ _btn(
_btn( context: context,
title: '立即更新', title: '立即更新',
onTap: () async { onTap: () {
if (Platform.isIOS) { if (Platform.isIOS) {
widget.jumpAppStore?.call(); onAppMarket?.call(null);
} else { } else {
// 判断网络是否连接 onDownLoad?.call();
var resList = await connectivity
.checkConnectivity();
if (resList.isNotEmpty &&
resList[0] ==
ConnectivityResult.none) {
ToastUtil.showToast("网络异常,请检查网络");
return;
} }
setState(() { },
_isDownload = true; ),
}); const SizedBox(height: 5.0),
_download(); Offstage(
} offstage: versionForce,
}, child: _btn(
), context: context,
const SizedBox(height: 5.0), title: '忽略此版本',
Offstage( textColor: const Color(0xFF666666),
offstage: widget.versionForce, bgColor: Colors.transparent,
child: _btn( onTap: () => Navigator.pop(context),
title: '忽略此版本', ),
textColor: const Color(0xFF666666),
bgColor: Colors.transparent,
onTap: () => Navigator.pop(context),
), ),
), ],
], ),
), const SizedBox(height: 10.0),
const SizedBox(height: 10.0), ],
], ),
), ),
), ],
], ),
), ),
), ),
), ),
), );
); });
} }
/// 顶部图片 /// 顶部图片
...@@ -179,13 +149,9 @@ class _UpdateDialogState extends State<UpdateDialog> { ...@@ -179,13 +149,9 @@ class _UpdateDialogState extends State<UpdateDialog> {
/// 显示html内容 /// 显示html内容
Widget htmlWidget(String? content) { Widget htmlWidget(String? content) {
return HtmlWidget( return HtmlWidget(
widget.content ?? "", content ?? "",
onTapUrl: (url) { onTapUrl: (url) {
if (Platform.isIOS) { onAppMarket?.call(url);
widget.jumpAppStore?.call();
} else {
openBrowser(url);
}
return true; return true;
}, },
); );
...@@ -197,6 +163,7 @@ class _UpdateDialogState extends State<UpdateDialog> { ...@@ -197,6 +163,7 @@ class _UpdateDialogState extends State<UpdateDialog> {
GestureTapCallback? onTap, GestureTapCallback? onTap,
Color? textColor, Color? textColor,
Color? bgColor, Color? bgColor,
required BuildContext context,
}) => }) =>
InkWell( InkWell(
onTap: onTap, onTap: onTap,
...@@ -214,85 +181,22 @@ class _UpdateDialogState extends State<UpdateDialog> { ...@@ -214,85 +181,22 @@ class _UpdateDialogState extends State<UpdateDialog> {
), ),
), ),
); );
}
///下载apk class AppUpgradeDialogLogic extends GetxController {
Future<void> _download() async { /// 是否正在下载
try { bool isDownload = false;
// 2024-11-21 使用OSSSDK下载
if (widget.isOssDownload == 1) {
//创建本地下载目录
String? path = await createDir();
if (widget.versionPath == null) {
widget.downloadApkError?.call();
_isDownload = false;
setState(() {});
return;
}
File apkFile = File("$path/${getFileName(widget.versionPath!)}");
File apkFileTmp = File("$path/${getFileName(widget.versionPath!)}.tmp");
// 判断localPath 下有没有下载完成的文件
if (apkFile.existsSync() && !apkFileTmp.existsSync()) {
ApkUpdatePlatform.instance.installApk(apkFile.path);
_isDownload = false;
setState(() {});
return;
}
_subscription =
ApkUpdatePlatform.instance.addDownloadListener().listen((event) {
var count = event['currentSize'] as num;
var total = event['totalSize'] as num;
var isDownloadSuccess = event['isDownloadSuccess'] == "1";
var isDownloadFailed = event['isDownloadSuccess'] == "0";
if (isDownloadFailed) {
_isDownload = false;
setState(() {});
return;
}
_value = count / total; /// 下载进度
if (isDownloadSuccess) { double downloadProgress = 0.0;
_isDownload = false;
}
setState(() {});
});
widget.downloadApk?.call(path, widget.versionPath); void updateProgress(double progress) {
return; downloadProgress = progress;
} update();
setInitDir(initStorageDir: true); }
await DirectoryUtil.getInstance();
DirectoryUtil.createStorageDirSync(category: 'Download');
String path = DirectoryUtil.getStoragePath(
fileName: 'clx_update', category: 'Download', format: 'apk')!;
File file = File(path);
debugPrint("===== Apk下载路径:$path");
/// 链接可能会失效 void updateDownload(bool isDownload) {
await Dio().download( this.isDownload = isDownload;
widget.versionPath!, update();
file.path,
cancelToken: _cancelToken,
onReceiveProgress: (int count, int total) {
if (total != -1) {
_value = count / total;
setState(() {});
if (count == total) {
debugPrint("===== Apk下载完成");
widget.installApk?.call(path);
}
}
},
);
} catch (e) {
widget.downloadApkError?.call();
debugPrint("===== Apk下载错误: $e");
setState(() {
_isDownload = false;
});
}
} }
} }
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论