import 'dart:async'; import 'dart:io'; ///https://blog.csdn.net/zcylyzhi4/article/details/108002879 ///1、导入相关包 import 'dart:isolate'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_downloader/flutter_downloader.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:hyzp_ybqx/components/dioFun.dart'; import 'package:open_file/open_file.dart'; import 'package:path_provider/path_provider.dart'; import 'package:progress_dialog/progress_dialog.dart'; import '../../../components/commonFun.dart'; ///版本更新类 class MyUpdatedNew { MyUpdatedNew( {this.ver, this.date, this.theContext, this.bStartUpdated = false, this.bShowNoNewVersion = false}) { initState(); } String ver = '1.0.0'; String date = ''; BuildContext theContext; bool bStartUpdated; bool bShowNoNewVersion; //2、声明变量 int _stampAppCompile = -1; String _dateNewver = ''; Map _mapVer = {}; String serviceVersionCode = ''; String appId = ''; ProgressDialog pr; String apkName = ''; String appPath = ''; ReceivePort _port = ReceivePort(); void initState() { // 0、初始化FlutterDownLoader。版本更新初始化,放在这里会报错,初始化失败 // WidgetsFlutterBinding.ensureInitialized(); if (!bFlutterDownloader_initialize) { FlutterDownloader.initialize(debug: true).then((value) { registerCallback(first: true); }); } else { registerCallback(); } } registerCallback({bool first = false}) { //3、在initState中初始化 /* D/DownloadWorker( 4745): Update too frequently!!!!, this should be dropped E/flutter ( 4745): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The method 'update' was called on null. E/flutter ( 4745): Receiver: null E/flutter ( 4745): Tried calling: update(message: "下载中,请稍后…", progress: 0.0) E/flutter ( 4745): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5) E/flutter ( 4745): #1 MyUpdatedNew._updateDownLoadInfo (package:hyzp_ybqx/pages/MyMsics/05_updated/MyUpdatedNew.dart:251:10) E/flutter ( 4745): #2 _rootRunUnary (dart:async/zone.dart:1206:13) E/flutter ( 4745): #3 _CustomZone.runUnary (dart:async/zone.dart:1100:19) E/flutter ( 4745): #4 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7) E/flutter ( 4745): #5 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:357:11) E/flutter ( 4745): #6 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:285:7) E/flutter ( 4745): #7 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:808:19) E/flutter ( 4745): #8 _StreamController._add (dart:async/stream_controller.dart:682:7) E/flutter ( 4745): #9 _StreamController.add (dart:async/stream_controller.dart:624:5) E/flutter ( 4745): #10 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12) E/flutter ( 4745): */ if (!first) { // 解决2次进入报错无法下载的问题-OK // 如果以前注册过必须先移除,否则报错无法下载:DownloadWorker( 4745): Update too frequently!!!!, this should be dropped IsolateNameServer.removePortNameMapping('downloader_send_port'); // FlutterDownloader.cancelAll(); // FlutterDownloader.remove(taskId: null); } IsolateNameServer.registerPortWithName(_port.sendPort, 'downloader_send_port'); _port.listen(_updateDownLoadInfo); FlutterDownloader.registerCallback(_downLoadCallback); getNewverUrl().then((value) { _mapVer = value; print('_mapVer = ${_mapVer}'); //I/flutter (12498): _mapVer = {id: 1, ver: 1.0.0, miaos: 版本说明, // downurl: http://www.sctastech.com/download/hyzp_20210425.apk, updatetime: 1620632231} print('oldVer = ${ver}'); //_mapVer['ver'] = '1.3.1'; print('newVer = ${_mapVer['ver']}'); // I/flutter ( 1872): oldVer = 1.3.0 // I/flutter ( 1872): newVer = 1.3.1 if (first) { bFlutterDownloader_initialize = true; } startUpdated(); }); } ///开始更新过程 Future startUpdated() async { // 如果是android,则执行热更新 if (Platform.isAndroid) { verCompare(newVer: _mapVer['ver'], oldVer: ver).then((value) { if (value) { print('value = $value'); //_getNewVersionAPP(context); //appId = res.data['id']; //_checkVersionCode(); bNewVer = true; //发现新版本 if (bStartUpdated) { serviceVersionCode = _mapVer['ver']; _showNewVersionAppDialog(); } } else if (bShowNoNewVersion) { // 没有发现新版本 _showNoNewVersionAppDialog(); } }); } } /// 没有发现新版本 Future _showNoNewVersionAppDialog() async { return showDialog( context: theContext, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [Text("没有发现新版本")], ), content: Container( //padding: EdgeInsets.only(bottom: ScreenUtil().setHeight(18)), height: ScreenUtil().setHeight(230), decoration: BoxDecoration( border: Border.all(color: Colors.blueAccent, width: 1.0), borderRadius: BorderRadius.circular(5), ), alignment: Alignment.center, child: RichText( textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan(text: 'NewVer: ', style: TextStyle(fontSize: 17, color: Colors.black)), TextSpan( text: '暂无新版本', style: TextStyle( fontSize: 17, color: Colors.black, fontWeight: FontWeight.bold)), ]), ), ), actions: [ new FlatButton( child: new Text('确定'), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }); } /// 版本更新提示对话框 Future _showNewVersionAppDialog() async { String content1 = "注意:"; String content2 = "新版本下载成功后,将弹出“安装未知应用程序”界面,请"; String content3 = "授权“允许此来源”"; String content4 = ";然后"; String content5 = "稍等几秒钟"; String content6 = ",再"; String content7 = "点击“返回”按钮(一般位于左上角)"; String content8 = ",按照提示即可完成升级过程。若"; String content9 = "升级过程意外中断"; String content10 = ",可重启App再次升级即可。"; return showDialog( context: theContext, barrierDismissible: false, builder: (BuildContext context) { return AlertDialog( insetPadding: EdgeInsets.symmetric(horizontal: 20.0, vertical: 24.0), buttonPadding: EdgeInsets.only(bottom: 15, right: 20), title: Row( mainAxisAlignment: MainAxisAlignment.center, children: [Text("发现新版本")], ), content: Container( padding: EdgeInsets.only( left: ScreenUtil().setHeight(25), right: ScreenUtil().setHeight(10)), height: ScreenUtil().setHeight(620), decoration: BoxDecoration( border: Border.all(color: Colors.blueAccent, width: 1.0), borderRadius: BorderRadius.circular(5), ), alignment: Alignment.center, child: Column( children: [ RichText( textAlign: TextAlign.center, text: TextSpan(children: [ TextSpan( text: '\nNewVer: ', style: TextStyle(fontSize: 17, color: Colors.redAccent)), TextSpan( text: serviceVersionCode, style: TextStyle( fontSize: 17, color: Colors.redAccent, fontWeight: FontWeight.bold)), ]), ), RichText( textAlign: TextAlign.justify, text: TextSpan(children: [ getTextSpan('\n' + content1, color: Colors.blueAccent), getTextSpan(content2), getTextSpan(content3, color: Colors.redAccent), getTextSpan(content4), getTextSpan(content5, color: Colors.redAccent), getTextSpan(content6), getTextSpan(content7, color: Colors.redAccent), getTextSpan(content8), getTextSpan(content9, color: Colors.blueAccent), getTextSpan(content10), ]), ), ], ), ), actions: [ new FlatButton( child: new Text('立即更新'), onPressed: () { /// 执行更新操作 Navigator.pop(context); _executeDownload(context); }, ), new FlatButton( child: new Text('下次再说'), onPressed: () { Navigator.of(context).pop(); }, ), ], ); }); } TextSpan getTextSpan(String _text, {Color color = Colors.black, double fontSize = 15}) { return TextSpan(text: _text, style: TextStyle(fontSize: fontSize, color: color)); } /// 下载最新apk包 Future _executeDownload(BuildContext context) async { pr = new ProgressDialog( context, type: ProgressDialogType.Download, isDismissible: true, showLogs: true, ); pr.style(message: '准备下载...'); if (!pr.isShowing()) { pr.show(); } final path = await _apkLocalPath; apkName = getFileName(_mapVer['downurl']); await FlutterDownloader.enqueue( //url: 'http://update.rwworks.com:8088/appManager/monitor/app/appload/' + appId + '', url: _mapVer['downurl'], savedDir: path, fileName: apkName, showNotification: true, openFileFromNotification: true); } /// 下载进度回调函数 static void _downLoadCallback(String id, DownloadTaskStatus status, int progress) { final SendPort send = IsolateNameServer.lookupPortByName('downloader_send_port'); send.send([id, status, progress]); } /// 更新下载进度框 _updateDownLoadInfo(dynamic data) { DownloadTaskStatus status = data[1]; int progress = data[2]; if (status == DownloadTaskStatus.running) { pr.update(progress: double.parse(progress.toString()), message: "下载中,请稍后…"); } if (status == DownloadTaskStatus.failed) { if (pr.isShowing()) { pr.hide(); } } if (status == DownloadTaskStatus.complete) { if (pr.isShowing()) { pr.hide(); } _installApk(); } } /// 安装apk Future _installApk() async { await OpenFile.open(appPath + '/' + apkName); } /// 获取apk存储位置 Future get _apkLocalPath async { final directory = await getExternalStorageDirectory(); String path = directory.path + Platform.pathSeparator + 'Download'; ; final savedDir = Directory(path); bool hasExisted = await savedDir.exists(); if (!hasExisted) { await savedDir.create(); } appPath = path; // this.setState(() { // appPath = path; // }); return path; } //4、判断,自动更新 // 版本比较 //R:\FlutterProject\FlutterProject33\hyzp_ybqx\lib\pages\MyMsics\05_updated\MyUpdatedNew.dart line 343 Future verCompare({String newVer, String oldVer}) async { //解决newVer中不包含字符“+”号报错失败问题 if (newVer.indexOf('+') > -1) { //解决App.Car_Ver.Getver接口返回值变化后,1.3.11+20210729字符串转换为数字报错问题 print('newVer = $newVer'); newVer = newVer.substring(0, newVer.indexOf('+')); // substring是含头不含尾 print('newVer2 = $newVer'); } List listNewVer = await tran2int(newVer.split('.')); List listOldVer = await tran2int(oldVer.split('.')); int len = listNewVer.length; for (int i = 0; i < len; i++) { if (listNewVer[i] > listOldVer[i]) { return true; } if (listNewVer[i] < listOldVer[i]) { return false; } } return false; } Future tran2int(List _list) async { List listRet = []; int len = _list.length; for (int i = 0; i < len; i++) { listRet.add(int.parse(_list[i].trim())); } return listRet; } ///https://blog.csdn.net/zcylyzhi4/article/details/108002879 //5、自动更新代码 /// 执行版本更新的网络请求 /// 检查当前版本是否为最新,若不是,则更新 // void _checkVersionCode() { // PackageInfo.fromPlatform().then((PackageInfo packageInfo) { // var currentVersionCode = packageInfo.version; // if (double.parse(serviceVersionCode.substring(0, 3)) > // double.parse(currentVersionCode.substring(0, 3))) { // _showNewVersionAppDialog(); // } // }); // } }