Browse Source

feat(版本更新): 实现应用版本检查与更新功能

添加版本更新服务及相关组件,包括:
1. 新增 VersionUpdateService 处理版本检查逻辑
2. 添加版本更新对话框组件 VersionUpdateDialog
3. 实现渠道包信息获取 API 接口
4. 在设置和启动页集成版本检查功能
5. 添加 url_launcher 依赖用于应用商店跳转
newdev_shunjiawei
lxm 1 year ago
parent
commit
1a8cfdd13d
  1. 4
      android/app/build.gradle.kts
  2. 2
      ios/Runner/Info.plist
  3. 4
      lib/core/bindings/initial_binding.dart
  4. 2
      lib/data/models/appconfig_model.g.dart
  5. 151
      lib/data/models/channel_app_model.dart
  6. 47
      lib/data/models/channel_app_model.g.dart
  7. 17
      lib/data/services/account_service.dart
  8. 9
      lib/data/services/network/api.dart
  9. 312
      lib/data/services/version_update_service.dart
  10. 226
      lib/modules/common/widgets/version_update_dialog.dart
  11. 48
      lib/modules/settings/controllers/settings_controller.dart
  12. 3
      lib/modules/settings/views/settings_view.dart
  13. 24
      lib/modules/splash/controllers/splash_controller.dart
  14. 1
      pubspec.yaml

4
android/app/build.gradle.kts

@ -69,8 +69,8 @@ android {
// For more information, see: https://flutter.dev/to/review-gradle-config. // For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = 26 // 更新为26以满足ble_service库的要求 minSdk = 26 // 更新为26以满足ble_service库的要求
targetSdk = 34 // 设置为 Android 13 (API 33),以匹配 FOREGROUND_SERVICE_MEDIA_PLAYBACK 权限的要求 targetSdk = 34 // 设置为 Android 13 (API 33),以匹配 FOREGROUND_SERVICE_MEDIA_PLAYBACK 权限的要求
versionCode = flutter.versionCode versionCode = flutter.versionCode // 对应构建号,自动同步flutter构建号
versionName = flutter.versionName versionName = flutter.versionName // 对应版本号,自动同步flutter版本号
} }
signingConfigs { signingConfigs {

2
ios/Runner/Info.plist

@ -39,7 +39,7 @@
</array> </array>
</dict> </dict>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key> <!-- 构建号 -->
<string>$(FLUTTER_BUILD_NUMBER)</string> <string>$(FLUTTER_BUILD_NUMBER)</string>
<key>FacebookAdvertiserIDCollectionEnabled</key> <key>FacebookAdvertiserIDCollectionEnabled</key>
<false/> <false/>

4
lib/core/bindings/initial_binding.dart

@ -10,6 +10,7 @@ import '../../core/utils/logger.dart';
import '../../data/services/bluetooth_manager.dart'; import '../../data/services/bluetooth_manager.dart';
import '../../data/services/ble_manager.dart'; import '../../data/services/ble_manager.dart';
import '../../data/services/account_service.dart'; import '../../data/services/account_service.dart';
import '../../data/services/version_update_service.dart';
/// 初始绑定,用于管理全局依赖 /// 初始绑定,用于管理全局依赖
class InitialBinding extends Bindings { class InitialBinding extends Bindings {
@ -46,6 +47,9 @@ class InitialBinding extends Bindings {
// 账号管理服务 // 账号管理服务
Get.lazyPut<AccountService>(() => AccountService(), fenix: true); Get.lazyPut<AccountService>(() => AccountService(), fenix: true);
// 版本更新服务
Get.lazyPut<VersionUpdateService>(() => VersionUpdateService(), fenix: true);
// 杰理蓝牙服务 // 杰理蓝牙服务
// // 语言管理器(需要最先初始化) // // 语言管理器(需要最先初始化)

2
lib/data/models/appconfig_model.g.dart

@ -57,7 +57,7 @@ Map<String, dynamic> _$DBAgentToJson(DBAgent instance) => <String, dynamic>{
DBMCPServer _$DBMCPServerFromJson(Map<String, dynamic> json) => DBMCPServer( DBMCPServer _$DBMCPServerFromJson(Map<String, dynamic> json) => DBMCPServer(
servername: json['servername'] as String, servername: json['servername'] as String,
url: json['url'] as String, url: json['url'] as String,
tools: json['tools'] as String? ?? '', tools: json['tools'] as String,
); );
Map<String, dynamic> _$DBMCPServerToJson(DBMCPServer instance) => Map<String, dynamic> _$DBMCPServerToJson(DBMCPServer instance) =>

151
lib/data/models/channel_app_model.dart

@ -0,0 +1,151 @@
import 'package:json_annotation/json_annotation.dart';
part 'channel_app_model.g.dart';
/// 渠道应用信息响应模型
@JsonSerializable()
class ChannelAppResponse {
@JsonKey(name: 'code')
final int code;
@JsonKey(name: 'data')
final ChannelAppData? data;
@JsonKey(name: 'msg')
final String msg;
const ChannelAppResponse({
required this.code,
this.data,
required this.msg,
});
factory ChannelAppResponse.fromJson(Map<String, dynamic> json) =>
_$ChannelAppResponseFromJson(json);
Map<String, dynamic> toJson() => _$ChannelAppResponseToJson(this);
}
/// 渠道应用数据模型
@JsonSerializable()
class ChannelAppData {
@JsonKey(name: 'app')
final AppInfo app;
const ChannelAppData({
required this.app,
});
factory ChannelAppData.fromJson(Map<String, dynamic> json) =>
_$ChannelAppDataFromJson(json);
Map<String, dynamic> toJson() => _$ChannelAppDataToJson(this);
}
/// 应用信息模型
@JsonSerializable()
class AppInfo {
/// 下载地址
@JsonKey(name: 'address')
final String address;
/// 渠道标识
@JsonKey(name: 'channel')
final String channel;
/// 应用描述
@JsonKey(name: 'description')
final String description;
/// 最新版本号
@JsonKey(name: 'version')
final String version;
const AppInfo({
required this.address,
required this.channel,
required this.description,
required this.version,
});
factory AppInfo.fromJson(Map<String, dynamic> json) =>
_$AppInfoFromJson(json);
Map<String, dynamic> toJson() => _$AppInfoToJson(this);
}
/// 版本更新信息模型
class VersionUpdateInfo {
/// 是否有新版本
final bool hasUpdate;
/// 当前版本
final String currentVersion;
/// 最新版本
final String latestVersion;
/// 应用信息
final AppInfo? appInfo;
/// 更新类型
final UpdateType updateType;
const VersionUpdateInfo({
required this.hasUpdate,
required this.currentVersion,
required this.latestVersion,
this.appInfo,
required this.updateType,
});
}
/// 更新类型枚举
enum UpdateType {
/// 无需更新
none,
/// 可选更新
optional,
/// 强制更新
force,
}
/// 应用商店类型枚举
enum AppStoreType {
/// iOS App Store
appStore,
/// Google Play
googlePlay,
/// 华为应用市场
huawei,
/// 小米应用商店
xiaomi,
/// OPPO软件商店
oppo,
/// vivo应用商店
vivo,
/// 荣耀应用市场
honor,
/// 官网下载
official,
/// 未知
unknown,
}
/// 平台信息模型
class PlatformInfo {
/// 平台类型
final String platform;
/// 应用商店类型
final AppStoreType storeType;
/// 渠道标识
final String channel;
const PlatformInfo({
required this.platform,
required this.storeType,
required this.channel,
});
}

47
lib/data/models/channel_app_model.g.dart

@ -0,0 +1,47 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'channel_app_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
ChannelAppResponse _$ChannelAppResponseFromJson(Map<String, dynamic> json) =>
ChannelAppResponse(
code: (json['code'] as num).toInt(),
data: json['data'] == null
? null
: ChannelAppData.fromJson(json['data'] as Map<String, dynamic>),
msg: json['msg'] as String,
);
Map<String, dynamic> _$ChannelAppResponseToJson(ChannelAppResponse instance) =>
<String, dynamic>{
'code': instance.code,
'data': instance.data,
'msg': instance.msg,
};
ChannelAppData _$ChannelAppDataFromJson(Map<String, dynamic> json) =>
ChannelAppData(
app: AppInfo.fromJson(json['app'] as Map<String, dynamic>),
);
Map<String, dynamic> _$ChannelAppDataToJson(ChannelAppData instance) =>
<String, dynamic>{
'app': instance.app,
};
AppInfo _$AppInfoFromJson(Map<String, dynamic> json) => AppInfo(
address: json['address'] as String,
channel: json['channel'] as String,
description: json['description'] as String,
version: json['version'] as String,
);
Map<String, dynamic> _$AppInfoToJson(AppInfo instance) => <String, dynamic>{
'address': instance.address,
'channel': instance.channel,
'description': instance.description,
'version': instance.version,
};

17
lib/data/services/account_service.dart

@ -25,7 +25,7 @@ class AccountService extends GetxService {
Future<bool> clearUserData() async { Future<bool> clearUserData() async {
try { try {
// 清理所有存储 // 清理所有存储
await _storage.erase(); //await _storage.erase();
// 或者逐个清理关键存储项 // 或者逐个清理关键存储项
await _storage.write("logintoken", null); await _storage.write("logintoken", null);
await _storage.write("user_info", null); await _storage.write("user_info", null);
@ -38,6 +38,18 @@ class AccountService extends GetxService {
} }
} }
Future<bool> clearAllUserData() async {
// 清理所有用户数据
try {
await _storage.erase();
logger.d('所有用户数据清理成功');
return true;
} catch (e) {
logger.e('用户数据清理失败: $e');
return false;
}
}
/// 退出第三方登录 /// 退出第三方登录
/// ///
/// 返回操作是否成功 /// 返回操作是否成功
@ -105,7 +117,8 @@ class AccountService extends GetxService {
} }
// 清理本地数据 // 清理本地数据
final dataCleaned = await clearUserData(); final dataCleaned = await clearAllUserData(); // 一次性清除所有数据
if (!dataCleaned) { if (!dataCleaned) {
return AccountOperationResult( return AccountOperationResult(
success: false, success: false,

9
lib/data/services/network/api.dart

@ -107,4 +107,13 @@ class Api {
params: params, params: params,
); );
} }
//获取渠道包信息
static getChannelApp([params]) {
return DioManager().request(
NWMethod.post,
'/api/home/user_getchannelapp',
params: params,
);
}
} }

312
lib/data/services/version_update_service.dart

@ -0,0 +1,312 @@
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: '官方内测',
);
// 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 currentVersion, String remoteVersion) {
try {
final current = _parseVersion(currentVersion);
final remote = _parseVersion(remoteVersion);
for (int i = 0; i < 3; i++) {
if (remote[i] > current[i]) {
return true;
} else if (remote[i] < current[i]) {
return false;
}
}
return false; // 版本相同
} catch (e) {
_logger.e('版本比较失败: $e');
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;
}
}
}

226
lib/modules/common/widgets/version_update_dialog.dart

@ -0,0 +1,226 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import '../../../data/models/channel_app_model.dart';
import '../../../data/services/version_update_service.dart';
/// 版本更新提示对话框
class VersionUpdateDialog extends StatelessWidget {
final VersionUpdateInfo updateInfo;
final VoidCallback? onCancel;
final VoidCallback? onUpdate;
const VersionUpdateDialog({
super.key,
required this.updateInfo,
this.onCancel,
this.onUpdate,
});
@override
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
child: Container(
width: 320.w,
padding: EdgeInsets.all(24.w),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[900] : Colors.white,
borderRadius: BorderRadius.circular(16.r),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 标题图标
Container(
width: 64.w,
height: 64.w,
decoration: BoxDecoration(
color: Colors.blue.withOpacity(0.1),
borderRadius: BorderRadius.circular(32.r),
),
child: Icon(
Icons.system_update,
size: 32.sp,
color: Colors.blue,
),
),
SizedBox(height: 16.h),
// 标题
Text(
'发现新版本',
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.bold,
color: isDarkMode ? Colors.white : Colors.black87,
),
),
SizedBox(height: 8.h),
// 版本信息
Text(
'${updateInfo.currentVersion} → ${updateInfo.latestVersion}',
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
),
SizedBox(height: 16.h),
// 更新描述
if (updateInfo.appInfo?.description.isNotEmpty == true) ...[
Container(
width: double.infinity,
padding: EdgeInsets.all(12.w),
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey[100],
borderRadius: BorderRadius.circular(8.r),
),
child: Text(
updateInfo.appInfo!.description,
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[300] : Colors.grey[700],
height: 1.4,
),
),
),
SizedBox(height: 20.h),
],
// 按钮区域
Row(
children: [
// 取消按钮(仅在非强制更新时显示)
if (updateInfo.updateType != UpdateType.force) ...[
Expanded(
child: TextButton(
onPressed: () {
Get.back();
onCancel?.call();
},
style: TextButton.styleFrom(
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
side: BorderSide(
color: isDarkMode ? Colors.grey[600]! : Colors.grey[300]!,
),
),
),
child: Text(
'稍后提醒',
style: TextStyle(
fontSize: 16.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
),
),
),
SizedBox(width: 12.w),
],
// 更新按钮
Expanded(
child: ElevatedButton(
onPressed: () async {
Get.back();
await _handleUpdate();
onUpdate?.call();
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 12.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.r),
),
elevation: 0,
),
child: Text(
_getUpdateButtonText(),
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
),
),
),
],
),
],
),
),
);
}
/// 获取更新按钮文本
String _getUpdateButtonText() {
switch (updateInfo.updateType) {
case UpdateType.force:
return '立即更新';
case UpdateType.optional:
return '立即更新';
default:
return '检查更新';
}
}
/// 处理更新操作
Future<void> _handleUpdate() async {
try {
// 显示加载提示
Get.dialog(
const Center(
child: CircularProgressIndicator(),
),
barrierDismissible: false,
);
final versionService = VersionUpdateService.to;
final success = await versionService.performUpdate(updateInfo);
// 关闭加载提示
Get.back();
if (!success) {
Get.snackbar(
'更新失败',
'无法打开应用商店,请手动前往应用商店更新',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,
);
}
} catch (e) {
// 关闭加载提示
if (Get.isDialogOpen == true) {
Get.back();
}
Get.snackbar(
'更新失败',
'更新过程中发生错误,请稍后重试',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,
);
}
}
/// 显示版本更新对话框
static Future<void> show(VersionUpdateInfo updateInfo) async {
await Get.dialog(
VersionUpdateDialog(updateInfo: updateInfo),
barrierDismissible: updateInfo.updateType != UpdateType.force,
);
}
}

48
lib/modules/settings/controllers/settings_controller.dart

@ -16,6 +16,8 @@ import 'package:package_info_plus/package_info_plus.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'dart:async'; import 'dart:async';
import 'package:app_settings/app_settings.dart'; import 'package:app_settings/app_settings.dart';
import '../../../data/services/version_update_service.dart';
import '../../common/widgets/version_update_dialog.dart';
class SettingsController extends GetxController { class SettingsController extends GetxController {
// 语言设置 // 语言设置
@ -490,4 +492,50 @@ class SettingsController extends GetxController {
} }
} }
} }
/// 手动检查版本更新
Future<void> checkForUpdate() async {
try {
// 显示加载提示
Get.dialog(
const Center(
child: CircularProgressIndicator(),
),
barrierDismissible: false,
);
final versionService = VersionUpdateService.to;
final updateInfo = await versionService.checkForUpdate();
// 关闭加载提示
Get.back();
if (updateInfo.hasUpdate) {
// 显示更新对话框
await VersionUpdateDialog.show(updateInfo);
} else {
// 显示已是最新版本的提示
Get.snackbar(
'检查更新',
'当前已是最新版本 ${updateInfo.currentVersion}',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.green.withOpacity(0.8),
colorText: Colors.white,
);
}
} catch (e) {
// 关闭加载提示
if (Get.isDialogOpen == true) {
Get.back();
}
Get.snackbar(
'检查更新失败',
'网络连接异常,请稍后重试',
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.8),
colorText: Colors.white,
);
}
}
} }

3
lib/modules/settings/views/settings_view.dart

@ -858,7 +858,8 @@ class SettingsView extends GetView<SettingsController> {
), ),
InkWell( InkWell(
onTap: () { onTap: () {
// 在这里添加检查更新的逻辑 // 调用检查更新方法
controller.checkForUpdate();
}, },
child: Container( child: Container(
constraints: BoxConstraints( constraints: BoxConstraints(

24
lib/modules/splash/controllers/splash_controller.dart

@ -8,6 +8,8 @@ import '../../../data/models/user_Info.dart';
import '../../../routes/app_routes.dart'; import '../../../routes/app_routes.dart';
import '../../../core/themes/theme_service.dart'; import '../../../core/themes/theme_service.dart';
import '../../../data/services/network/api.dart'; import '../../../data/services/network/api.dart';
import '../../../data/services/version_update_service.dart';
import '../../../modules/common/widgets/version_update_dialog.dart';
class SplashController extends GetxController { class SplashController extends GetxController {
final GetStorage _storage = GetStorage(); final GetStorage _storage = GetStorage();
@ -73,6 +75,9 @@ class SplashController extends GetxController {
// await _loadImages(); // await _loadImages();
// await _initDatabase(); // await _initDatabase();
// 检查版本更新(在后台进行,不阻塞启动流程)
_checkVersionUpdate();
_isResourceLoaded.value = true; _isResourceLoaded.value = true;
_checkNavigateCondition(); _checkNavigateCondition();
} catch (e) { } catch (e) {
@ -151,4 +156,23 @@ class SplashController extends GetxController {
return false; return false;
} }
} }
/// 检查版本更新(后台执行,不阻塞启动流程)
void _checkVersionUpdate() {
// 延迟执行版本检查,避免影响启动速度
Timer(const Duration(seconds: 2), () async {
try {
final versionService = VersionUpdateService.to;
final updateInfo = await versionService.checkForUpdate();
if (updateInfo.hasUpdate) {
// 显示更新对话框
await VersionUpdateDialog.show(updateInfo);
}
} catch (e) {
print('版本检查失败: $e');
// 版本检查失败不影响用户使用,静默处理
}
});
}
} }

1
pubspec.yaml

@ -57,6 +57,7 @@ dependencies:
lottie: ^3.3.1 lottie: ^3.3.1
app_settings: 5.2.0 app_settings: 5.2.0
fluwx: ^5.4.1 fluwx: ^5.4.1
url_launcher: ^6.3.1
firebase_core: ^3.12.1 firebase_core: ^3.12.1
firebase_auth: ^5.5.1 firebase_auth: ^5.5.1
google_sign_in: ^6.2.2 google_sign_in: ^6.2.2

Loading…
Cancel
Save