基础库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

186 lines
6.3 KiB

  1. import 'dart:io';
  2. import 'package:flutter/cupertino.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_update_dialog/flutter_update_dialog.dart';
  5. import 'package:flutter_xupdate/flutter_xupdate.dart';
  6. import 'package:package_info/package_info.dart';
  7. import 'package:url_launcher/url_launcher.dart';
  8. import 'package:zhiying_comm/util/shared_prefe_util.dart';
  9. import 'package:zhiying_comm/util/update/app_update_model.dart';
  10. import 'package:zhiying_comm/zhiying_comm.dart';
  11. import 'package:fluttertoast/fluttertoast.dart';
  12. import '../log/let_log.dart';
  13. ///
  14. /// App更新工具类
  15. ///
  16. class AppUpdateUtil {
  17. static final String _IGNORE_VERSION = "xupdate_ignore_version";
  18. ///
  19. /// 初始化更新插件
  20. ///
  21. static void initXUpdate() {
  22. if (Platform.isAndroid) {
  23. FlutterXUpdate.init(
  24. ///是否输出日志
  25. debug: true,
  26. ///是否使用post请求
  27. isPost: false,
  28. ///post请求是否是上传json
  29. isPostJson: false,
  30. ///是否开启自动模式
  31. isWifiOnly: false,
  32. ///是否开启自动模式
  33. isAutoMode: false,
  34. ///需要设置的公共参数
  35. supportSilentInstall: false,
  36. ///在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗
  37. enableRetry: false)
  38. .then((value) {
  39. Logger.log('初始化成功: $value');
  40. }).catchError((error) {
  41. print(error);
  42. });
  43. FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async {
  44. Logger.warn(message);
  45. });
  46. FlutterXUpdate.setErrorHandler(onUpdateError: (Map<String, dynamic> message) async {
  47. Logger.warn(message);
  48. });
  49. } else {
  50. Logger.log('ios暂不支持XUpdate更新');
  51. }
  52. }
  53. ///
  54. /// 检查并且更新app
  55. ///
  56. /// @context 上下文
  57. /// @needToast 是否需要提示最新版本
  58. /// @mustShowDialog 是否必须弹窗(检查更新页面要弹窗)
  59. ///
  60. static Future updateApp(BuildContext context, {bool needToast = false, bool mustShowDialog = false}) async {
  61. UpdateEntity updateEntity = await _checkAppUpdate();
  62. // 有新版本,进行更新
  63. if (!EmptyUtil.isEmpty(updateEntity) && updateEntity.hasUpdate) {
  64. if (Platform.isAndroid) {
  65. FlutterXUpdate.updateByInfo(
  66. updateEntity: updateEntity,
  67. supportBackgroundUpdate: true,
  68. enableIgnore: mustShowDialog || updateEntity.isForce,
  69. retryContent: '更新下载速度太慢了,是否考虑切换下载方式?',
  70. enableRetry: updateEntity.thirdParty,
  71. overrideGlobalRetryStrategy: true,
  72. retryUrl: updateEntity.thirdUrl,
  73. );
  74. } else if (Platform.isIOS) {
  75. bool ignore = await isIgnoreVersion(updateEntity?.versionCode?.toString());
  76. if ((!ignore || mustShowDialog) || updateEntity.isForce || !updateEntity.isIgnorable) {
  77. String updateUrl = updateEntity.downloadUrl;
  78. customStyle(context, updateEntity, onUpdate: () {
  79. // 打开第三方sdk
  80. launch(updateUrl, forceSafariVC: true, enableJavaScript: true, forceWebView: true);
  81. Navigator.pop(context);
  82. });
  83. }
  84. }
  85. } else {
  86. if (needToast) Fluttertoast.showToast(msg: '已经是最新版本了~');
  87. }
  88. return null;
  89. }
  90. /// 检查是否有新版本
  91. static Future<UpdateEntity> _checkAppUpdate() async {
  92. try {
  93. // var result = {
  94. // "code": 1,
  95. // "data": {
  96. // "app_download_thirdparty_url": "https://android.myapp.com/myapp/detail.htm?apkName=com.hairuyi.www&ADTAG=mobile",
  97. // "app_download_url": "http://fir.osant.cn/zhiyi",
  98. // "app_version": "1",
  99. // "app_version_name": "1.0.0",
  100. // "content": "更新接口\n完善app页面\n更新站长后台",
  101. // "dialog": "1",
  102. // "is_force": "0",
  103. // "is_ignore": "0",
  104. // "is_thirdparty": "1",
  105. // "tip": "有新版下载"
  106. // },
  107. // "msg": "ok"
  108. // };
  109. var result = await NetUtil.post('/api/v1/appcheck', method: NetMethod.GET);
  110. AppUpdateModel model = AppUpdateModel.fromJson(result[GlobalConfig.HTTP_RESPONSE_KEY_DATA]);
  111. if (!EmptyUtil.isEmpty(model)) {
  112. return UpdateEntity(
  113. hasUpdate: model?.dialog == '1',
  114. isIgnorable: model?.isIgnore == '1' && model?.isForce != '1',
  115. isForce: model?.isForce == '1',
  116. versionCode: int.parse(model?.appVersion ?? '1'),
  117. versionName: model?.appVersionName,
  118. downloadUrl: model?.appDownloadUrl,
  119. updateContent: model?.content,
  120. tip: model?.tip,
  121. thirdUrl: model?.appDownloadThirdpartyUrl,
  122. thirdParty: model?.isThirdparty == '1',
  123. );
  124. }
  125. } catch (e, s) {
  126. Logger.error(e, s);
  127. }
  128. return null;
  129. }
  130. // IOS 样式
  131. static void customStyle(BuildContext context, UpdateEntity updateEntity, {@required VoidCallback onUpdate}) {
  132. UpdateDialog.showUpdate(context,
  133. width: 250,
  134. title: "是否升级到${updateEntity?.versionName ?? '1.0.0'}版本?",
  135. updateContent: updateEntity?.updateContent ?? '',
  136. titleTextSize: 14,
  137. contentTextSize: 12,
  138. buttonTextSize: 12,
  139. // topImage: Image.asset('assets/bg_update_top.png'),
  140. extraHeight: 5,
  141. radius: 8,
  142. themeColor: Colors.redAccent,
  143. progressBackgroundColor: Color(0x5AFFAC5D),
  144. isForce: updateEntity?.isForce ?? false,
  145. updateButtonText: '升级',
  146. ignoreButtonText: '忽略此版本',
  147. enableIgnore: updateEntity?.isIgnorable ?? false, onIgnore: () {
  148. saveIgnoreVersion(updateEntity?.versionCode?.toString());
  149. Navigator.pop(context);
  150. }, onUpdate: onUpdate);
  151. }
  152. // 保存忽略的版本号码
  153. static void saveIgnoreVersion(String newVersion) async {
  154. if (!EmptyUtil.isEmpty(newVersion)) {
  155. await SharedPreferencesUtil.setStringValue(_IGNORE_VERSION, newVersion);
  156. }
  157. }
  158. // 是否是忽略版本
  159. static Future<bool> isIgnoreVersion(String newVersion) async {
  160. String oldVersion = await SharedPreferencesUtil.getStringValue(_IGNORE_VERSION);
  161. if (!EmptyUtil.isEmpty(oldVersion) && !EmptyUtil.isEmpty(newVersion)) {
  162. return oldVersion == newVersion;
  163. }
  164. return false;
  165. }
  166. }