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

feat:优化代码

上级 f01f7c6d
import 'package:apk_update/apk_update.dart';
import 'package:apk_update/utils/toast_util.dart';
import 'package:apk_update/app_upgrade_factory.dart';
import 'package:apk_update/core/common/app_upgrade_config.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
......@@ -26,53 +26,93 @@ class _MyAppState extends State<MyApp> {
children: [
TextButton(
onPressed: () {
ApkUpdate().checkAppVersion(
var appUpgrade = AppUpgradeFactory.create(
config: AppUpgradeConfig(
baseUrl: "https://api.clxkj.cn:8088",
productCode: "",
token: "a0b6655571e0412787c9e0dd113ded74",
onceDay: false,
appleId: "1585610919",
versionNumber: 1,
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('升级应用(旧)'),
),
TextButton(
onPressed: () {
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",
},
var appUpgrade = AppUpgradeFactory.create(
config: AppUpgradeConfig(
baseUrl: "https://gateway.testclx.cn",
productCode: "carrier-driver-app",
token: "a0b6655571e0412787c9e0dd113ded74",
onceDay: false,
downloadApkError: () {
ToastUtil.showToast('下载Apk错误');
},
paramsOSS: map,
appleId: "1585610919");
appleId: "1585610919",
versionNumber: 1,
),
);
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('升级应用(新)'),
),
TextButton(
onPressed: () {
var map = {
'token': "a0b6655571e0412787c9e0dd113ded74",
};
ApkUpdate().updateAppByPM(
var appUpgrade = AppUpgradeFactory.create(
config: AppUpgradeConfig(
baseUrl: "https://gateway.91msl.com",
productCode: "carrier-driver-app",
versionNumber: 1,
token: "a0b6655571e0412787c9e0dd113ded74",
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('升级应用(项目管理工具)'),
),
......
import 'dart:io';
library apk_update;
import 'package:apk_update/utils/dio_update_util.dart';
import 'package:apk_update/utils/toast_util.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("应用更新失败,请稍后重新");
// },
// );
}
}
export 'app_upgrade_factory.dart';
export 'core/common/app_upgrade_config.dart';
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 {
static const String getSystemVersionByNumber =
"/user-service/system/version/getSystemVersionByNumber";
/// ==================== 承运 ====================
// 获取版本号
static const String getSystemVersionByNumberCarrier =
"/clx-user/app/version/getSystemVersionByNumber";
/// ==================== 项目管理工具 ====================
// 项目管理工 具 版本检测接口
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/services/version_service/version_service.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart';
import '../../../utils/dio_update_util.dart';
import '../../../utils/toast_util.dart';
import '../../common/constants.dart';
import '../../../../utils/dio_update_util.dart';
import '../../../../utils/toast_util.dart';
import '../../../common/app_upgrade_config.dart';
import '../../../common/constants.dart';
import '../../../common/servier_api.dart';
/// 承运
class CarrierVersionServices implements VersionService {
/// 网络全路径
final String url;
/// 请求头
final Map<String, dynamic>? header;
/// 请求参数
final Map<String, dynamic>? params;
class CarrierVersionImpl implements VersionService {
final AppUpgradeConfig config;
/// 一天提示一次升级标识
final bool onceDay;
const CarrierVersionServices({
required this.url,
this.params,
this.header,
this.onceDay = false,
});
const CarrierVersionImpl({required this.config});
@override
Future<VersionInfo?> checkVersion() async {
var result =
await DioUpdateUtil.get(url, queryParameters: params, headers: header);
var result = await DioUpdateUtil.get(
"${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 current =
DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
//一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
if (onceDay && result?['versionForce'] == 0 && spCurrent == current) {
if (config.onceDay &&
result?['versionForce'] == 0 &&
spCurrent == current) {
// 不再提示
return null;
}
//缓存当前时间
SpUtil.putString(Constants.spCurrentDay, current);
// 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
if (!onceDay && result == null) {
if (!config.onceDay && result == null) {
// 当前已经是最新版本
ToastUtil.showToast("已经是最新版本了!");
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/services/version_service/version_service.dart';
import 'package:flustars_flutter3/flustars_flutter3.dart';
import '../../../utils/dio_update_util.dart';
import '../../../utils/toast_util.dart';
import '../../common/constants.dart';
import '../../../../utils/dio_update_util.dart';
import '../../../../utils/toast_util.dart';
import '../../../common/constants.dart';
import '../../../common/servier_api.dart';
/// 老马上来
class MSLVersionServices implements VersionService {
/// 网络全路径
final String url;
/// 请求头
final Map<String, dynamic>? header;
/// 请求参数
final Map<String, dynamic>? params;
class MSLVersionImpl implements VersionService {
final AppUpgradeConfig config;
/// 一天提示一次升级标识
final bool onceDay;
const MSLVersionServices({
required this.url,
this.params,
this.header,
this.onceDay = false,
});
const MSLVersionImpl({required this.config});
@override
Future<VersionInfo?> checkVersion() async {
var result =
await DioUpdateUtil.get(url, queryParameters: params, headers: header);
var result = await DioUpdateUtil.get(
"${config.baseUrl}${ServerApi.getSystemVersionByNumber}",
queryParameters: {
"versionNumber": config.versionNumber,
"productNo": config.productNo
},
);
if (result == null) return null;
//获取当前时间
String spCurrent = SpUtil.getString(Constants.spCurrentDay) ?? "";
String current =
DateUtil.formatDate(DateTime.now(), format: Constants.dateFormat);
//一天提示一次升级 & 非强升 & 当天已提示 => 不再提示
if (onceDay && result?['versionForce'] == 0 && spCurrent == current) {
if (config.onceDay &&
result?['versionForce'] == 0 &&
spCurrent == current) {
// 不再提示
return null;
}
//缓存当前时间
SpUtil.putString(Constants.spCurrentDay, current);
// 一天提示一次升级,是在应用首次设置,不需要提示最新版本toast
if (!onceDay && result == null) {
if (!config.onceDay && result == null) {
// 当前已经是最新版本
ToastUtil.showToast("已经是最新版本了!");
return null;
......
import 'dart:convert';
import 'dart:io';
import 'package:apk_update/core/common/version_info.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/toast_util.dart';
import '../../common/constants.dart';
import '../../common/servier_api.dart';
import '../../../../utils/dio_update_util.dart';
import '../../../../utils/toast_util.dart';
import '../../../common/app_upgrade_config.dart';
import '../../../common/servier_api.dart';
/// 项目管理工具
class PMVersionServices implements VersionService {
/// 域名
final String baseUrl;
class PMVersionImpl implements VersionService {
final AppUpgradeConfig 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,
});
const PMVersionImpl({required this.config});
@override
Future<VersionInfo?> checkVersion() async {
......@@ -48,16 +32,22 @@ class PMVersionServices implements VersionService {
/// 版本检测
Future<dynamic> checkVersionPM() async {
var checkResult = await DioUpdateUtil.get(
"$baseUrl${ServerApi.getLatestByProductCodePM}",
queryParameters: params,
headers: header);
"${config.baseUrl}${ServerApi.getLatestByProductCodePM}",
queryParameters: {
"productCode": config.productCode,
"currentVersion": config.versionNumber,
"sideType": Platform.isIOS ? 2 : 1
},
headers: {"productGroupCode": "common"},
);
if (checkResult == null) return null;
// 是否是最新版本提示
final newVersion =
int.tryParse(checkResult?['version']?.toString() ?? '') ?? 0;
final currentVersion =
int.tryParse(params?["currentVersion"]?.toString() ?? '') ?? 0;
int.tryParse(config.versionNumber?.toString() ?? '') ?? 0;
if (newVersion <= currentVersion) {
if (!onceDay) {
if (!config.onceDay) {
ToastUtil.showToast('已经是最新版本了!');
}
return null;
......@@ -68,16 +58,17 @@ class PMVersionServices implements VersionService {
/// 获取版本详情
Future<dynamic> getVersionDetailPM(int? id) async {
var detailResult = await DioUpdateUtil.get(
"$baseUrl${ServerApi.getDetailPM}",
"${config.baseUrl}${ServerApi.getDetailPM}",
queryParameters: {'id': id},
headers: header);
headers: {"productGroupCode": "common"});
if (detailResult == null) return null;
// 是否是最新版本提示
final newVersion =
int.tryParse(detailResult?['version']?.toString() ?? '') ?? 0;
final currentVersion =
int.tryParse(params?["currentVersion"]?.toString() ?? '') ?? 0;
int.tryParse(config.versionNumber?.toString() ?? '') ?? 0;
if (newVersion <= currentVersion) {
if (!onceDay) {
if (!config.onceDay) {
ToastUtil.showToast('已经是最新版本了!');
}
return null;
......
import 'package:apk_update/core/common/version_info.dart';
import '../../../utils/connectivity_util.dart';
import '../../../utils/toast_util.dart';
/// 版本检测接口
/// 版本检测
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();
}
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';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'connectivity_util.dart';
class DioUpdateUtil {
static final Dio _dio = _initDio();
......@@ -31,6 +33,9 @@ class DioUpdateUtil {
Map<String, dynamic>? queryParameters,
Map<String, dynamic>? headers,
}) async {
if (!await checkNetWorker()) {
return null;
}
try {
final Response response = await _dio.get(
path,
......@@ -40,6 +45,7 @@ class DioUpdateUtil {
return successCallbackHandler(response);
} on DioException catch (e) {
debugPrint(e.message);
ToastUtil.showToast(e.message);
return null;
}
}
......@@ -51,6 +57,9 @@ class DioUpdateUtil {
Map<String, dynamic>? queryParameters,
Map<String, dynamic>? headers,
}) async {
if (!await checkNetWorker()) {
return null;
}
try {
final Response response = await _dio.post(
path,
......@@ -61,6 +70,7 @@ class DioUpdateUtil {
return successCallbackHandler(response);
} on DioException catch (e) {
debugPrint(e.message);
ToastUtil.showToast(e.message);
return null;
}
}
......@@ -80,18 +90,14 @@ class DioUpdateUtil {
}
}
// /// 日志打印
// void printLog(Response? response) {
// var responseData = response?.data;
// var requestOptions = response?.requestOptions;
// var headers = response?.headers;
// debugPrint("========== 网络请求响应 ==========\n"
// "statusCode:${response?.statusCode} \n"
// "statusMessage:${response?.statusMessage}\n"
// "method:${requestOptions?.method}\n"
// "path:${requestOptions?.path}\n"
// "headers:${headers?.map}\n\n"
// "queryParameters:${requestOptions?.queryParameters}\n"
// "data:${requestOptions?.data}\n"
// "responseData:$responseData\n");
// }
/// 网络检测
Future<bool> checkNetWorker() async {
// 判断网络是否连接
var resList = await connectivity.checkConnectivity();
if (resList.isNotEmpty && resList[0] == ConnectivityResult.none) {
ToastUtil.showToast("网络异常,请检查网络");
return false;
}
return true;
}
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';
/// 处理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 {
setInitDir(initStorageDir: true);
......@@ -50,3 +33,10 @@ void jumpAppStore(String id) async {
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
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论