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

4 篇文章 0 订阅
4 篇文章 0 订阅
本次需要用到的插件

因为最新版的插件要我升级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.setCode(0);
                appUpdateInfo.setApkMd5(null);
                appUpdateInfo.setApkSize(0);
                appUpdateInfo.setDownloadUrl(null);
                appUpdateInfo.setMsg("No new updates");
                appUpdateInfo.setUpdateContent(null);
                appUpdateInfo.setUpdateStatus(0);
                appUpdateInfo.setIsForce(0);
                appUpdateInfo.setVersionCode(null);
                appUpdateInfo.setVersionName(null);

                return appUpdateInfo;
            }
            AppUpdateInfo appUpdateInfo = new AppUpdateInfo();
            appUpdateInfo.setCode(0);
            appUpdateInfo.setMsg("success");
            appUpdateInfo.setApkMd5(latestAppUpdate.getApkMd5());
            appUpdateInfo.setDownloadUrl(latestAppUpdate.getDownloadUrl());
            appUpdateInfo.setUpdateContent(latestAppUpdate.getUpdateContent());
            appUpdateInfo.setUpdateStatus(latestAppUpdate.getUpdateStatus());
            appUpdateInfo.setIsForce(latestAppUpdate.getIsForce());
            appUpdateInfo.setVersionCode(latestAppUpdate.getVersionCode());
            appUpdateInfo.setVersionName(latestAppUpdate.getVersionName());
            appUpdateInfo.setApkSize(latestAppUpdate.getApkSize());
            return appUpdateInfo;
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage(), e);
            return null;
        }
3.Mapper
<select id="selectByLatest" resultType="java.util.Map">
		select * from app_update
		order by version_code desc limit 0, 1;
</select>

mysql代码

DROP TABLE IF EXISTS `app_update`;
CREATE TABLE `app_update`  (
  `id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  `update_status` tinyint(1) NOT NULL COMMENT '0代表不更新,1代表更新',
  `is_force` tinyint(1) NOT NULL DEFAULT 0 COMMENT '1代表代表有版本更新,需要强制升级,0代表有版本更新,不需要强制升级',
  `version_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '版本号,用于版本比较',
  `version_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '版本号(显示)',
  `update_content` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '发布说明/升级内容',
  `download_url` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '软件包下载地址',
  `apk_size` mediumtext CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '发布的软件包大小(字节)',
  `apk_md5` varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'MD5校验码',
  `create_time` timestamp(0) NULL DEFAULT NULL COMMENT '发布日期',
  `create_by` varchar(36) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '发布人',
  `remark` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统版本发布' ROW_FORMAT = Dynamic;

数据库截图
在这里插入图片描述

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值