zoukankan      html  css  js  c++  java
  • flutter 优雅的版本更新处理

    本人掘金文章

    思路步骤:

    1.  获取后台接口返回的最新版本的 vsersion 值! (这需要每次APP发版提审后,同时更新后台数据库App version);
    2.  使用 package_info 插件获取项目当前APP运行的 的版本号 version
    3.  后台返回的版本 version 大于 package_info 获取的 version!则弹出提示更新;
    4.  ios 跳转 AppStore 进行更新; android 则App内下载更新

    说明:

    1.  android 版本的 apk 上传到公司 oss, 生成的链接就是下载链接
    2.  可能存在的坑有, 本地开发模式下 android 下载好的apk安装不了, 提示应用签名不一致! (原因 本地开发模式并没有走 keystore签名;但是apk有; 用户从应用商店下载不会出现这情况; 或者你通过apk安装应用,在走流程测试就不会了)
    3.  使用的第三方插件有 package_info 用于获取当前版本号;flutter_xupdate 用于 android App内下载更新;
    4.  效果图见尾部

    具体代码:

    注: android 实现 App 内下载更新,我选用的是 flutter_xupdate插件并且使用的是自定义JSON的格式(灵活性较好); 插件使用方式请点击 flutter_xupdate

    homePage.dart 文件
     import './CheckUpdate.dart';
        CheckUpdate checkUpdate = CheckUpdate();
      
        // 获取版本
        Future<dynamic> initPackageInfo () async {
          PackageInfo packageInfo = await PackageInfo.fromPlatform();
          version = packageInfo.version;
        }
        
         // 检查是否需要版本更新
        void _checkUpdateVersion () async {
          await initPackageInfo();
          try {
            var response = await HttpUtil().post("app/version/detail?", 'mobile', 'json', false);
            if (response["code"] != 0) {
              setState(() {
                versionData = response["data"];
              });
              // 后台返回的版本号是带小数点的(2.8.1)所以去除小数点用于做对比
              var targetVersion = response["data"]["versionCode"].replaceAll('.', '');
              // 当前App运行版本
              var currentVersion = version.replaceAll('.', '');
              if (int.parse(targetVersion) > int.parse(currentVersion)) {
                if (Platform.isAndroid) { // 安卓弹窗提示本地下载, 交由flutter_xupdate 处理,不用我们干嘛。
                  await checkUpdate.initXUpdate();
                  checkUpdate.checkUpdateByUpdateEntity(versionData); // flutter_xupdate 自定义JSON 方式, 
                } else if (Platform.isIOS) { // IOS 跳转 AppStore
                  showIOSDialog(); // 弹出ios提示更新框
                }
              }
            }
          } catch (e) {
            print(e);
          }
        }
    CheckUpdate.dart 文件
    import 'dart:convert';
    import 'package:flutter_xupdate/flutter_xupdate.dart';
    
    class CheckUpdate{
      // 将自定义的json内容解析为UpdateEntity实体类
      UpdateEntity customParseJson(String json) {
        AppInfo appInfo = AppInfo.fromJson(json);
        return UpdateEntity(
          isForce: appInfo.isForce, // 是否强制更新
          hasUpdate: appInfo.hasUpdate, // 是否需要更新  默认true, 手动自行判断
          isIgnorable: appInfo.isIgnorable, // 是否显示 “忽略该版本”
          versionCode: appInfo.versionCode, // 新版本号
          versionName: appInfo.versionName, // 新版名称
          updateContent: appInfo.updateLog, // 新版更新日志
          downloadUrl: appInfo.apkUrl, // 新版本下载链接
          apkSize: appInfo.apkSize); // 新版本大小
      }
        // 自定义JSON更新
      checkUpdateByUpdateEntity(Map jsonData) async {
        var versionCode = jsonData["versionCode"].replaceAll('.', '');
        var updateText = jsonData["updateLog"].split('');
        var updateLog = '';
        updateText.forEach((t) {
          updateLog += '
    $t';
        });
        var rusultJson = {
          "isForce": jsonData["isForce"] == 1,
          "hasUpdate": true,
          "isIgnorable": false,
          "versionCode": int.parse(versionCode),
          "versionName": jsonData["versionName"],
          "updateLog": updateLog,
          "apkUrl": jsonData["apkUrl"],
          "apkSize":jsonData["apkSize"]
        };
        FlutterXUpdate.updateByInfo(updateEntity: customParseJson(json.encode(rusultJson)));
      }
    
      // 初始化插件
      Future<dynamic> initXUpdate () async {
        FlutterXUpdate.init(
          //是否输出日志
          debug: true,
          //是否使用post请求
          isPost: false,
          //post请求是否是上传json
          isPostJson: false,
          //是否开启自动模式
          isWifiOnly: false,
          ///是否开启自动模式
          isAutoMode: false,
          //需要设置的公共参数
          supportSilentInstall: false,
          //在下载过程中,如果点击了取消的话,是否弹出切换下载方式的重试提示弹窗
          enableRetry: false)
        .then((value) {
          print("初始化成功: $value");
        }).catchError((error) {
          print(error);
        });
        FlutterXUpdate.setUpdateHandler(
          onUpdateError: (Map<String, dynamic> message) async {
            print("初始化成功: $message");
          }, onUpdateParse: (String json) async {
            //这里是自定义json解析
            return customParseJson(json);
          });
      }
    }
    
    // 使用Dart Data Class Generator插件进行创建  使用命令: Generate from JSON
    class AppInfo {
      final bool isForce;
      final bool hasUpdate;
      final bool isIgnorable;
      final int versionCode;
      final String versionName;
      final String updateLog;
      final String apkUrl;
      final int apkSize;
    
      AppInfo({
        this.isForce,
        this.hasUpdate,
        this.isIgnorable,
        this.versionCode,
        this.versionName,
        this.updateLog,
        this.apkUrl,
        this.apkSize,
      });
    
      Map<String, dynamic> toMap() {
        return {
          'isForce': isForce,
          'hasUpdate': hasUpdate,
          'isIgnorable': isIgnorable,
          'versionCode': versionCode,
          'versionName': versionName,
          'updateLog': updateLog,
          'apkUrl': apkUrl,
          'apkSize': apkSize,
        };
      }
    
      static AppInfo fromMap(Map<String, dynamic> map) {
        if (map == null) return null;
    
        return AppInfo(
          isForce: map['isForce'],
          hasUpdate: map['hasUpdate'],
          isIgnorable: map['isIgnorable'],
          versionCode: map['versionCode']?.toInt(),
          versionName: map['versionName'],
          updateLog: map['updateLog'],
          apkUrl: map['apkUrl'],
          apkSize: map['apkSize']?.toInt(),
        );
      }
    
      String toJson() => json.encode(toMap());
    
      static AppInfo fromJson(String source) => fromMap(json.decode(source));
    
      @override
      String toString() {
        return 'AppInfo isForce: $isForce, hasUpdate: $hasUpdate, isIgnorable: $isIgnorable, versionCode: $versionCode, versionName: $versionName, updateLog: $updateLog, apkUrl: $apkUrl, apkSize: $apkSize';
      }
    }

    有疑问欢迎留言

    效果图: 左边2张为 android, 右边为 ios

                     

  • 相关阅读:
    C#中AppDomain.CurrentDomain.BaseDirectory及各种路径获取方法
    Sqlserver查询数据库文件大小和剩余空间
    【免费视频】使用VS Code开发ASP.NET Core WebAPI应用程序
    WinForm自动记录从上次关闭位置启动窗体
    c#通过socket判断服务器连接是否正常
    ASP.NET Core Windows服务开发技术实战演练
    win7/win10 设置始终以管理员身份运行cmd窗口
    投资回报率,止损率
    等额本息,等额本金,先息后本解读
    银行加息有什么影响(央行加息,对股市和房价有何影响?)
  • 原文地址:https://www.cnblogs.com/ljx20180807/p/13038654.html
Copyright © 2011-2022 走看看