You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
315 lines
9.5 KiB
315 lines
9.5 KiB
import 'dart:io';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
import 'package:logger/logger.dart';
|
|
import 'package:device_info_plus/device_info_plus.dart';
|
|
import '../models/channel_app_model.dart';
|
|
import 'network/api.dart';
|
|
|
|
/// 版本更新服务类
|
|
class VersionUpdateService extends GetxService {
|
|
static VersionUpdateService get to => Get.find();
|
|
|
|
final Logger _logger = Logger();
|
|
|
|
/// 获取当前应用版本信息
|
|
Future<String> getCurrentVersion() async {
|
|
try {
|
|
final packageInfo = await PackageInfo.fromPlatform();
|
|
return '${packageInfo.version}+${packageInfo.buildNumber}';
|
|
} catch (e) {
|
|
_logger.e('获取当前版本信息失败: $e');
|
|
return '1.0.0';
|
|
}
|
|
}
|
|
|
|
/// 获取当前平台信息
|
|
Future<PlatformInfo> getCurrentPlatformInfo() async {
|
|
if (kIsWeb) {
|
|
return const PlatformInfo(
|
|
platform: 'web',
|
|
storeType: AppStoreType.official,
|
|
channel: '官方网站',
|
|
);
|
|
}
|
|
|
|
if (Platform.isIOS) {
|
|
return const PlatformInfo(
|
|
platform: 'ios',
|
|
storeType: AppStoreType.appStore,
|
|
channel: 'App Store',
|
|
);
|
|
}
|
|
|
|
if (Platform.isAndroid) {
|
|
// 根据设备品牌判断应用商店类型
|
|
return await getAndroidStoreInfoByBrand();
|
|
}
|
|
|
|
return const PlatformInfo(
|
|
platform: 'unknown',
|
|
storeType: AppStoreType.unknown,
|
|
channel: '未知',
|
|
);
|
|
}
|
|
|
|
/// 根据设备品牌获取应用商店信息
|
|
Future<PlatformInfo> getAndroidStoreInfoByBrand() async {
|
|
try {
|
|
final deviceInfo = DeviceInfoPlugin();
|
|
final androidInfo = await deviceInfo.androidInfo;
|
|
final brand = androidInfo.brand.toLowerCase();
|
|
|
|
return const PlatformInfo(
|
|
platform: 'android',
|
|
storeType: AppStoreType.official,
|
|
channel: 'officialTesting',
|
|
);
|
|
|
|
// switch (brand) {
|
|
// case 'huawei':
|
|
// case 'honor':
|
|
// return PlatformInfo(
|
|
// platform: 'android',
|
|
// storeType:
|
|
// brand == 'huawei' ? AppStoreType.huawei : AppStoreType.honor,
|
|
// channel: brand == 'huawei' ? '华为应用市场' : '荣耀应用市场',
|
|
// );
|
|
// case 'xiaomi':
|
|
// case 'redmi':
|
|
// return const PlatformInfo(
|
|
// platform: 'android',
|
|
// storeType: AppStoreType.xiaomi,
|
|
// channel: '小米应用商店',
|
|
// );
|
|
// case 'oppo':
|
|
// case 'oneplus':
|
|
// return const PlatformInfo(
|
|
// platform: 'android',
|
|
// storeType: AppStoreType.oppo,
|
|
// channel: 'OPPO软件商店',
|
|
// );
|
|
// case 'vivo':
|
|
// case 'iqoo':
|
|
// return const PlatformInfo(
|
|
// platform: 'android',
|
|
// storeType: AppStoreType.vivo,
|
|
// channel: 'vivo应用商店',
|
|
// );
|
|
// default:
|
|
// return const PlatformInfo(
|
|
// platform: 'android',
|
|
// storeType: AppStoreType.googlePlay,
|
|
// channel: 'Google Play',
|
|
// );
|
|
// }
|
|
} catch (e) {
|
|
_logger.e('获取Android设备信息失败: $e');
|
|
return const PlatformInfo(
|
|
platform: 'android',
|
|
storeType: AppStoreType.googlePlay,
|
|
channel: 'Google Play',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 检查版本更新
|
|
Future<VersionUpdateInfo> checkForUpdate() async {
|
|
try {
|
|
final currentVersion = await getCurrentVersion();
|
|
final platformInfo = await getCurrentPlatformInfo();
|
|
|
|
// 调用后端接口获取最新版本信息
|
|
final response =
|
|
await Api.getChannelApp({'channel': platformInfo.channel});
|
|
|
|
print('获取渠道包信息:$response');
|
|
|
|
if (response == null || !response.containsKey('app')) {
|
|
return VersionUpdateInfo(
|
|
hasUpdate: false,
|
|
currentVersion: currentVersion,
|
|
latestVersion: currentVersion,
|
|
updateType: UpdateType.none,
|
|
);
|
|
}
|
|
|
|
//final channelAppResponse = ChannelAppResponse.fromJson(response);
|
|
// 直接从response中获取app信息
|
|
final appInfo = AppInfo.fromJson(response['app']);
|
|
|
|
// if (channelAppResponse.code != 0 || channelAppResponse.data == null) {
|
|
// _logger.w('获取版本信息失败: ${channelAppResponse.msg}');
|
|
// return VersionUpdateInfo(
|
|
// hasUpdate: false,
|
|
// currentVersion: currentVersion,
|
|
// latestVersion: currentVersion,
|
|
// updateType: UpdateType.none,
|
|
// );
|
|
// }
|
|
|
|
// final appInfo = channelAppResponse.data!.app;
|
|
final hasUpdate = _compareVersions(currentVersion, appInfo.version);
|
|
|
|
return VersionUpdateInfo(
|
|
hasUpdate: hasUpdate,
|
|
currentVersion: currentVersion,
|
|
latestVersion: appInfo.version,
|
|
appInfo: appInfo,
|
|
updateType: hasUpdate ? UpdateType.optional : UpdateType.none,
|
|
);
|
|
} catch (e) {
|
|
_logger.e('检查版本更新失败: $e');
|
|
final currentVersion = await getCurrentVersion();
|
|
return VersionUpdateInfo(
|
|
hasUpdate: false,
|
|
currentVersion: currentVersion,
|
|
latestVersion: currentVersion,
|
|
updateType: UpdateType.none,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// 比较版本号
|
|
/// 返回true表示需要更新(远程版本更高)
|
|
bool _compareVersions(String current, String latest) {
|
|
// 拆分版本号与构建号
|
|
final currentParts = current.split('+');
|
|
final latestParts = latest.split('+');
|
|
|
|
// 解析版本号 (major.minor.patch)
|
|
final currentVersions = currentParts[0].split('.').map(int.parse).toList();
|
|
final latestVersions = latestParts[0].split('.').map(int.parse).toList();
|
|
|
|
// 逐级比较版本号
|
|
for (var i = 0; i < currentVersions.length; i++) {
|
|
if (latestVersions[i] > currentVersions[i]) return true;
|
|
if (latestVersions[i] < currentVersions[i]) return false;
|
|
}
|
|
|
|
// 版本号相同则比较构建号
|
|
if (latestParts.length > 1 && currentParts.length > 1) {
|
|
return int.parse(latestParts[1]) > int.parse(currentParts[1]);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// 解析版本号字符串为数字数组
|
|
List<int> _parseVersion(String version) {
|
|
final parts = version.split('.');
|
|
final result = <int>[];
|
|
|
|
for (int i = 0; i < 3; i++) {
|
|
if (i < parts.length) {
|
|
result.add(int.tryParse(parts[i]) ?? 0);
|
|
} else {
|
|
result.add(0);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// 执行更新操作
|
|
Future<bool> performUpdate(VersionUpdateInfo updateInfo) async {
|
|
if (!updateInfo.hasUpdate || updateInfo.appInfo == null) {
|
|
return false;
|
|
}
|
|
|
|
final platformInfo = await getCurrentPlatformInfo();
|
|
|
|
try {
|
|
switch (platformInfo.storeType) {
|
|
case AppStoreType.appStore:
|
|
return await _openAppStore();
|
|
case AppStoreType.googlePlay:
|
|
return await _openGooglePlay();
|
|
case AppStoreType.huawei:
|
|
return await _openHuaweiStore();
|
|
case AppStoreType.xiaomi:
|
|
return await _openXiaomiStore();
|
|
case AppStoreType.oppo:
|
|
return await _openOppoStore();
|
|
case AppStoreType.vivo:
|
|
return await _openVivoStore();
|
|
case AppStoreType.honor:
|
|
return await _openHonorStore();
|
|
case AppStoreType.official:
|
|
return await _openOfficialDownload(updateInfo.appInfo!.address);
|
|
default:
|
|
return await _openOfficialDownload(updateInfo.appInfo!.address);
|
|
}
|
|
} catch (e) {
|
|
_logger.e('执行更新失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/// 打开iOS App Store
|
|
Future<bool> _openAppStore() async {
|
|
// 这里需要替换为实际的App Store ID
|
|
const appStoreUrl = 'https://apps.apple.com/app/id你的应用ID';
|
|
return await _launchUrl(appStoreUrl);
|
|
}
|
|
|
|
/// 打开Google Play
|
|
Future<bool> _openGooglePlay() async {
|
|
// 这里需要替换为实际的包名
|
|
const packageName = 'com.yourcompany.deepvoice';
|
|
const playStoreUrl =
|
|
'https://play.google.com/store/apps/details?id=$packageName';
|
|
return await _launchUrl(playStoreUrl);
|
|
}
|
|
|
|
/// 打开华为应用市场
|
|
Future<bool> _openHuaweiStore() async {
|
|
const huaweiStoreUrl = 'appmarket://details?id=com.yourcompany.deepvoice';
|
|
return await _launchUrl(huaweiStoreUrl);
|
|
}
|
|
|
|
/// 打开小米应用商店
|
|
Future<bool> _openXiaomiStore() async {
|
|
const xiaomiStoreUrl = 'mimarket://details?id=com.yourcompany.deepvoice';
|
|
return await _launchUrl(xiaomiStoreUrl);
|
|
}
|
|
|
|
/// 打开OPPO软件商店
|
|
Future<bool> _openOppoStore() async {
|
|
const oppoStoreUrl =
|
|
'oppomarket://details?packagename=com.yourcompany.deepvoice';
|
|
return await _launchUrl(oppoStoreUrl);
|
|
}
|
|
|
|
/// 打开vivo应用商店
|
|
Future<bool> _openVivoStore() async {
|
|
const vivoStoreUrl = 'vivomarket://details?id=com.yourcompany.deepvoice';
|
|
return await _launchUrl(vivoStoreUrl);
|
|
}
|
|
|
|
/// 打开荣耀应用市场
|
|
Future<bool> _openHonorStore() async {
|
|
const honorStoreUrl = 'honormarket://details?id=com.yourcompany.deepvoice';
|
|
return await _launchUrl(honorStoreUrl);
|
|
}
|
|
|
|
/// 打开官网下载
|
|
Future<bool> _openOfficialDownload(String downloadUrl) async {
|
|
return await _launchUrl(downloadUrl);
|
|
}
|
|
|
|
/// 启动URL
|
|
Future<bool> _launchUrl(String url) async {
|
|
try {
|
|
final uri = Uri.parse(url);
|
|
if (await canLaunchUrl(uri)) {
|
|
return await launchUrl(uri, mode: LaunchMode.externalApplication);
|
|
}
|
|
return false;
|
|
} catch (e) {
|
|
_logger.e('启动URL失败: $e');
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|