uniapp app热更新

306 阅读3分钟

全局参数

import { hotUpdateStore } from "@/stores/hotUpdate.js";
let UpdateInfo = null;//更新的信息
let AppInfo = null;//当前app的信息

@/stores/hotUpdate.js里的函数

// 全局配置
import { defineStore } from "pinia";

export const hotUpdateStore = defineStore("hotUpdate", {
  state: () => {
    return {
      //是否需要更新
      ISNeedUpdate: false,
      // 当前app版本
      version: "",
    };
  },
  getters: {},
  actions: {
    setISNeedUpdate(data) {
      this.ISNeedUpdate = data;
    },
    setVersion(data) {
      this.version = data;
    },
  },
});

获取app更新信息

function getUpdateInfo() {
  return new Promise((resolve, reject) => {
    uni.request({
      url: "xxxxxxxxxxxxxxxxxxx",
      success(res) {
        resolve(res.data);
      },
      fail(error) {
        resolve(false);
      },
    });
  });
}
返回格式为
{  
    description"升级说明",  
    androidVer"1.1.7",  //安卓版本
    iosVer"1.1.7",  //ios版本
    wgtUrl"https://xxxx/xxx.wgt", //热更包下载地址,Hbuild发行-制作wgt包
    apkUrl"https://xxxxx",  //apk线上下载地址
    vivoUrl"vivomarket://details?id=xxxx",  
    xiaomiUrl"mimarket://details?id=xxxx",  
    oppoUrl"oppomarket://details?packagename=xxxx",  
    huaweiUrl"appmarket://details?id=xxxx",  
    honorUrl"xxxxxxxxxx",
    ipaUrl"https://apps.apple.com/xxx" //苹果商城下载地址 
}

获取app获取应用信息,这里我们需要4个信息
①是安卓还是ios
②应用渠道,只有安卓有用到这个参数
③当前版本号,这里我们取appWgtVersion

api来源 www.html5plus.org/doc/zh_cn/r… www.html5plus.org/doc/zh_cn/r…

// 获取应用信息
function getAppInfo() {
  return new Promise(async (resolve, reject) => {
    //这里目的是获取当前app所有信息
    let AppInfo = await uni.getSystemInfo();
    // store状态管理存应用版本
    const usehotUpdateStore = hotUpdateStore();
    usehotUpdateStore.setVersion(AppInfo.appWgtVersion);
    /*#ifdef APP-PLUS*/
    //渠道信息
    AppInfo.channel = plus.runtime.channel;
    /*#endif*/
    resolve(AppInfo);
  });
}

判断应用是否需要更新

//判断是否需要更新 true为是
async function isNeedUpdate() {
  //版本对比函数
  /**
   * 对比版本号
   * 支持比对	("1.0.1", "1.0");("2.0.0.0", "3.0");("1.0.1", "1.1.1") 之类的,支持不同位数
   * @param {Object} v1
   * @param {Object} v2
   * v1 > v2 return 1
   * v1 < v2 return -1
   * v1 == v2 return 0
   */
  function compareVersions(version1, version2) {
    const v1 = version1.split(".").map(Number);
    const v2 = version2.split(".").map(Number);
    while (v1.length < v2.length) {
      v1.push(0);
    }
    while (v2.length < v1.length) {
      v2.push(0);
    }
    for (let i = 0; i < v1.length; i++) {
      if (v1[i] < v2[i]) {
        return -1;
      } else if (v1[i] > v2[i]) {
        return 1;
      }
    }
    return 0;
  }
  const usehotUpdateStore = hotUpdateStore();
  return new Promise(async (resolve, reject) => {
    //各自系统对应的版本号
    //更新的版本号
    let updateVersionObj = {
      android: UpdateInfo.androidVer,
      ios: UpdateInfo.iosVer,
    };
    //现在的版本号
    let oldVersionObj = {
      android: AppInfo.appWgtVersion,
      ios: AppInfo.appWgtVersion,
    };
    //判断哪个版本大
    let isUpdate = compareVersions(
      updateVersionObj[AppInfo.osName],
      oldVersionObj[AppInfo.osName]
    );
    //不需要更新
    if (isUpdate !== 1) {
      //存是否需要更新
      usehotUpdateStore.setISNeedUpdate(false);
      resolve(false);
      return;
    }
    //需要更新
    //如果是qqq这个渠道的才热更
    if (AppInfo.channel !== "qqq" && AppInfo.osName == "android") {
      resolve(false);
      return;
    }
    //存是否需要更新
    usehotUpdateStore.setISNeedUpdate(true);
    resolve(true);
  });
}

判断app为安卓还是ios,执行对应的更新函数

//执行更新
function startUpdate() {
  console.log(`______热更5_1:${AppInfo.osName}开始更新`);
  switch (AppInfo.osName) {
    case "android":
      updateAndroid();
      break;
    case "ios":
      updateIOS();
      break;
    default:
      break;
  }
}

ios不能热更,会封号,所以我们要跳去苹果商城的下载地址,地址示例apps.apple.com/us/app/%E5%…

//ios更新
function updateIOS() {
  if ("ipaUrl" in UpdateInfo && UpdateInfo.ipaUrl) {
    plus.runtime.openURL("苹果商城下载地址")
  }
}

安卓热更
国内厂商应用商店跳转链接可以参考这里www.70apps.com/blog/web/20…

//安卓更新
export let progress = 0; //下载进度
function updateAndroid() {
  switch (AppInfo.brand) {
    case "vivo":
      plus.runtime.openURL(UpdateInfo.vivoUrl);
      break;
    case "oppo":
      plus.runtime.openURL(UpdateInfo.oppoUrl);
      break;
    case "xiaomi":
      plus.runtime.openURL(UpdateInfo.xiaomiUrl);
      break;
    case "honor":
      plus.runtime.openURL(UpdateInfo.honorUrl);
      break;
    case "huawei":
      plus.runtime.openURL(UpdateInfo.huaweiUrl);
      break;
    default:
      if ("wgtUrl" in UpdateInfo && UpdateInfo.wgtUrl) {
        const task = uni.downloadFile({
          url: UpdateInfo["wgtUrl"],
          success(downloadResult) {
            if (downloadResult.statusCode == 200) {
              uni.showLoading({
                title: `${AppInfo.appName}更新中`,
              });
              setTimeout(() => {
                plus.runtime.install(
                  downloadResult.tempFilePath,
                  {
                    force: false,
                  },
                  function () {
                    uni.hideLoading();
                    plus.runtime.restart();
                  },
                  function (e) {}
                );
              }, 2000);
            }
          },
          fail: () => {
            uni.hideLoading();
            uni.showToast({
              title: "更新文件下载失败",
              icon: "none",
              duration: 1500,
            });
          },
        });
        uni.showLoading({
          title: `更新文件下载中`,
        });
        //下载进度
        task?.onProgressUpdate((update) => {
          progress = update.progress;
        });
      }
      break;
  }
}

我们可以将以上信息这样组合起来

hotUpdate(false)为主动触发
hotUpdate(ture)为自动触发

// 热更新 auto为true是自动触发,false是主动触发
export async function hotUpdate(auto = true) {
  /*#ifdef APP-PLUS*/
  console.log("______热更1:热更程序开始执行");
  //应用信息
  AppInfo = await getAppInfo();
  // 从服务器获取版本信息,看看是否需要更新
  UpdateInfo = await getUpdateInfo();
  //是否需要更新
  let NeedUpdate = await isNeedUpdate();
  if (!NeedUpdate) {
    console.log("______热更2_1:当前已是最新版");
    if (!auto) {
      uni.showToast({
        title: "当前已是最新版",
        icon: "none",
        duration: 1500,
      });
    }
    return;
  }
  console.log("______热更2_1:存在可以更新的版本");
  if (auto) {
    let currentData = dayjs().format("YYYYMMDD");
    let UpdateTime = uni.getStorageSync("AutoUpdateTime"); 
    if (UpdateTime) {
      uni.setStorageSync("AutoUpdateTime", UpdateTime); //不加这个,不知道哪里就给我清了。。。
      let UpdateTime_format = dayjs(UpdateTime).format("YYYYMMDD");
      if (currentData < UpdateTime_format) {
        console.log(
          `______热更3_1:用户之前热更提醒点击了取消,需要自他点击起等待7天,${UpdateTime_format}才会再次提醒`
        );
        return;
      }
    }
  }
  uni.showModal({
    title: "发现新版本",
    content: "是否更新应用?",
    success(res) {
      if (res.confirm) {
        startUpdate();
      }
      if (res.cancel) {
        console.log("______热更4_2:取消更新,7天后再次提醒");
        if (auto) {
          // 如果取消,设置7天后才提醒
          let sevenDayAfter = dayjs().add(7, "day").format("YYYY-MM-DD");
          uni.setStorageSync("AutoUpdateTime", JSON.stringify(sevenDayAfter));
          console.log(
            `______热更4_2:${uni.getStorageSync(
              "AutoUpdateTime"
            )}日之后再次提醒`
          );
        }
      }
    },
    fail(err) {},
  });
  /*#endif*/
  console.log("______热更1:运行在H5环境上,热更程序不执行");
}