HBuilderX实现uniapp项目打包成app后-实现app内热更新和大版本更新

1,886 阅读5分钟
需求说明:要给HBuilder创建的uniapp项目,项目完成之后打包成安卓app,用户安装到手机上,后期如果小版本更新时要求做到用户无感更新,大版本更新时apk整包下载替换原安装包,具体实现步骤如下:

一. 实现前须知:

  1. 要知道manifest.json文件里面是配置相关信息-->应用标识id,应用名称、应用版本名称、应用版本号... (应用版本名称 这个参数是更新时需要对比的参数,很重要!!! 例如->当前应用内的版本号version1,二次开发打包的版本号version2 后台开启更新选项时若version2>version1,从接口获取二开后上传的下载wgtUrl实现热更新/实现apk整包更新)
  2. app项目在初始运行时加载App.vue文件更早,后面我们实现的热更新功能就在App.vue里书写代码逻辑(根据需要其实在哪个页面都可以更)
  3. ① uni.getSystemInfoSync()方法获取本地应用资源版本号 ②热更新用plus.downloader.createDownload下载wgt安装包-->下载完使用plus.runtime.install安装。 ③ apk包更新是去浏览器下载,使用plus.runtime.openURL(url); 打开网址下载,安装后替换原来apk包

注:以上方法网上都可找到学习资源,有疑问咱们评论区见🤡

二. 实现过程:

1. App.vue里的created()方法里或者onLaunch:function(){}里其实都ok

created() {
  // // #ifdef APP-PLUS和#endif  实现只在app内调此方法
  // #ifdef APP-PLUS
    this.AppUpdateInfo() //我们实现更新的方法
  // #endif
},

methods: {
   async AppUpdateInfo(){
     const systemInfo = uni.getSystemInfoSync();
     //从接口获取是否需要更新的参数,对比确定是否更新和哪种更新
     let result = await back_channel_list({id:'14'})	
     //未更新前已下载app版本号systemInfo.appWgtVersion
     let isupData=this.compareVersion(result.edition,systemInfo.appWgtVersion)
     //未更新前app版本号小于接口传入版本号则需要更新,否则不需要
     if (isupData==1) {
	     //需要更新
	     uni.showModal({
		title: 'TIPS',
		content: result.update_content?result.update_content:'Found a new version to upgrade',
		cancelText: 'Cancel update',
		confirmText: 'Update now',
		success: res1 => {
		     if (res1.confirm) {
		        // last_update_type后台接口设置 2热更新 1大版本更新 其他不更新
			if (result.last_update_type==2) { 
			   //热更新 wgturl
			    this.downWgt(result.wgt_url)
		        } else if(result.last_update_type==1){
			   //大版本apk更新 apkurl
			    this.downApk(result.download_url)
			}else{
			   //不做更新
			}
		     } else if (res1.cancel) {
                        //重启app
			// plus.runtime.restart();
			//退出app
			// plus.runtime.quit(); 
		      }
		},
		fail: (err) => {
		   // console.log('下载失败', err);
		}
	})
}
},
//根据后端传过来的wgturl下载wgt文件包
downWgt(url) {
   uni.showLoading({title: 'please wait...',mask:true})
   let that=this  //重点!!! 不然不生效
   plus.downloader.createDownload( url, {filename:"_doc/update/"}, function(d,status){
	if ( status == 200 ) {
	  // console.log("下载wgt成功:"+d.filename);
	  uni.hideLoading()
	  that.installWgt(d.filename); // 安装wgt包
	} else {
	  uni.hideLoading()
	  // console.log("下载wgt失败!");
	plus.nativeUI.alert("Update file download failed!",function(){},'','confirm');
        }
   }).start();
},
//大版本apk更新时--网页打开apkurl地址下载
downApk(url) {
   let platform = uni.getSystemInfoSync().platform;
   if (platform === 'android') {
      plus.runtime.openURL(url);
   } else {
      //可做其他处理,目前随便写的
      plus.runtime.openURL(url);
   }
},
//热更时下载完包开始热更新wgt资源
installWgt(path){
  // 打开安装loading
  plus.nativeUI.showWaiting("wait a minute...");
  plus.runtime.install(path,{force:false},function(){
     plus.nativeUI.closeWaiting();
     // console.log("安装wgt文件成功!");
     plus.nativeUI.alert("install successfully!",function(){
	plus.runtime.restart(); 
     },'','confirm');
  },function(e){
     plus.nativeUI.closeWaiting();
     // console.log("安装wgt文件失败["+e.code+"]:"+e.message);
     plus.nativeUI.alert("fail to install ["+e.code+"]:"+e.message,function(){},'','confirm');
   });
   //关闭loading
     plus.nativeUI.closeWaiting();
},
   //版本号大小对比 v2>v1 返回值为1 需要更新
compareVersion(v1, v2) {
  v1 = v1.split('.')
  v2 = v2.split('.')
  const len = Math.max(v1.length, v2.length)
  while (v1.length < len) {
          v1.push('0')
	}
  while (v2.length < len) {
	  v2.push('0')
	}
  for (let i = 0; i < len; i++) {
      const num1 = parseInt(v1[i])
      const num2 = parseInt(v2[i])
      if (num1 > num2) {
	return 1
      } else if (num1 < num2) {
	return -1
      }
     }
     return 0
   }
 },

2. 提前和后端协定好后台配置的关于热更新和大版本整包更新的一些参数,本文代码涉及的参数大致有以下几个重要参数:

AC7C4B06-AD8F-4144-AFE7-D4C0C1ABB678-37012-00000F45E406D420.png

① download_url-->后台上传apk文件生成的apk下载链接 ②edition当前更新包的版本号 ③last_update_type设置是否需要更新 值为 1大版本更新2热更新 其他不更新 ④update_content本次新版本更新内容 ⑤wgt_url后台上传wgt文件生成的wgt下载链接

--->还有兄弟不会apk包和wgt包怎么打吗?

image.png

-----热更新 1.wgt打包 HbuilderX App选择发行=>原生App--制作应用wgt包 生成的

-----整包更新 1.apk打包 HbuilderX App选择发行=>原生App-云打包成功后通过链接下载下来的既是

三. 调试需注意:

真机调试时,设置错很容易出现没更新弹框,该有的效果没出现一类的问题

  • 完成后的项目先安装到手机或者连上手机线,手机权限打开运行到手机上

image.png

  • 需要热更的新需求整完,保存代码,找到manifest.json文件打开更改下应用版本名称应用版本号,一定要大于之前安装的那个(例如之前包版本号是1.0.0 这次必须是1.0.1或者更大)设置完保存重新打包成wgt和apk,随后在后台页面给最新的包上传上去,改下版本号(和现在上传的新包一定要保持一致),更新类型和内容按照自己需求设置
  • 1.如果在手机上联机运行的,测试时把manifest.json版本号还原到之前1.0.0,因为联机是同步的,还原后再进入手机app,上述环节没问题情况下就会弹出更新提示。2.如果是安装的apk包,就不用上述过程,直接进入app就会有提示更新
  • 有些情况下是必须整包apk更新才生效的,例如:在App模块配置新增了 Maps 模块或者其他,不可通过此方式升级,必须通过整包的方式升级。页面优化,新增页面和方法,只要是配置外的一些东西,热更新就好
  • 这玩意测试时某个细节搞错也是实现不了的,出现问题要认真检查后台设置和代码,做好打印排查

四. 结果:

到这我们就实现了app wgt热更新和apk整包更新 需要更新时提示,点击现在更新-->热更就开始

刚开始实现如果不顺利的话,多实验几次,多看看,方法要形成闭环,控制台多打印,我这也并非最优解,有不同观点的大神欢迎一起沟通,共同进步

0C9E0D71-A5E1-4492-B4E2-3EA83F1A99F8.png