import 'package:cashier_reserve/common/print/print.dart'; import 'package:cashier_reserve/data_model/version/update_version_model.dart'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_app_installer/flutter_app_installer.dart'; import 'package:path_provider/path_provider.dart'; import 'package:percent_indicator/percent_indicator.dart'; class UpdateVersionView extends StatefulWidget { final UpdateVersionModel versionModel; const UpdateVersionView({super.key, required this.versionModel}); @override State createState() { return _UpdateVersionViewState(); } } class _UpdateVersionViewState extends State { DateTime? lastPopTime; double progress = 0; String progressText = "0%"; bool isDownload = false; // 用于控制下载任务取消的CancelToken CancelToken? _cancelToken; @override void dispose() { _cancelToken?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return PopScope( canPop: (widget.versionModel.isUp ?? 0) != 0, onPopInvokedWithResult: (didPop, result) async { // 点击返回键的操作 if (lastPopTime == null || DateTime.now().difference(lastPopTime!) > const Duration(seconds: 2)) { lastPopTime = DateTime.now(); // Utils.toast('再按一次退出', context); } else { lastPopTime = DateTime.now(); // 退出app await SystemChannels.platform.invokeMethod('SystemNavigator.pop'); } }, child: Scaffold( backgroundColor: Colors.black.withOpacity(0.2), body: GestureDetector( onTap: () { FocusScope.of(context).requestFocus(FocusNode()); }, child: Container( width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, color: const Color(0x55000000), child: Center( child: Container( padding: const EdgeInsets.fromLTRB(30, 30, 30, 30), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(10), ), width: 400, // height: 400, child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( "发现新版本", style: TextStyle(fontSize: 22, color: Color(0xff333333)), ), const SizedBox( height: 20, ), Text( widget.versionModel.message ?? "", style: const TextStyle( fontSize: 16, color: Color(0xff666666)), ), const SizedBox( height: 20, ), isDownload ? LinearPercentIndicator( padding: EdgeInsets.zero, animation: false, lineHeight: 20.0, // animationDuration: 2500, percent: progress, center: Text(progressText), // linearStrokeCap: LinearStrokeCap.roundAll, progressColor: Colors.green, ) : Container(), isDownload ? const SizedBox( height: 20, ) : Container(), _buildActionViews(context), ], ), ), ), ), ), ), ), ); } Widget _buildActionViews(BuildContext context) { bool isMustUpdate = widget.versionModel.isUp == 1; return Row(mainAxisAlignment: MainAxisAlignment.center, children: [ isMustUpdate ? Container() : ElevatedButton( onPressed: () { Navigator.of(context).pop(); }, style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Colors.white), foregroundColor: WidgetStateProperty.all(const Color(0xff666666)), minimumSize: WidgetStateProperty.all(const Size(100, 40)), shape: WidgetStateProperty.all(const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(20)), )), ), child: const Text("跳过"), ), isMustUpdate ? Container() : const SizedBox( width: 20, ), ElevatedButton( onPressed: () { startDownload(); }, style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Colors.blue), foregroundColor: WidgetStateProperty.all(Colors.white), minimumSize: WidgetStateProperty.all(Size(isMustUpdate ? 200 : 100, 40)), shape: WidgetStateProperty.all(const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(20)), )), ), child: const Text("立即更新"), ), ]); } startDownload() async { setState(() { isDownload = true; }); String fileUrl = widget.versionModel.url ?? ""; if (fileUrl.isEmpty) { yjPrint("下载地址为空"); return; } _cancelToken?.cancel(); setState(() { progress = 0.0; progressText = "0.0%"; }); yjPrint("fileUrl: $fileUrl"); Dio dio = Dio(); try { String savePath = await getPhoneLocalPath(); String appName = "file.apk"; _cancelToken = CancelToken(); // 创建CancelToken对象 await dio.download( fileUrl, "$savePath$appName", onReceiveProgress: (received, total) { if (total != -1) { ///当前下载的百分比例 double currentProgress = received / total; setState(() { progressText = "${(currentProgress * 100).toStringAsFixed(2)}%"; progress = double.parse(currentProgress.toStringAsFixed(2)); }); yjPrint(progressText); } }, cancelToken: _cancelToken); yjPrint("文件下载成功"); _cancelToken = null; installApk("$savePath$appName"); } catch (e) { yjPrint("文件下载失败:$e"); } } Future getPhoneLocalPath() async { final directory = await getExternalStorageDirectory(); return directory?.path ?? ''; } installApk(String apkPath) async { final FlutterAppInstaller flutterAppInstaller = FlutterAppInstaller(); flutterAppInstaller.installApk( filePath: apkPath, ); } }