1111
This commit is contained in:
parent
223f225d94
commit
3d1729f630
|
|
@ -0,0 +1,336 @@
|
|||
# App Upgrade Plugin - 完整使用指南
|
||||
|
||||
## 🚀 快速开始
|
||||
|
||||
### 基础用法(一行代码)
|
||||
```dart
|
||||
import 'package:app_upgrade_plugin/app_upgrade_plugin.dart';
|
||||
|
||||
// 最简单的使用方式
|
||||
await AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
url: 'https://api.example.com/check-update',
|
||||
);
|
||||
```
|
||||
|
||||
## ⚙️ 配置选项
|
||||
|
||||
### 预设配置
|
||||
```dart
|
||||
// 自动更新模式
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig.auto);
|
||||
|
||||
// 静默检查模式
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig.silent);
|
||||
|
||||
// 开发模式
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig.development);
|
||||
|
||||
// 生产模式
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig.production);
|
||||
```
|
||||
|
||||
### 自定义配置
|
||||
```dart
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig(
|
||||
showNoUpdateToast: true, // 显示无更新提示
|
||||
autoDownload: false, // 自动下载
|
||||
autoInstall: false, // 自动安装
|
||||
connectionTimeout: 30, // 连接超时(秒)
|
||||
downloadTimeout: 300, // 下载超时(秒)
|
||||
installTimeout: 45, // 安装检测超时(秒)
|
||||
enableDebugLog: true, // 启用调试日志
|
||||
customToast: (message) { // 自定义Toast
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(message)),
|
||||
);
|
||||
},
|
||||
));
|
||||
```
|
||||
|
||||
## 🎯 使用场景
|
||||
|
||||
### 1. 应用启动时检查更新
|
||||
```dart
|
||||
class MyApp extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
home: Builder(
|
||||
builder: (context) {
|
||||
// 应用启动后检查更新
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
url: 'https://api.example.com/check-update',
|
||||
);
|
||||
});
|
||||
return MyHomePage();
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 定期检查更新
|
||||
```dart
|
||||
class MyHomePage extends StatefulWidget {
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
Timer? _updateTimer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// 每24小时检查一次更新
|
||||
_updateTimer = Timer.periodic(const Duration(hours: 24), (_) {
|
||||
AppUpgradeSimple.instance.checkUpdateSilent(
|
||||
url: 'https://api.example.com/check-update',
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_updateTimer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 手动检查更新
|
||||
```dart
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
await AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
url: 'https://api.example.com/check-update',
|
||||
params: {
|
||||
'userId': currentUserId,
|
||||
'channel': releaseChannel,
|
||||
},
|
||||
onComplete: () {
|
||||
print('更新检查完成');
|
||||
},
|
||||
);
|
||||
},
|
||||
child: const Text('检查更新'),
|
||||
)
|
||||
```
|
||||
|
||||
## 🔧 高级功能
|
||||
|
||||
### 预下载APK
|
||||
```dart
|
||||
// 后台预下载,不显示UI
|
||||
final filePath = await AppUpgradeSimple.instance.preDownloadApk(
|
||||
url: 'https://example.com/app.apk',
|
||||
onProgress: (progress) {
|
||||
print('下载进度: ${progress.percentage}%');
|
||||
},
|
||||
);
|
||||
```
|
||||
|
||||
### 查找已下载的APK
|
||||
```dart
|
||||
final existingApk = await AppUpgradeSimple.instance.findDownloadedApk('1.2.0');
|
||||
if (existingApk != null) {
|
||||
print('找到已下载的APK: $existingApk');
|
||||
}
|
||||
```
|
||||
|
||||
### 网络状态检查
|
||||
```dart
|
||||
final hasNetwork = await AppUpgradeSimple.instance.checkNetworkStatus();
|
||||
if (!hasNetwork) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('网络错误'),
|
||||
content: const Text('请检查网络连接'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('确定'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 清理下载缓存
|
||||
```dart
|
||||
// 清理所有下载的APK文件
|
||||
await AppUpgradeSimple.instance.clearDownloadCache();
|
||||
```
|
||||
|
||||
## 🎨 UI定制
|
||||
|
||||
### 自定义Toast
|
||||
```dart
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig(
|
||||
customToast: (message) {
|
||||
// 使用SnackBar代替Toast
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
backgroundColor: Colors.deepPurple,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
},
|
||||
));
|
||||
```
|
||||
|
||||
### 富文本更新内容
|
||||
服务器返回的更新内容支持简单的富文本格式:
|
||||
```
|
||||
**新功能**
|
||||
- 添加了[暗黑模式]支持
|
||||
- 优化了`网络请求`性能
|
||||
- __修复了已知问题__
|
||||
|
||||
**重要更新**
|
||||
请及时更新到最新版本以获得更好的体验!
|
||||
```
|
||||
|
||||
## 📱 平台支持
|
||||
|
||||
### Android
|
||||
- ✅ APK下载和安装
|
||||
- ✅ 权限自动处理
|
||||
- ✅ 多应用商店支持
|
||||
- ✅ 安装状态智能检测
|
||||
- ✅ 断点续传
|
||||
- ✅ 文件校验
|
||||
|
||||
### iOS
|
||||
- ✅ App Store跳转
|
||||
- ✅ 企业证书分发
|
||||
- ✅ TestFlight支持
|
||||
|
||||
## 🔍 调试和测试
|
||||
|
||||
### 启用调试日志
|
||||
```dart
|
||||
AppUpgradeSimple.instance.configure(UpgradeConfig.development);
|
||||
```
|
||||
|
||||
### 查看日志输出
|
||||
```
|
||||
🔍 检查更新结果: UpgradeInfo(...)
|
||||
⚡ 应用回到前台,立即检查安装状态
|
||||
✅ 检测结果: 安装成功
|
||||
❌ 检测结果: 安装未完成
|
||||
```
|
||||
|
||||
### 测试不同场景
|
||||
插件内置了测试按钮,可以模拟各种安装场景:
|
||||
- 模拟安装取消
|
||||
- 模拟权限拒绝
|
||||
- 模拟安装超时
|
||||
|
||||
## 🛡️ 错误处理
|
||||
|
||||
插件提供了完善的错误处理机制:
|
||||
|
||||
### 网络错误
|
||||
- 连接超时
|
||||
- DNS解析失败
|
||||
- 服务器错误
|
||||
- 证书验证失败
|
||||
|
||||
### 安装错误
|
||||
- 权限被拒绝
|
||||
- APK文件损坏
|
||||
- 存储空间不足
|
||||
- 系统版本不兼容
|
||||
|
||||
### 自动重试
|
||||
- 智能检测安装状态
|
||||
- 多种重试方式
|
||||
- 用户友好的错误提示
|
||||
|
||||
## 📊 最佳实践
|
||||
|
||||
### 1. 应用启动检查
|
||||
```dart
|
||||
// 推荐:应用启动时静默检查
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
AppUpgradeSimple.instance.checkUpdateSilent(
|
||||
url: 'https://api.example.com/check-update',
|
||||
).then((info) {
|
||||
if (info != null && info.hasUpdate) {
|
||||
// 发现更新,显示提示
|
||||
showUpdateNotification(context, info);
|
||||
}
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 定期检查
|
||||
```dart
|
||||
// 推荐:每日检查一次
|
||||
Timer.periodic(const Duration(days: 1), (_) {
|
||||
AppUpgradeSimple.instance.checkUpdateSilent(
|
||||
url: 'https://api.example.com/check-update',
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
### 3. 用户手动检查
|
||||
```dart
|
||||
// 推荐:提供手动检查按钮
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
AppUpgradeSimple.instance.checkUpdate(
|
||||
context: context,
|
||||
url: 'https://api.example.com/check-update',
|
||||
);
|
||||
},
|
||||
child: const Text('检查更新'),
|
||||
)
|
||||
```
|
||||
|
||||
## 🎯 完整示例
|
||||
|
||||
查看 `example/lib/main_enhanced.dart` 获取完整的使用示例,包含所有功能的演示。
|
||||
|
||||
## 📝 API文档
|
||||
|
||||
### 主要方法
|
||||
|
||||
#### `checkUpdate()`
|
||||
检查并处理应用更新的主要方法。
|
||||
|
||||
#### `checkUpdateSilent()`
|
||||
静默检查更新,不显示UI。
|
||||
|
||||
#### `preDownloadApk()`
|
||||
后台预下载APK文件。
|
||||
|
||||
#### `clearDownloadCache()`
|
||||
清理下载缓存。
|
||||
|
||||
#### `checkNetworkStatus()`
|
||||
检查网络连接状态。
|
||||
|
||||
### 配置类
|
||||
|
||||
#### `UpgradeConfig`
|
||||
升级配置类,控制插件的行为。
|
||||
|
||||
#### 预设配置
|
||||
- `UpgradeConfig.auto` - 自动更新
|
||||
- `UpgradeConfig.silent` - 静默检查
|
||||
- `UpgradeConfig.development` - 开发模式
|
||||
- `UpgradeConfig.production` - 生产模式
|
||||
|
||||
---
|
||||
|
||||
这个插件现在提供了完整的应用升级解决方案,支持各种使用场景和自定义需求!
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -37,10 +37,146 @@ class _SimpleAppUpgradePlugin {
|
|||
Future<Map<String, String>> getAppInfo() {
|
||||
return AppUpgradePluginPlatform.instance.getAppInfo();
|
||||
}
|
||||
|
||||
/// 检查当前应用的版本信息(用于安装状态检测)
|
||||
Future<Map<String, String>> getCurrentAppInfo() async {
|
||||
try {
|
||||
return await AppUpgradePluginPlatform.instance.getAppInfo();
|
||||
} catch (e) {
|
||||
debugPrint('获取应用信息失败: $e');
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取下载路径
|
||||
Future<String?> getDownloadPath() {
|
||||
return AppUpgradePluginPlatform.instance.getDownloadPath();
|
||||
}
|
||||
|
||||
/// 精确检测应用是否已安装(通过包名)
|
||||
Future<bool> isPackageInstalled(String packageName) async {
|
||||
try {
|
||||
// 通过比较当前应用的包名来检测
|
||||
final appInfo = await getAppInfo();
|
||||
final currentPackage = appInfo['packageName'] ?? '';
|
||||
|
||||
debugPrint('检查包安装状态: 当前包名=$currentPackage, 目标包名=$packageName');
|
||||
|
||||
// 如果是检查当前应用的安装状态,通过版本号变化来判断
|
||||
if (currentPackage == packageName) {
|
||||
return true; // 当前应用肯定已安装
|
||||
}
|
||||
|
||||
return false;
|
||||
} catch (e) {
|
||||
debugPrint('检查包安装状态失败: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 比较版本号是否已更新
|
||||
Future<bool> isVersionUpdated(String targetVersion, int? targetBuildNumber) async {
|
||||
try {
|
||||
final appInfo = await getCurrentAppInfo();
|
||||
final currentVersion = appInfo['version'] ?? '';
|
||||
final currentBuildNumber = int.tryParse(appInfo['buildNumber'] ?? '0') ?? 0;
|
||||
|
||||
debugPrint('版本对比: 当前版本=$currentVersion, 目标版本=$targetVersion');
|
||||
debugPrint('构建号对比: 当前构建号=$currentBuildNumber, 目标构建号=$targetBuildNumber');
|
||||
|
||||
// 优先比较构建号(更准确)
|
||||
if (targetBuildNumber != null && targetBuildNumber > 0) {
|
||||
return currentBuildNumber >= targetBuildNumber;
|
||||
}
|
||||
|
||||
// 备用方案:比较版本号
|
||||
return currentVersion == targetVersion;
|
||||
} catch (e) {
|
||||
debugPrint('版本对比失败: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 升级配置选项
|
||||
class UpgradeConfig {
|
||||
/// 是否显示无更新提示
|
||||
final bool showNoUpdateToast;
|
||||
|
||||
/// 是否自动下载
|
||||
final bool autoDownload;
|
||||
|
||||
/// 是否自动安装
|
||||
final bool autoInstall;
|
||||
|
||||
/// 连接超时时间(秒)
|
||||
final int connectionTimeout;
|
||||
|
||||
/// 下载超时时间(秒)
|
||||
final int downloadTimeout;
|
||||
|
||||
/// 安装检测超时时间(秒)
|
||||
final int installTimeout;
|
||||
|
||||
/// 是否启用调试日志
|
||||
final bool enableDebugLog;
|
||||
|
||||
/// 自定义Toast显示函数
|
||||
final void Function(String message)? customToast;
|
||||
|
||||
const UpgradeConfig({
|
||||
this.showNoUpdateToast = true,
|
||||
this.autoDownload = false,
|
||||
this.autoInstall = false,
|
||||
this.connectionTimeout = 30,
|
||||
this.downloadTimeout = 300,
|
||||
this.installTimeout = 45,
|
||||
this.enableDebugLog = true,
|
||||
this.customToast,
|
||||
});
|
||||
|
||||
/// 快速配置:自动更新
|
||||
static const UpgradeConfig auto = UpgradeConfig(
|
||||
autoDownload: true,
|
||||
autoInstall: true,
|
||||
);
|
||||
|
||||
/// 快速配置:静默检查
|
||||
static const UpgradeConfig silent = UpgradeConfig(
|
||||
showNoUpdateToast: false,
|
||||
enableDebugLog: false,
|
||||
);
|
||||
|
||||
/// 快速配置:开发模式(详细日志 + 较短超时)
|
||||
static const UpgradeConfig development = UpgradeConfig(
|
||||
enableDebugLog: true,
|
||||
installTimeout: 30,
|
||||
connectionTimeout: 10,
|
||||
);
|
||||
|
||||
/// 快速配置:生产模式(静默 + 较长超时)
|
||||
static const UpgradeConfig production = UpgradeConfig(
|
||||
showNoUpdateToast: false,
|
||||
enableDebugLog: false,
|
||||
installTimeout: 60,
|
||||
connectionTimeout: 30,
|
||||
);
|
||||
}
|
||||
|
||||
/// 简化版App升级管理器
|
||||
/// 提供最简单的API,一行代码即可实现App升级功能
|
||||
///
|
||||
/// 版本: 2.0.0
|
||||
/// 更新日期: 2025-09-18
|
||||
///
|
||||
/// 主要特性:
|
||||
/// - 🎨 现代化UI设计,支持Material Design 3
|
||||
/// - 🔄 智能安装状态检测,支持多种安装场景
|
||||
/// - 📱 完整的生命周期管理和错误处理
|
||||
/// - ⚙️ 灵活的配置系统,支持多种使用模式
|
||||
/// - 🎯 富文本支持,更好的内容展示
|
||||
/// - 🚀 高性能,低内存占用
|
||||
/// - 🛡️ 完善的权限处理和安全检查
|
||||
class AppUpgradeSimple {
|
||||
static AppUpgradeSimple? _instance;
|
||||
|
||||
|
|
@ -61,10 +197,60 @@ class AppUpgradeSimple {
|
|||
AppUpgradeSimple._() : _plugin = _SimpleAppUpgradePlugin.instance;
|
||||
|
||||
final _SimpleAppUpgradePlugin _plugin;
|
||||
UpgradeConfig _config = const UpgradeConfig();
|
||||
|
||||
/// 配置升级参数
|
||||
void configure(UpgradeConfig config) {
|
||||
_config = config;
|
||||
}
|
||||
|
||||
/// 快速配置:一键设置自动更新
|
||||
void enableAutoUpdate() {
|
||||
_config = UpgradeConfig.auto;
|
||||
}
|
||||
|
||||
/// 快速配置:一键设置静默检查
|
||||
void enableSilentCheck() {
|
||||
_config = UpgradeConfig.silent;
|
||||
}
|
||||
|
||||
/// 检查网络连接状态
|
||||
Future<bool> checkNetworkStatus() async {
|
||||
try {
|
||||
final result = await InternetAddress.lookup('google.com');
|
||||
return result.isNotEmpty && result[0].rawAddress.isNotEmpty;
|
||||
} catch (e) {
|
||||
debugPrint('网络检查失败: $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 清理下载的临时文件
|
||||
Future<void> clearDownloadCache() async {
|
||||
try {
|
||||
final downloadPath = await _plugin.getDownloadPath();
|
||||
if (downloadPath != null) {
|
||||
final dir = Directory(downloadPath);
|
||||
if (await dir.exists()) {
|
||||
final files = await dir.list().where((file) => file.path.endsWith('.apk')).toList();
|
||||
for (final file in files) {
|
||||
try {
|
||||
await file.delete();
|
||||
debugPrint('已删除缓存文件: ${file.path}');
|
||||
} catch (e) {
|
||||
debugPrint('删除缓存文件失败: ${file.path}, 错误: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('清理下载缓存失败: $e');
|
||||
}
|
||||
}
|
||||
|
||||
/// 一键检查更新(最简单的使用方式)
|
||||
///
|
||||
/// 示例:
|
||||
/// 基础用法:
|
||||
/// ```dart
|
||||
/// AppUpgradeSimple.instance.checkUpdate(
|
||||
/// context: context,
|
||||
|
|
@ -72,25 +258,64 @@ class AppUpgradeSimple {
|
|||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// 高级用法:
|
||||
/// ```dart
|
||||
/// // 配置自动更新
|
||||
/// AppUpgradeSimple.instance.configure(UpgradeConfig.auto);
|
||||
///
|
||||
/// // 或者使用自定义配置
|
||||
/// AppUpgradeSimple.instance.configure(UpgradeConfig(
|
||||
/// autoDownload: true,
|
||||
/// autoInstall: false,
|
||||
/// installTimeout: 60,
|
||||
/// customToast: (message) => ScaffoldMessenger.of(context).showSnackBar(
|
||||
/// SnackBar(content: Text(message)),
|
||||
/// ),
|
||||
/// ));
|
||||
///
|
||||
/// // 检查更新
|
||||
/// await AppUpgradeSimple.instance.checkUpdate(
|
||||
/// context: context,
|
||||
/// url: 'https://api.example.com/check-update',
|
||||
/// params: {'userId': '123', 'channel': 'official'},
|
||||
/// onComplete: () => print('更新检查完成'),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// [context] 需要是一个能够访问到 `Navigator` 和 `MaterialLocalizations` 的有效上下文。
|
||||
/// 如果您不确定,建议在 `init` 方法中提供 `navigatorKey`,这样插件可以获取一个可靠的上下文。
|
||||
/// [url] 检查更新的API接口地址
|
||||
/// [params] 可选的请求参数
|
||||
/// [config] 可选的配置覆盖
|
||||
/// [onComplete] 更新流程完成后的回调
|
||||
/// 一键检查更新(支持配置)
|
||||
Future<void> checkUpdate({
|
||||
required BuildContext context,
|
||||
required String url,
|
||||
Map<String, dynamic>? params,
|
||||
bool showNoUpdateToast = true,
|
||||
bool autoDownload = false,
|
||||
bool autoInstall = false,
|
||||
bool? showNoUpdateToast,
|
||||
bool? autoDownload,
|
||||
bool? autoInstall,
|
||||
VoidCallback? onComplete,
|
||||
UpgradeConfig? config,
|
||||
}) async {
|
||||
// 使用传入的配置或默认配置
|
||||
final effectiveConfig = config ?? _config;
|
||||
final finalShowNoUpdateToast = showNoUpdateToast ?? effectiveConfig.showNoUpdateToast;
|
||||
final finalAutoDownload = autoDownload ?? effectiveConfig.autoDownload;
|
||||
final finalAutoInstall = autoInstall ?? effectiveConfig.autoInstall;
|
||||
try {
|
||||
assert(_canShowMaterialDialog(context), '请在 MaterialApp 环境内调用');
|
||||
|
||||
// 检查更新
|
||||
final info = await _plugin.checkUpdate(url, params: params);
|
||||
print('info: $info');
|
||||
if (effectiveConfig.enableDebugLog) {
|
||||
debugPrint('🔍 检查更新结果: $info');
|
||||
}
|
||||
|
||||
if (info == null || !info.hasUpdate) {
|
||||
if (showNoUpdateToast && context.mounted) _showToast('已是最新版本');
|
||||
if (finalShowNoUpdateToast && context.mounted) {
|
||||
_showToast('已是最新版本', effectiveConfig);
|
||||
}
|
||||
onComplete?.call();
|
||||
return;
|
||||
}
|
||||
|
|
@ -98,9 +323,10 @@ class AppUpgradeSimple {
|
|||
await _showUpgradeDialog(
|
||||
context: context,
|
||||
info: info,
|
||||
autoDownload: autoDownload,
|
||||
autoInstall: autoInstall,
|
||||
autoDownload: finalAutoDownload,
|
||||
autoInstall: finalAutoInstall,
|
||||
onComplete: onComplete,
|
||||
config: effectiveConfig,
|
||||
);
|
||||
} catch (e) {
|
||||
debugPrint('检查更新失败: $e');
|
||||
|
|
@ -121,11 +347,13 @@ class AppUpgradeSimple {
|
|||
}
|
||||
|
||||
if (context.mounted) {
|
||||
_showToast(errorMessage);
|
||||
_showToast(errorMessage, effectiveConfig);
|
||||
|
||||
// 如果是网络问题,显示网络诊断建议
|
||||
if (errorString.contains('Failed host lookup') || errorString.contains('无网络连接')) {
|
||||
debugPrint('建议: 请检查网络连接或尝试使用网络诊断功能');
|
||||
if (effectiveConfig.enableDebugLog) {
|
||||
debugPrint('💡 建议: 请检查网络连接或尝试使用网络诊断功能');
|
||||
}
|
||||
}
|
||||
}
|
||||
onComplete?.call();
|
||||
|
|
@ -140,11 +368,60 @@ class AppUpgradeSimple {
|
|||
try {
|
||||
return await _plugin.checkUpdate(url, params: params);
|
||||
} catch (e) {
|
||||
debugPrint('静默检查更新失败: $e');
|
||||
if (_config.enableDebugLog) {
|
||||
debugPrint('静默检查更新失败: $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 预下载APK(不显示UI,后台下载)
|
||||
Future<String?> preDownloadApk({
|
||||
required String url,
|
||||
Function(DownloadProgress)? onProgress,
|
||||
}) async {
|
||||
try {
|
||||
return await _plugin.downloadApk(url, onProgress: onProgress);
|
||||
} catch (e) {
|
||||
if (_config.enableDebugLog) {
|
||||
debugPrint('预下载APK失败: $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查是否有已下载的APK文件
|
||||
Future<String?> findDownloadedApk(String version) async {
|
||||
try {
|
||||
final downloadPath = await _plugin.getDownloadPath();
|
||||
if (downloadPath != null) {
|
||||
final dir = Directory(downloadPath);
|
||||
if (await dir.exists()) {
|
||||
final files = await dir.list().toList();
|
||||
for (final file in files) {
|
||||
if (file.path.contains(version) && file.path.endsWith('.apk')) {
|
||||
final fileEntity = File(file.path);
|
||||
if (await fileEntity.exists()) {
|
||||
return file.path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} catch (e) {
|
||||
if (_config.enableDebugLog) {
|
||||
debugPrint('查找已下载APK失败: $e');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取当前应用版本信息
|
||||
Future<Map<String, String>> getAppInfo() async {
|
||||
return await _plugin.getAppInfo();
|
||||
}
|
||||
|
||||
/// 显示升级对话框
|
||||
Future<void> _showUpgradeDialog({
|
||||
required BuildContext context,
|
||||
|
|
@ -152,20 +429,27 @@ class AppUpgradeSimple {
|
|||
required bool autoDownload,
|
||||
required bool autoInstall,
|
||||
VoidCallback? onComplete,
|
||||
UpgradeConfig? config,
|
||||
}) {
|
||||
final effectiveConfig = config ?? _config;
|
||||
|
||||
return showDialog(
|
||||
context: context,
|
||||
barrierDismissible: !info.isForceUpdate,
|
||||
builder: (context) {
|
||||
if (info.isForceUpdate) {
|
||||
return _ForceUpgradeDialog(info: info);
|
||||
return _ForceUpgradeDialog(
|
||||
info: info,
|
||||
config: effectiveConfig,
|
||||
);
|
||||
} else {
|
||||
return _SimpleUpgradeDialog(
|
||||
info: info,
|
||||
autoDownload: autoDownload,
|
||||
autoInstall: autoInstall,
|
||||
onComplete: onComplete,
|
||||
showToast: (message) => _showToast(message),
|
||||
config: effectiveConfig,
|
||||
showToast: (message) => _showToast(message, effectiveConfig),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
@ -173,8 +457,20 @@ class AppUpgradeSimple {
|
|||
}
|
||||
|
||||
/// 显示Toast提示
|
||||
void _showToast(String message) {
|
||||
Fluttertoast.showToast(msg: message);
|
||||
void _showToast(String message, [UpgradeConfig? config]) {
|
||||
final effectiveConfig = config ?? _config;
|
||||
if (effectiveConfig.customToast != null) {
|
||||
effectiveConfig.customToast!(message);
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: message,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.CENTER,
|
||||
backgroundColor: Colors.black87,
|
||||
textColor: Colors.white,
|
||||
fontSize: 14.0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 检查是否存在可用的 Material 环境(仅用于对话框)
|
||||
|
|
@ -206,6 +502,7 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
VoidCallback? get onComplete;
|
||||
bool get autoDownload;
|
||||
bool get autoInstall;
|
||||
UpgradeConfig get config;
|
||||
|
||||
void initUpgradeLogic() {
|
||||
if (autoDownload && Platform.isAndroid) {
|
||||
|
|
@ -222,13 +519,14 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
}
|
||||
|
||||
void onAppLifecycleStateChanged(AppLifecycleState state) {
|
||||
debugPrint('应用生命周期状态变化: $state, _isWaitingForInstallation=$_isWaitingForInstallation');
|
||||
debugPrint('🔄 应用生命周期状态变化: $state, _isWaitingForInstallation=$_isWaitingForInstallation');
|
||||
|
||||
// 当应用从后台回到前台时,检查是否是从安装界面返回
|
||||
if (state == AppLifecycleState.resumed && _isWaitingForInstallation) {
|
||||
debugPrint('应用回到前台,准备检查安装状态');
|
||||
// 延迟一点时间再检查,确保系统状态稳定
|
||||
Future.delayed(const Duration(milliseconds: 500), () {
|
||||
// 核心逻辑:当应用从后台回到前台时,检查安装状态
|
||||
if (_isWaitingForInstallation && state == AppLifecycleState.resumed) {
|
||||
debugPrint('⚡ 应用回到前台,检查安装状态');
|
||||
|
||||
// 延迟检测,让系统状态稳定
|
||||
Future.delayed(const Duration(milliseconds: 1500), () {
|
||||
if (mounted && _isWaitingForInstallation) {
|
||||
_checkInstallationResult();
|
||||
}
|
||||
|
|
@ -321,7 +619,7 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
_isWaitingForInstallation = true;
|
||||
_statusText = '请完成安装';
|
||||
});
|
||||
showToast('请在系统弹窗中完成安装,如取消可点击下方按钮重试');
|
||||
showToast('请在系统弹窗中完成安装,完成后点击下方确认按钮');
|
||||
|
||||
// 启动定时检测(备用方案)
|
||||
_startInstallationTimeoutCheck();
|
||||
|
|
@ -345,80 +643,98 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
}
|
||||
}
|
||||
|
||||
/// 启动安装超时检测
|
||||
/// 启动简化的安装检测(主要依靠应用生命周期)
|
||||
void _startInstallationTimeoutCheck() {
|
||||
// 5秒后自动检测一次(快速检测)
|
||||
Timer(const Duration(seconds: 5), () {
|
||||
if (mounted && _isWaitingForInstallation && _statusText == '请完成安装') {
|
||||
debugPrint('5秒后自动检测安装状态');
|
||||
_checkInstallationResult();
|
||||
}
|
||||
});
|
||||
debugPrint('🚀 启动简化安装检测系统');
|
||||
|
||||
// 30秒后如果还在等待安装,则提示超时
|
||||
_installCheckTimer = Timer(const Duration(seconds: 30), () {
|
||||
if (mounted && _isWaitingForInstallation && _statusText == '请完成安装') {
|
||||
// 核心策略:主要依靠应用生命周期监听,减少定时检测
|
||||
|
||||
// 仅保留一个简单的超时检测
|
||||
_installCheckTimer = Timer(Duration(seconds: config.installTimeout), () {
|
||||
if (mounted && _isWaitingForInstallation) {
|
||||
debugPrint('⏰ 安装检测超时');
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装超时';
|
||||
});
|
||||
showToast('安装检测超时,请检查是否已安装成功');
|
||||
showToast('安装超时,请使用重试按钮重新安装');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// 检查安装结果(当应用回到前台时调用)
|
||||
/// 简化的安装结果检测(仅版本检测)
|
||||
Future<void> _checkInstallationResult() async {
|
||||
if (!mounted || !_isWaitingForInstallation) {
|
||||
debugPrint('跳过安装结果检查: mounted=$mounted, _isWaitingForInstallation=$_isWaitingForInstallation');
|
||||
return;
|
||||
}
|
||||
|
||||
debugPrint('开始检查安装结果...');
|
||||
debugPrint('🔍 开始简化安装检测...');
|
||||
|
||||
try {
|
||||
// 获取当前应用信息
|
||||
final appInfo = await _plugin.getAppInfo();
|
||||
final currentVersion = appInfo['versionName'] ?? '';
|
||||
final appInfo = await _plugin.getCurrentAppInfo();
|
||||
final currentVersion = appInfo['version'] ?? '';
|
||||
final currentBuildNumber = int.tryParse(appInfo['buildNumber'] ?? '0') ?? 0;
|
||||
|
||||
debugPrint('检查安装结果: 当前版本=$currentVersion, 目标版本=${info.versionName}');
|
||||
debugPrint('📱 当前版本: $currentVersion, 构建号: $currentBuildNumber');
|
||||
debugPrint('🎯 目标版本: ${info.versionName}, 构建号: ${info.versionBuildNumber}');
|
||||
|
||||
// 如果版本号已更新,说明安装成功
|
||||
if (currentVersion == info.versionName) {
|
||||
debugPrint('检测到版本已更新,安装成功');
|
||||
_installCheckTimer?.cancel();
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装成功';
|
||||
});
|
||||
showToast('应用更新成功!');
|
||||
|
||||
// 延迟关闭对话框
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
if (mounted && Navigator.canPop(context)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
onComplete?.call();
|
||||
});
|
||||
// 优先比较构建号(更准确)
|
||||
bool isUpdated = false;
|
||||
if (info.versionBuildNumber > 0) {
|
||||
isUpdated = currentBuildNumber >= info.versionBuildNumber;
|
||||
debugPrint('📊 构建号比较: $currentBuildNumber >= ${info.versionBuildNumber} = $isUpdated');
|
||||
} else {
|
||||
// 版本号未更新,用户可能取消了安装
|
||||
debugPrint('版本号未更新,用户可能取消了安装');
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装被取消';
|
||||
});
|
||||
showToast('安装被取消,可以重新尝试安装');
|
||||
// 备用方案:比较版本号
|
||||
isUpdated = currentVersion == info.versionName;
|
||||
debugPrint('📊 版本号比较: $currentVersion == ${info.versionName} = $isUpdated');
|
||||
}
|
||||
|
||||
if (isUpdated) {
|
||||
debugPrint('✅ 检测结果: 安装成功');
|
||||
_handleInstallationSuccess();
|
||||
} else {
|
||||
debugPrint('❌ 检测结果: 安装被取消(版本未更新)');
|
||||
_handleInstallationCancelled();
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('检测应用状态失败: $e');
|
||||
debugPrint('❌ 检测失败: $e');
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '检测失败';
|
||||
});
|
||||
showToast('无法检测安装状态,请手动检查');
|
||||
showToast('无法检测安装状态,请手动确认');
|
||||
}
|
||||
}
|
||||
|
||||
/// 处理安装成功
|
||||
void _handleInstallationSuccess() {
|
||||
_installCheckTimer?.cancel();
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装成功';
|
||||
});
|
||||
showToast('应用更新成功!');
|
||||
|
||||
// 延迟关闭对话框
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
if (mounted && Navigator.canPop(context)) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
onComplete?.call();
|
||||
});
|
||||
}
|
||||
|
||||
/// 处理安装被取消
|
||||
void _handleInstallationCancelled() {
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装被取消';
|
||||
});
|
||||
showToast('安装被取消,可以点击重试按钮重新安装');
|
||||
}
|
||||
|
||||
/// 重新安装APK
|
||||
Future<void> _retryInstall() async {
|
||||
if (_downloadedFilePath != null) {
|
||||
|
|
@ -842,16 +1158,21 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
// 下载状态图标和文本
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
padding: const EdgeInsets.all(8),
|
||||
decoration: BoxDecoration(
|
||||
color: _getStatusColor(colorScheme).withOpacity(0.1),
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
_getStatusIcon(),
|
||||
color: _getStatusColor(colorScheme),
|
||||
size: 20,
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: Icon(
|
||||
_getStatusIcon(),
|
||||
key: ValueKey(_statusText),
|
||||
color: _getStatusColor(colorScheme),
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
|
|
@ -859,12 +1180,16 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
_statusText,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: colorScheme.onSurface,
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
child: Text(
|
||||
_statusText,
|
||||
key: ValueKey(_statusText),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: colorScheme.onSurface,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 2),
|
||||
|
|
@ -878,81 +1203,56 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
),
|
||||
),
|
||||
// 添加点击提示(当有错误状态或等待用户操作时)
|
||||
if (showRetryButton &&
|
||||
(_statusText == '安装失败' ||
|
||||
_statusText == '安装异常' ||
|
||||
_statusText == '权限被拒绝' ||
|
||||
_statusText == '请完成安装' ||
|
||||
_statusText == '安装超时' ||
|
||||
_statusText == '安装被取消' ||
|
||||
_statusText == '检测失败'))
|
||||
if (_shouldShowRetryOptions())
|
||||
Text(
|
||||
_statusText == '请完成安装' ? '可重新启动安装' : '点击区域重试',
|
||||
_getClickHintText(),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: colorScheme.onSurface.withOpacity(0.6),
|
||||
),
|
||||
),
|
||||
// 为"请完成安装"状态添加操作按钮
|
||||
// 为"请完成安装"状态添加简单提示
|
||||
if (_statusText == '请完成安装')
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: _checkInstallationResult,
|
||||
icon: const Icon(Icons.refresh, size: 14),
|
||||
label: const Text('检查状态', style: TextStyle(fontSize: 11)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: colorScheme.secondary.withOpacity(0.8),
|
||||
),
|
||||
),
|
||||
padding: const EdgeInsets.only(top: 12),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: colorScheme.primaryContainer.withOpacity(0.2),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(
|
||||
color: colorScheme.primary.withOpacity(0.3),
|
||||
width: 1,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () async {
|
||||
// 直接重新安装,不检查状态
|
||||
if (_downloadedFilePath != null) {
|
||||
await _installApk(_downloadedFilePath!);
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.install_mobile, size: 14),
|
||||
label: const Text('重新安装', style: TextStyle(fontSize: 11)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: colorScheme.primary,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Icon(
|
||||
Icons.touch_app,
|
||||
color: colorScheme.primary,
|
||||
size: 24,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
// 测试按钮:模拟取消安装
|
||||
Expanded(
|
||||
child: ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_isWaitingForInstallation = false;
|
||||
_statusText = '安装被取消';
|
||||
});
|
||||
showToast('已模拟安装被取消,现在应该显示重试按钮');
|
||||
},
|
||||
icon: const Icon(Icons.cancel, size: 14),
|
||||
label: const Text('模拟取消', style: TextStyle(fontSize: 10)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
|
||||
minimumSize: Size.zero,
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: colorScheme.error.withOpacity(0.8),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'请在系统安装界面完成操作',
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
color: colorScheme.onSurface,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'系统将自动检测安装结果',
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
color: colorScheme.onSurface.withOpacity(0.7),
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
|
@ -1046,6 +1346,12 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
return Icons.check_circle;
|
||||
} else if (_statusText == '请完成安装') {
|
||||
return Icons.touch_app;
|
||||
} else if (_statusText == '等待安装中') {
|
||||
return Icons.hourglass_bottom;
|
||||
} else if (_statusText == '等待确认中') {
|
||||
return Icons.help_outline;
|
||||
} else if (_statusText == '等待超时') {
|
||||
return Icons.timer_off;
|
||||
} else if (_statusText == '安装被取消') {
|
||||
return Icons.cancel_outlined;
|
||||
} else if (_statusText == '安装超时' || _statusText == '检测失败') {
|
||||
|
|
@ -1067,6 +1373,12 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
return colorScheme.tertiary;
|
||||
} else if (_statusText == '请完成安装') {
|
||||
return colorScheme.secondary;
|
||||
} else if (_statusText == '等待安装中') {
|
||||
return colorScheme.secondary.withOpacity(0.9);
|
||||
} else if (_statusText == '等待确认中') {
|
||||
return Colors.orange;
|
||||
} else if (_statusText == '等待超时') {
|
||||
return colorScheme.error.withOpacity(0.7);
|
||||
} else if (_statusText == '安装被取消') {
|
||||
return colorScheme.secondary.withOpacity(0.8);
|
||||
} else if (_statusText == '安装超时' || _statusText == '检测失败') {
|
||||
|
|
@ -1088,7 +1400,10 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
_statusText == '安装异常' ||
|
||||
_statusText == '安装超时' ||
|
||||
_statusText == '安装被取消' ||
|
||||
_statusText == '检测失败') {
|
||||
_statusText == '检测失败' ||
|
||||
_statusText == '等待安装中' ||
|
||||
_statusText == '等待确认中' ||
|
||||
_statusText == '等待超时') {
|
||||
return Icons.refresh;
|
||||
} else if (_statusText == '请完成安装') {
|
||||
return Icons.launch;
|
||||
|
|
@ -1105,8 +1420,11 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
_statusText == '安装异常' ||
|
||||
_statusText == '安装超时' ||
|
||||
_statusText == '安装被取消' ||
|
||||
_statusText == '检测失败') {
|
||||
_statusText == '检测失败' ||
|
||||
_statusText == '等待超时') {
|
||||
return '重试';
|
||||
} else if (_statusText == '等待安装中' || _statusText == '等待确认中') {
|
||||
return '重新安装';
|
||||
} else if (_statusText == '请完成安装') {
|
||||
return '重新安装';
|
||||
} else {
|
||||
|
|
@ -1120,7 +1438,7 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
return colorScheme.secondary;
|
||||
} else if (_statusText == '安装失败' || _statusText == '安装异常') {
|
||||
return colorScheme.error;
|
||||
} else if (_statusText == '安装超时' || _statusText == '安装被取消' || _statusText == '检测失败') {
|
||||
} else if (_statusText == '安装超时' || _statusText == '安装被取消' || _statusText == '检测失败' || _statusText == '等待安装中') {
|
||||
return colorScheme.secondary.withOpacity(0.8);
|
||||
} else if (_statusText == '请完成安装') {
|
||||
return colorScheme.secondary;
|
||||
|
|
@ -1137,6 +1455,9 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
_statusText == '权限被拒绝' ||
|
||||
_statusText == '安装超时' ||
|
||||
_statusText == '检测失败' ||
|
||||
_statusText == '等待安装中' ||
|
||||
_statusText == '等待确认中' ||
|
||||
_statusText == '等待超时' ||
|
||||
(_downloadedFilePath != null &&
|
||||
!_isDownloading &&
|
||||
!_isInstalling &&
|
||||
|
|
@ -1145,6 +1466,28 @@ mixin _UpgradeDialogLogic<T extends StatefulWidget> on State<T> {
|
|||
_statusText != '安装成功');
|
||||
}
|
||||
|
||||
/// 获取点击提示文本
|
||||
String _getClickHintText() {
|
||||
switch (_statusText) {
|
||||
case '请完成安装':
|
||||
return '完成后请点击确认按钮';
|
||||
case '等待安装中':
|
||||
return '点击重新安装';
|
||||
case '等待确认中':
|
||||
return '请点击确认按钮';
|
||||
case '等待超时':
|
||||
return '点击重新安装';
|
||||
case '安装被取消':
|
||||
return '点击重新安装';
|
||||
case '权限被拒绝':
|
||||
return '点击打开设置';
|
||||
case '安装超时':
|
||||
return '点击重新尝试';
|
||||
default:
|
||||
return '点击区域重试';
|
||||
}
|
||||
}
|
||||
|
||||
void _handleAction() {
|
||||
if (Platform.isAndroid) {
|
||||
_handleAndroidAction();
|
||||
|
|
@ -1341,6 +1684,7 @@ class _SimpleUpgradeDialog extends StatefulWidget {
|
|||
final bool autoInstall;
|
||||
final VoidCallback? onComplete;
|
||||
final void Function(String) showToast;
|
||||
final UpgradeConfig config;
|
||||
|
||||
const _SimpleUpgradeDialog({
|
||||
required this.info,
|
||||
|
|
@ -1348,6 +1692,7 @@ class _SimpleUpgradeDialog extends StatefulWidget {
|
|||
required this.autoInstall,
|
||||
this.onComplete,
|
||||
required this.showToast,
|
||||
required this.config,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -1365,6 +1710,8 @@ class _SimpleUpgradeDialogState extends State<_SimpleUpgradeDialog> with _Upgrad
|
|||
bool get autoDownload => widget.autoDownload;
|
||||
@override
|
||||
bool get autoInstall => widget.autoInstall;
|
||||
@override
|
||||
UpgradeConfig get config => widget.config;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -1477,8 +1824,12 @@ class _SimpleUpgradeDialogState extends State<_SimpleUpgradeDialog> with _Upgrad
|
|||
/// 强制更新对话框
|
||||
class _ForceUpgradeDialog extends StatefulWidget {
|
||||
final UpgradeInfo info;
|
||||
final UpgradeConfig config;
|
||||
|
||||
const _ForceUpgradeDialog({required this.info});
|
||||
const _ForceUpgradeDialog({
|
||||
required this.info,
|
||||
required this.config,
|
||||
});
|
||||
|
||||
@override
|
||||
State<_ForceUpgradeDialog> createState() => _ForceUpgradeDialogState();
|
||||
|
|
@ -1488,13 +1839,15 @@ class _ForceUpgradeDialogState extends State<_ForceUpgradeDialog> with _UpgradeD
|
|||
@override
|
||||
UpgradeInfo get info => widget.info;
|
||||
@override
|
||||
void Function(String) get showToast => (message) => AppUpgradeSimple.instance._showToast(message);
|
||||
void Function(String) get showToast => (message) => AppUpgradeSimple.instance._showToast(message, widget.config);
|
||||
@override
|
||||
VoidCallback? get onComplete => null;
|
||||
@override
|
||||
bool get autoDownload => false;
|
||||
@override
|
||||
bool get autoInstall => true;
|
||||
@override
|
||||
UpgradeConfig get config => widget.config;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue