import 'dart:io'; import 'package:apk_update/utils/image_utils.dart'; import 'package:dio/dio.dart'; import 'package:flustars_flutter3/flustars_flutter3.dart'; import 'package:flutter/material.dart'; class UpdateDialog extends StatefulWidget { final String? title; // 升级版本 final String? content; // 升级内容 final bool isUpdateMore; // 是否强升 final String? versionPath; // apk 路径 final Function()? jumpAppStore; // 跳转AppStore final Function(String? path)? installApk; // 安装Apk final Function()? downloadApkError; // 下载Apk错误 const UpdateDialog({ Key? key, this.title, this.content, this.isUpdateMore = false, this.versionPath, this.jumpAppStore, this.installApk, this.downloadApkError, }) : super(key: key); @override State<UpdateDialog> createState() => _UpdateDialogState(); } class _UpdateDialogState extends State<UpdateDialog> { final CancelToken _cancelToken = CancelToken(); bool _isDownload = false; double _value = 0; @override void dispose() { if (!_cancelToken.isCancelled && _value != 1) { _cancelToken.cancel(); } super.dispose(); } @override Widget build(BuildContext context) { return WillPopScope( onWillPop: () => Future.value(false), //使用false禁止返回键返回,达到强制升级目的 child: Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, body: Center( child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(8.0), ), width: 280.0, child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ // 顶部图片 _topImage(), Padding( padding: const EdgeInsets.symmetric(horizontal: 15.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 标题 _content(title: widget.title, content: widget.content), _isDownload // 下载进度 ? LinearProgressIndicator( backgroundColor: const Color(0xFFF2F3F3), value: _value, ) // 按钮 : Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: <Widget>[ Offstage( offstage: widget.isUpdateMore, child: _btn( title: '残忍拒绝', textColor: Theme.of(context).primaryColor, bgColor: Colors.transparent, onTap: () => Navigator.pop(context), ), ), _btn( title: '立即更新', onTap: () { if (Platform.isIOS) { Navigator.pop(context); widget.jumpAppStore?.call(); } else { setState(() { _isDownload = true; }); _download(); } }, ) ], ), const SizedBox(height: 15.0), ], ), ), ], ), ), ), ), ); } /// 顶部图片 Widget _topImage() => Container( height: 140.0, width: 280.0, decoration: BoxDecoration( borderRadius: const BorderRadius.only( topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), ), image: DecorationImage( image: ImageUtils.getAssetImage('update_head'), fit: BoxFit.cover, ), ), ); /// 标题、内容 Widget _content({String? title, String? content}) => Column( children: [ const SizedBox(height: 15.0), // 标题 Text( title ?? "", style: const TextStyle( fontSize: 15.0, color: Color(0xFF333C4C), ), ), const SizedBox(height: 5.0), // 内容 Text( content ?? "", style: const TextStyle(fontSize: 15.0, color: Color(0xFF4E5969)), ), const SizedBox(height: 15.0), ], ); /// 按钮 Widget _btn({ String? title, GestureTapCallback? onTap, Color? textColor, Color? bgColor, }) => InkWell( onTap: onTap, child: Container( width: 110.0, constraints: const BoxConstraints(minHeight: 36.0), alignment: Alignment.center, decoration: BoxDecoration( color: bgColor ?? Theme.of(context).primaryColor, borderRadius: BorderRadius.circular(20.0), border: Border.all(color: Theme.of(context).primaryColor), ), child: Text( title ?? "", style: TextStyle(fontSize: 15.0, color: textColor ?? Colors.white), ), ), ); ///下载apk Future<void> _download() async { try { setInitDir(initStorageDir: true); await DirectoryUtil.getInstance(); DirectoryUtil.createStorageDirSync(category: 'apk'); String path = DirectoryUtil.getStoragePath( fileName: 'clx_update', category: 'Download', format: 'apk')!; File file = File(path); /// 链接可能会失效 await Dio().download( widget.versionPath!, file.path, cancelToken: _cancelToken, onReceiveProgress: (int count, int total) { if (total != -1) { _value = count / total; setState(() {}); if (count == total) { Navigator.pop(context); widget.installApk?.call(path); } } }, ); } catch (e) { widget.downloadApkError?.call(); debugPrint("e: $e"); setState(() { _isDownload = false; }); } } }