flutter使用flutter_xupdate插件实现app内更新

Posted 英文不好太难了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flutter使用flutter_xupdate插件实现app内更新相关的知识,希望对你有一定的参考价值。

本次需要用到的插件

因为最新版的插件要我升级flutter,所以没有用最新的

#1.app内更新
flutter_xupdate: ^1.0.2
#2.http请求,用来下载app
dio: ^3.0.10

flutter端代码

  1. 更改app主题,(必须要这个操作),修改android》app》src》main》res》values》styles.xml 文件为
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="LaunchTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>
</resources>

2.在pubspec.yaml里添加两个插件

flutter_xupdate: ^1.0.2
dio: ^3.0.10

3.新建AppInfo.dart

// 使用Dart Data Class Generator插件进行创建  使用命令: Generate from JSON
import 'dart:convert';

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';
  }
}

4.新建CheckUpdate.dart


import 'package:flutter_xupdate/flutter_xupdate.dart';
import 'package:stapp/custom/AppInfo.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["updateContent"].split('。');
    var updateContent = '';
    updateText.forEach((t) {
      updateContent += '\\r\\n$t';
    });

    UpdateEntity updateEntity = new  UpdateEntity(
        isForce: jsonData["isForce"] == 1,
        hasUpdate: true,
        isIgnorable: false,
        versionCode: int.parse(versionCode),
        versionName: jsonData["versionName"],
        updateContent: updateContent,
        downloadUrl: jsonData["downloadUrl"],
        apkSize: jsonData["apkSize"]);
    FlutterXUpdate.updateByInfo(updateEntity: updateEntity);
  }

  // 初始化插件
  Future<dynamic> initXUpdate () async {
    FlutterXUpdate.init(
      //是否输出日志
        debug: true,
        //是否使用post请求
        isPost: true,
        //post请求是否是上传json
        isPostJson: true,
        //是否开启自动模式
        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);
    });
  }
}


5.在main.dart里添加代码,还有引入相关class

import ‘package:dio/dio.dart’;
import ‘package:package_info/package_info.dart’;
import ‘custom/CheckUpdate.dart’;

在main.dart里的 class 类名 extends State<类名> 下面加上

 @override
  void initState() {
    checkUpdateVersion();
    super.initState();
  }

void appUpdate(versionData) async{
  CheckUpdate checkUpdate = new CheckUpdate();
  await checkUpdate.initXUpdate();
  await checkUpdate.checkUpdateByUpdateEntity(versionData); // flutter_xupdate 自定义JSON 方式,
}

  // 检查是否需要版本更新
  Future<bool> checkUpdateVersion() async {
    PackageInfo packageInfo = await PackageInfo.fromPlatform();


    String versionCode = packageInfo.version;

    bool check=false;

    try {
      Dio dio = new Dio();
      Map<String, dynamic> dataMap = new Map<String, dynamic>();
      dataMap['versionCode'] = versionCode;
      var data = json.encode(dataMap);

      Response response = await dio.post(
            IP请求后端路径,例如"110.63.174.25:8080/weixin/api/appUpdate", data: data).then((value) {
        Map versionData = json.decode(value.data);
        if (versionData["code"] == 0 && versionData['msg']=="success") {
          if(versionData['updateStatus'] != 0) {
            print(versionData);
            // 后台返回的版本号是带小数点的(2.8.1)所以去除小数点用于做对比
            var targetVersion = versionData["versionCode"].replaceAll(
                '.', '');
            // 当前App运行版本
            var currentVersion = versionCode.replaceAll('.', '');
            if (int.parse(targetVersion) > int.parse(currentVersion)) {
              if (Platform.isAndroid) { // 安卓弹窗提示本地下载, 交由flutter_xupdate 处理,不用我们干嘛。
               appUpdate(versionData);
              } else if (Platform.isios) { // IOS 跳转 AppStore
              //  print( 'ios不支持app内更新');
              }
            }
          }
        }
        }
      );
      } catch (e)
      {
        print(e);
      }
      return check;
    }

java框架springboot代码

1.model

1.1、新建AppUpdate.java

import com.annotation.persistence.Id;

import java.io.Serializable;
import java.util.Date;
import java.util.UUID;

public class AppUpdate implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = 2205916048882337011L;
    @Id
    private String id = UUID.randomUUID().toString();
    /**
     * 1代表代表有版本更新,需要强制升级,0代表有版本更新,不需要强制升级
     */
    private Integer isForce;
    /**
     * 0代表不更新,1代表更新
     */
    private Integer updateStatus;
    /**
     * 版本号,用于版本比较
     */
    private String versionCode;
    /**
     * 版本号(显示)
     */
    private String versionName;
    /**
     * 发布说明/升级内容
     */
    private String updateContent;
    /**
     * 软件包下载地址
     */
    private String downloadUrl;
    /**
     * 发布的软件包大小(字节)
     */
    private Long apkSize;
    /**
     * MD5校验码
     */
    private String apkMd5;
    /**
     * 发布日期
     */
    private Date createTime;
    /**
     * 发布人
     */
    private String createBy;
    /**
     * 备注
     */
    private String remark;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Integer getIsForce() {
        return isForce;
    }

    public void setIsForce(Integer isForce) {
        this.isForce = isForce;
    }

    public Integer getUpdateStatus() {
        return updateStatus;
    }

    public void setUpdateStatus(Integer updateStatus) {
        this.updateStatus = updateStatus;
    }

    public String getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(String versionCode) {
        this.versionCode = versionCode;
    }

    public String getVersionName() {
        return versionName;
    }

    public void setVersionName(String versionName) {
        this.versionName = versionName;
    }

    public String getUpdateContent() {
        return updateContent;
    }

    public void setUpdateContent(String updateContent) {
        this.updateContent = updateContent;
    }

    public String getDownloadUrl() {
        return downloadUrl;
    }

    public void setDownloadUrl(String downloadUrl) {
        this.downloadUrl = downloadUrl;
    }

    public Long getApkSize() {
        return apkSize;
    }

    public void setApkSize(Long apkSize) {
        this.apkSize = apkSize;
    }

    public String getApkMd5() {
        return apkMd5;
    }

    public void setApkMd5(String apkMd5) {
        this.apkMd5 = apkMd5;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    public String getCreateBy() {
        return createBy;
    }

    public void setCreateBy(String createBy) {
        this.createBy = createBy;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

1.2 、新建AppUpdateInfo.java

public class AppUpdateInfo {
        /*
    "Code": 0, //0代表请求成功,非0代表失败
    "Msg": "", //请信息
         */


    private int code;
    private String Msg;
    private String versionCode;
    private String versionName;
    private String updateContent;
    private String downloadUrl;
    private long apkSize;
    private String apkMd5;
    private int updateStatus;
    private int isForce;

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public String getMsg() {
        return Msg;
    }

    public void setMsg(String msg) {
        Msg = msg;
    }

    public String getVersionCode() {
        return versionCode;
    }

    public void setVersionCode(String versionCode) {
        this.versionCode = versionCode;
    }

    public String getVersionName() {
        return versionName;
    }

    public void setVersionName(String versionName) {
        this.versionName = versionName;
    }

    public String getUpdateContent() {
        return updateContent;
    }

    public void setUpdateContent(String updateContent) {
        this.updateContent = updateContent;
    }

    public String getDownloadUrl() {
        return downloadUrl;
    }

    public void setDownloadUrl(String downloadUrl) {
        this.downloadUrl = downloadUrl;
    }

    public long getApkSize() {
        return apkSize;
    }

    public void setApkSize(long apkSize) {
        this.apkSize = apkSize;
    }

    public String getApkMd5() {
        return apkMd5;
    }

    public void setApkMd5(String apkMd5) {
        this.apkMd5 = apkMd5;
    }

    public int getUpdateStatus() {
        return updateStatus;
    }

    public void setUpdateStatus(int updateStatus) {
        this.updateStatus = updateStatus;
    }

    public int getIsForce() {
        return isForce;
    }

    public void setIsForce(int isForce) {
        this.isForce = isForce;
    }

}

2.controller

2.1、AppUpdateController.java部分代码

  /**
     * app应用内升级检查
     *
     * @param versionCode APP当前的版本号
     * @return AppUpdateInfo
     */
    @ResponseBody
    @RequestMapping("/weixin/api/appUpdate")
    public AppUpdateInfo update(@RequestBody Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) {
        String versionCode = Utils.dealNull(params.get("versionCode"));
        String id = Utils.dealNull(params.get("id"));
        try {

            AppUpdate latestAppUpdate = this.baseService.findByLatest(AppUpdate.class);
            /*
            "Code": 0, //0代表请求成功,非0代表失败
            "Msg": "", //请求出错的信息
            "UpdateStatus": 1, //0代表不更新,1代表有版本更新,不需要强制升级,2代表有版本更新,需要强制升级
            是否强制升级,用isForce字段
            "VersionCode": 3,
            "VersionName": "1.0.2",
            "ModifyContent": "1、优化api接口。\\r\\n2、添加使用demo演示。\\r\\n3、新增自定义更新服务API接口。\\r\\n4、优化更新提示界面。",
            "DownloadUrl": "https://raw.githubusercontent.com/xuexiangjys/XUpdate/master/apk/xupdate_demo_1.0.2.apk",
            "ApkSize": 2048
            "ApkMd5": "..."  //md5值没有的话,就无法保证apk是否完整,每次都会重新下载。框架默认使用的是md5加密。*/
            if (latestAppUpdate == null || VersionNumberComparer.versionCompare(latestAppUpdate.getVersionCode(), versionCode) <= 0) {
                AppUpdateInfo appUpdateInfo = new AppUpdateInfo();
                appUpdateInfo.以上是关于flutter使用flutter_xupdate插件实现app内更新的主要内容,如果未能解决你的问题,请参考以下文章

Flutter 最好的导航插件

Flutter 最好的导航插件

集成 iOS 原生插件到 flutter 项目

Flutter 工程报错 Failed to create provisioning profile.

移动硬盘插在苹果电脑上后其他电脑使用不了了怎么修复?

多重插补为啥要汇总分析