uniapp中检查版本,提示升级app,安卓下载apk,ios跳转应用商店

uniapp中检查版本,提示升级app,安卓下载apk,ios跳转应用商店

##使用方法:
可以在app.vueonLaunch中调用appUpdate,打开app就会检测

onLaunch: function () {
    appUpdate()
},

完整代码如下:

//APP更新
import {queryAppVersion} from "@/apis/app";

// 比较版本号:v1 < v2 返回 -1,v1 > v2 返回 1,相等返回 0
function compareVersions(v1, v2) {
  const v1Parts = v1.split('.').map(Number);
  const v2Parts = v2.split('.').map(Number);

  const maxLength = Math.max(v1Parts.length, v2Parts.length);

  for (let i = 0; i < maxLength; i++) {
    const part1 = v1Parts[i] || 0;
    const part2 = v2Parts[i] || 0;

    if (part1 > part2) return 1;
    if (part1 < part2) return -1;
  }

  return 0;
}


async function checkAndroid(remoteRes) {
  let curVersion = uni.getAppBaseInfo().appVersion

  const {appDownloadUrl, izForceFlush, appVersion} = remoteRes;
  if (compareVersions(appVersion, curVersion) === 1) {
    uni.showModal({
      title: "提示",
      content: "发现新版本,立即升级!",
      confirmText: "确定",
      cancelText: "取消",
      showCancel: izForceFlush !== '1',
      success: function (res) {
        if (res.confirm) {
          uni.showLoading({
            title: '下载中',
            mask: true
          });
          uni.downloadFile({
            url: appDownloadUrl, // 这个是最新版本apk包的地址
            success: (res) => {
              uni.hideLoading();
              if (res.tempFilePath) {
                plus.runtime.install(res.tempFilePath, {force: true}, _res => {
                    uni.showToast({
                      title: "更新成功,重启中",
                      duration: 1500,
                    });
                    plus.runtime.restart();
                  }
                );
              } else {
                uni.showToast({
                  title: "下载失败!",
                  icon: "none",
                });
              }
            },
            fail(err) {
              uni.showToast({
                title: "下载失败!",
                icon: "none",
              });
            }
          })
        }
      }


    })
  }
}

// TODO 你的appStore中的id
const appleId = '';

async function checkIos(remoteRes) {
  const {iosForceFlush, iosAppVersion} = remoteRes;
  let curVersion = uni.getAppBaseInfo().appVersion
  uni.request({
    url: `http://itunes.apple.com/cn/lookup?id=${appleId}`,
    method: 'POST',
    success: (res) => {
      if (res.data.results && res.data.results.length) {
        const onlineVersion = res.data.results[0].version;

        // 服务器版本 > 当前版本 && appStore版本 > 当前版本,则提示更新
        if (compareVersions(onlineVersion, curVersion) === 1 && compareVersions(iosAppVersion, curVersion) === 1) {
          uni.showModal({
            title: '更新提示',
            content: '发现新版本,是否要更新?',
            showCancel: iosForceFlush !== '1',
            success(res) {
              if (res.confirm) {
                plus.runtime.launchApplication(
                  {
                    action: `itms-apps://itunes.apple.com/cn/app/id${appleId}?mt=8`
                  },
                  function (e) {
                    console.log(e.message);
                  }
                );
              }
            }
          })
        }
      }
    }
  });
}


export default async function appUpdate() {
  // #ifdef APP-PLUS
  let system = uni.getSystemInfoSync();
  const [err, res] = await queryAppVersion();
  if (err || !res.result) return;
  if (system.platform === 'ios') {
    checkIos(res.result);
  }
  if (system.platform === 'android') {
    checkAndroid(res.result);
  }
  // #endif
}

queryAppVersion是后台管理配置的版本信息

对比方法:

  • 安卓:比对当前版本和后台管理版本,提示更新
  • IOS:比对当前版本和后台管理版本 && 比对当前版本和应用商店版本,满足则提示更新
  • 同时也会校验后台管理是否配置强制更新,是的话,不显示关闭弹框按钮
<think>我们参考用户的需求:在鸿蒙系统中实现当应用版本号小于API最小版本号时强制跳转应用商店进行更新。用户希望的是强制更新,即当条件满足时,应用必须更新,否则无法使用。这通常是在应用启动时检查。根据提供的引用,我们知道:-引用[1]介绍了Android平台实现自动更新的步骤:检查服务器版本号,与当前版本对比,如果服务器版本更高则进行更新-引用[2]展示了uniapp开发中,通过接口获取最新版本号和下载链接,然后下载并安装(不跳转应用商店)。但是用户要求跳转应用商店-引用[3]展示了iOS应用内跳转AppStore以及获取AppStore内最新版本号的方法。用户的需求是鸿蒙系统(HarmonyOS)下的实现。鸿蒙系统目前有两种应用模型:FA(FeatureAbility)模型和Stage模型。我们假设开发的是传统的JSFA模型(基于Ability和AbilitySlice),但Stage模型在检查版本跳转的逻辑上类似。步骤规划:1.获取应用当前版本号:在鸿蒙中,我们可以通过`bundle.getBundleInfoForSelf`获取当前应用的BundleInfo,从而得到版本信息(版本名和版本号)。2.获取API最小版本号(即服务器要求的最低版本号):这个版本号应该由服务器提供,我们可以通过接口请求获取。但是用户需求中有一个“API最小版本号”,这里可能是指服务器配置的一个最低支持的版本号,低于此版本的应用将强制更新。3.比较当前版本号与API最小版本号:如果当前版本号小于API最小版本号,则强制跳转应用商店。4.跳转应用商店:在鸿蒙系统中,我们可以使用`Intent`跳转到应用市场的详情页(需要知道该应用在应用市场的地址)。不过,目前鸿蒙的应用商店(华为应用市场)的跳转方式与Android类似。注意:鸿蒙系统也支持安装APK(兼容Android应用),但如果是纯鸿蒙应用(使用.hap包),则跳转到华为应用市场。具体实现:1.获取当前版本号:```typescriptimportbundlefrom'@ohos.bundle';//导入bundle模块//在Ability的onCreate或onWindowStageCreate中调用//由于bundle.getBundleInfoForSelf是异步操作,我们使用异步函数处理asyncfunctiongetCurrentVersion():Promise<string>{try{letbundleInfo=awaitbundle.getBundleInfoForSelf(bundle.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION);letappInfo=bundleInfo.appInfo;//一般版本号使用versionCode(数字)或versionName(字符串),这里假设我们要比较的是versionCode(整数)//但注意:鸿蒙中appInfo.versionCode是数字,而服务器返回的可能是字符串,需要转换returnappInfo.versionCode.toString();//或者直接使用versionName:appInfo.versionName}catch(error){console.error('Failedtogetbundleinfo.Error:'+error);return"0";//返回一个默认值,避免出错}}```2.请求服务器获取API最小版本号(假设我们有一个接口返回json,包含minVersion字段):```typescriptimporthttpfrom'@ohos.net.http';//导入http模块asyncfunctiongetMinVersionFromServer():Promise<string>{lethttpRequest=http.createHttp();leturl="http://yourserver.com/api/version";//替换为实际接口地址try{letresponse=awaithttpRequest.request(url,{method:'GET'});if(response.responseCode===200){letresult=JSON.parse(response.result.toString());returnresult.minVersion;//根据服务器返回的字段名}else{console.error(`Requestfailed,code=${response.responseCode}`);return"0";//请求失败,返回0,避免强制更新(或者根据业务逻辑处理)}}catch(error){console.error('Requesterror:'+error);return"0";}finally{httpRequest.destroy();//关闭连接}}```3.比较版本号:这里需要注意的是,版本号可能是字符串形式(如1.2.3)或者整数。我们通常将版本号转换为数字来比较(如果版本号是类似x.x.x的多段式,需要自己定义比较方法,但常见的做法是使用一个整数递增版本号,如每次发布+1)。这里假设版本号是整数(如10102,代表1.1.2)或者字符串格式的纯数字(如"10102"),那么可以直接转换为整数比较。如果版本号是带点的字符串(如"1.1.2"),我们需要将其转换为数字或者分段比较。为了简化,我们假设版本号是整数(versionCode)的比较。```typescript//比较版本号,如果当前版本号小于API最小版本号,返回truefunctioncompareVersion(current:string,minVersion:string):boolean{//将字符串转换为整数letcurrentCode=parseInt(current);letminVersionCode=parseInt(minVersion);//如果转换失败,返回false(避免误判)if(isNaN(currentCode)||isNaN(minVersionCode)){console.error('Versionformaterror');returnfalse;}returncurrentCode< minVersionCode;}```4.跳转应用商店:鸿蒙系统中,跳转到华为应用市场的方法与Android类似。我们可以通过Intent的action和uri来实现。需要注意的是,鸿蒙应用市场的包名和详情页的urischeme。目前,华为应用市场的包名是`com.huawei.appmarket`,我们可以构造一个Intent,设置Action为`"android.intent.action.VIEW"`,然后设置应用的详情页uri(通常为`market://details?id=<包名>`)。但是,在鸿蒙系统中,我们推荐使用`featureAbility`的`startAbility`方法(对于FA模型)或`AbilityContext`的`startAbility`(Stage模型)来跳转。**FA模型示例**:假设我们在AbilitySlice中执行:首先,导入:```typescriptimportfeatureAbilityfrom'@ohos.ability.featureAbility';```然后:```typescriptfunctiongotoAppMarket(){letbundleName="com.example.myapp";//当前应用的包名letintent={bundleName:"com.huawei.appmarket",abilityName:"com.huawei.appmarket.MainActivity",uri:`market://details?id=${bundleName}`};featureAbility.startAbility({want:{action:"android.intent.action.VIEW",uri:intent.uri,bundleName:intent.bundleName,abilityName:intent.abilityName}}).then(()=>{console.info('Jumptoappmarketsuccess');}).catch((err)=>{console.error('Jumptoappmarketfailed.Error:'+JSON.stringify(err));});}```但是,以上方法在鸿蒙上可能不直接支持。另一种更通用的方式是直接使用`ohos.app.ability.Want`并指定参数:```typescriptimportfeatureAbilityfrom'@ohos.ability.featureAbility';functiongotoAppMarket(){//构造Wantletwant={action:"android.intent.action.VIEW",uri:"market://details?id=com.example.myapp",//替换为你的包名//也可以显式指定应用市场的包名和ability,但如果不指定,系统会自动打开默认的应用商店//所以我们可以只设置action和uri};featureAbility.startAbility({want:want}).then(()=>{console.info('Jumptoappmarketsuccess');}).catch((err)=>{console.error('Jumptoappmarketfailed.Error:'+JSON.stringify(err));//如果跳转失败,可以考虑使用浏览器打开网页版应用市场//例如:https://appgallery.huawei.com/app/C100000000});}```注意:鸿蒙系统也支持通过`want`中的`package`参数指定包名(但这里我们使用uri已经指定了目标应用)。5.整合逻辑:在应用启动时(比如在MainAbility的onWindowStageCreate中),进行版本检查,并在需要时跳转。注意,因为跳转应用商店后,我们希望用户更新后重新进入,所以通常我们会结束当前应用。伪代码:```typescriptasyncfunctioncheckVersion(){letcurrentVersion=awaitgetCurrentVersion();letminVersion=awaitgetMinVersionFromServer();if(compareVersion(currentVersion,minVersion)){//需要强制更新//提示用户需要更新//然后跳转应用商店gotoAppMarket();//结束当前应用letcontext=featureAbility.getContext();context.terminateSelf();//结束自己}}```但是,注意:如果用户不更新,我们结束应用后,用户再次打开还是会进入这个流程,只有更新后才能使用。这达到了强制更新的目的。注意事项:-网络请求需要权限:在config.json中配置网络权限(ohos.permission.INTERNET)。-使用应用商店跳转的权限:如果使用显式跳转(指定包名和Ability名)需要知道应用市场的具体信息。华为应用市场的Ability名称可能会变化,所以只使用uri跳转更通用。-错误处理:如果跳转应用商店失败,可以尝试用浏览器打开网页版应用市场。另一种方案:如果鸿蒙应用市场不支持`market`协议,我们可以使用华为应用市场的网页链接。例如:```typescriptletwant={action:"android.intent.action.VIEW",uri:"https://appgallery.huawei.com/app/C100000000"//替换成你应用的AppGallery链接};```因此,根据实际情况选择合适的uri。总结步骤:1.应用启动时,获取当前版本号(通过bundle模块)。2.从服务器获取API最小版本号(通过http模块)。3.比较当前版本号和最小版本号,如果当前版本小于最小版本,则跳转应用商店(华为应用市场)并结束应用。相关引用信息我们整合到回答中。现在,我们生成相关的问题。</think> ### 鸿蒙系统强制更新实现方案 在鸿蒙系统中实现"当应用版本号小于API最小版本号时强制跳转应用商店更新"的功能,需结合本地版本检测和商店跳转逻辑。以下是具体实现方法: #### 1. **获取应用版本信息** ```typescript // 获取当前应用版本号 import bundle from '@ohos.bundle'; async function getAppVersion() { try { const bundleInfo = await bundle.getBundleInfoForSelf(bundle.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION); return bundleInfo.versionCode; // 版本号(整数) 或 versionName(字符串) } catch (error) { console.error('获取版本信息失败: ' + JSON.stringify(error)); return 0; } } ``` #### 2. **对比版本号逻辑** ```typescript // 强制更新判断逻辑 const MIN_API_VERSION = 202; // 预设的API最小版本号 async function checkForceUpdate() { const currentVersion = await getAppVersion(); if (currentVersion < MIN_API_VERSION) { showUpdateDialog(); // 弹出强制更新提示 return true; } return false; } ``` #### 3. **跳转应用商店实现** ```typescript // 鸿蒙跳转应用商店 import common from '@ohos.app.ability.common'; function gotoAppMarket(context: common.UIAbilityContext) { const want = { bundleName: 'com.huawei.appmarket', // 华为应用商店包名 abilityName: 'com.huawei.appmarket.MainActivity', parameters: { appName: '你的应用名称', packageName: context.abilityInfo.bundleName } }; context.startAbility(want).then(() => { console.info('跳转应用商店成功'); context.terminateSelf(); // 关闭当前应用 }).catch(err => { console.error('跳转失败: ' + JSON.stringify(err)); // 备选方案:打开网页版商店 openWebStore(context); }); } // 网页版备选方案 function openWebStore(context: common.UIAbilityContext) { const want = { uri: 'https://appgallery.huawei.com/app/C101000000' // 替换为你的应用ID }; context.startAbility(want); } ``` #### 4. **强制更新提示弹窗** ```typescript // 使用@ohos.promptAction显示模态对话框 import promptAction from '@ohos.promptAction'; function showUpdateDialog() { promptAction.showDialog({ title: '强制更新', message: '当前版本已停止服务,请更新至最新版', buttons: [{ text: '立即更新', color: '#FF0000' }] }).then(result => { if (result.index === 0) { gotoAppMarket(getContext(this)); // 获取上下文后跳转 } }); } ``` #### 5. **入口处添加检查** ```typescript // 在应用启动页的onPageShow中添加 onPageShow() { checkForceUpdate().then(needUpdate => { if (needUpdate) return; // 已触发更新流程 // 正常进入应用的逻辑 }); } ``` ### 关键注意事项 1. **版本号格式** - 使用`versionCode`(整数)而非`versionName`进行对比,避免"1.10.0" < "1.2.0"的字符串比较问题 - 每次发布新版本需在`config.json`递增versionCode ```json "app": { "bundleName": "com.example.app", "version": { "code": 202, // 版本号(整数) "name": "1.2.0" // 显示用版本名 } } ``` 2. **网络权限配置** 在`module.json5`添加网络权限: ```json "requestPermissions": [{ "name": "ohos.permission.INTERNET" }] ``` 3. **备选跳转方案** - 华为设备优先使用`com.huawei.appmarket`包名 - 非华为设备可尝试通用URL Scheme:`"appmarket://details?id=包名"` 4. **服务端配合** - 建议增加API接口获取动态`MIN_API_VERSION`,避免客户端硬编码[^1] > **实现原理**:启动时检测当前版本号 → 与预设API最小版本比对 → 触发强制更新弹窗 → 跳转应用商店 → 关闭当前应用。用户必须更新后才能继续使用[^2][^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值