import 'package:flutter/material.dart'; import 'package:url_launcher/url_launcher.dart'; /// 强制更新页:检测到新版本时的全屏阻塞页。 /// PopScope 禁返回(Android 系统返回 / iOS 边缘滑动均不可退出)。 /// 2026-09-03 改为浏览器下载:App 内 PackageInstaller 会话安装在小米等 /// ROM 上点系统确认框后失败(下载/写入正常但最终安装被拒),而系统浏览器 /// 下载 APK 后经通知栏走 ROM 自己的安装器可正常完成,故下载链接改由浏览器 /// 打开,不再 App 内下载/安装。仅点「立即更新」按钮时打开浏览器,不自动 /// 跳转;安装完成(versionName 追上服务器)后下次启动不再提示。 class UpdateScreen extends StatefulWidget { final String version; final String url; final String notes; const UpdateScreen({ super.key, required this.version, required this.url, this.notes = '', }); @override State createState() => _UpdateScreenState(); } class _UpdateScreenState extends State { String? _message; Future _openBrowser() async { final uri = Uri.tryParse(widget.url); if (uri == null) { setState(() => _message = '下载链接无效,请联系管理员'); return; } try { final ok = await launchUrl(uri, mode: LaunchMode.externalApplication); if (!mounted) return; setState(() { _message = ok ? '已打开浏览器下载,完成后点击通知栏的安装提示即可更新' : '打开浏览器失败,请点「立即更新」重试'; }); } catch (_) { if (!mounted) return; setState(() => _message = '打开浏览器失败,请点「立即更新」重试'); } } @override Widget build(BuildContext context) { final theme = Theme.of(context); return PopScope( canPop: false, child: Scaffold( body: Center( child: Padding( padding: const EdgeInsets.all(32), child: Column( mainAxisSize: MainAxisSize.min, children: [ Icon(Icons.system_update_alt, size: 64, color: theme.colorScheme.primary), const SizedBox(height: 16), Text('发现新版本 ${widget.version}', style: theme.textTheme.headlineSmall), const SizedBox(height: 12), if (widget.notes.isNotEmpty) Text(widget.notes, textAlign: TextAlign.center, style: const TextStyle(height: 1.6)), const SizedBox(height: 24), FilledButton.icon( onPressed: _openBrowser, icon: const Icon(Icons.open_in_browser), label: const Text('立即更新'), style: FilledButton.styleFrom( minimumSize: const Size(200, 48), textStyle: const TextStyle(fontSize: 16), ), ), const SizedBox(height: 16), Text( '新版本需在浏览器下载 APK 后手动安装\n安装完成后请重新打开应用', textAlign: TextAlign.center, style: theme.textTheme.bodySmall ?.copyWith(color: theme.colorScheme.error), ), if (_message != null) ...[ const SizedBox(height: 12), Text( _message!, textAlign: TextAlign.center, style: TextStyle( height: 1.5, color: _message!.startsWith('已打开') ? Colors.green : theme.colorScheme.error, ), ), ], ], ), ), ), ), ); } }