uniAPP Android端内部更新与热更新

1,722 阅读2分钟

一:综述: 1.uni-app打包成apk或wgt文件,使用plus.runtime.getProperty方法获取本地应用资源版本号。 2.调用后端接口,拿到与后端规定好的版本号,与前面获取的版本号进行对比,如果不一致(也可以判断当前版本号是否小于线上版本号,也就是最新版本号),进行下一步操作。 3.uni.showModal或其他弹出框弹出下载提示。 4.使用plus.downloader.createDownload下载安装包。下载完可以使用plus.runtime.openFile(path),打开文件安装。 5.另一种方法是去浏览器下载,使用plus.runtime.openURL(url); 打开一个网址去下载。 6.推荐的方法是使用wgt热更新,这样就不用每次更改都需要对ios包进行加签。这种方法着重记一下。

以上方法详情详见:plus文档地址

二:整包更新 1.HbuilderX打包及其步骤 HbuilderX App选择发行=>原生App-云打包

HbuilderX App云打包,证书可以由公司安卓开发人员提供,打安卓包也可以使用公共测试证书进行测试。打包完成会返回一个下载地址,在浏览器下载即可。将下载后的安卓包上传到公司的服务器下载地址。

前端关键代码 前端关键代码(APP.vue)创建下载资源的下载任务并弹出相应提示信息的弹窗,这里使用plus的api进行操作。

    // #ifdef APP-PLUS
   const dtask = plus.downloader.createDownload(this.$store.state.url,{force : true},function(d,status){
					// 下载完成
					if(status == 200){
						var path = (d.filename);//文件安装路径
						plus.runtime.install(path,{},function(){
							plus.nativeUI.closeWaiting();//关闭系统等待对话框
							if(name == 'wgt'){
								console.log("安装wgt文件成功!");
							}else{
								console.log("安装apk文件成功!")
							}
							
							plus.nativeUI.alert("引用资源更新完成!",function(){
								plus.runtime.restart();
							})
						},function(e){
							plus.nativeUI.closeWaiting();//关闭系统等待对话框
							if(name == 'wgt'){
								console.log("安装wgt文件失败["+e.code+"]:"+e.message);
								plus.nativeUI.alert("安装wgt文件失败["+e.code+"]:"+e.message);
							}else{
								console.log("安装apk文件失败["+e.code+"]:"+e.message);
								plus.nativeUI.alert("安装apk文件失败["+e.code+"]:"+e.message);
							}
							
						})
						
					}else{
						alert("Download failed:"+status);
					}
				})
    // #endif

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 三:wgt热更新 1.wgt打包 HbuilderX App选择发行=>原生App-制作应用wgt包

生成wgt包,将其放于服务器下载端。

可能存在的问题:使用wgt文件升级问题,安装wgt文件失败[-1205],WGT安装包中mainfest.json文件的version版本不匹配。 解决方法1,把线上的version版本号的首个数字调高;

解决方法2,在安装WGT的时候,添加一个参数,不进行版本对比。force: true

前端关键代码 App.vue

   getVersionNumber(){//获取版本号
		var _self = this;
		this.$http('/wangge/systemManage/getLastVersion',{citycode:this.citycode},'GET').then(res=>{
			console.log(res)
			console.log(this.$store.state)
			if(res.data.result && res.data.result.length>0){
				//保存版本号
				this.AppVersion(res.data.result[0]);
				//获取下载地址
				let url = res.data.result[0].url;
				let arr = url.split('.');
				let name = arr[arr.length-1];
				console.log(arr,name);
				if( Number(res.data.result[0].versioncode) > Number(this.$store.state.versionCode) ){//是否有新的版本
				
					//下载热更新资源包 不比较版本
					const dtask = plus.downloader.createDownload(this.$store.state.url,{force : true},function(d,status){
						// 下载完成
						if(status == 200){
							var path = (d.filename);//文件安装路径
							plus.runtime.install(path,{},function(){
								plus.nativeUI.closeWaiting();//关闭系统等待对话框
								if(name == 'wgt'){
									console.log("安装wgt文件成功!");
								}else{
									console.log("安装apk文件成功!")
								}
								
								plus.nativeUI.alert("引用资源更新完成!",function(){
									plus.runtime.restart();
								})
							},function(e){
								plus.nativeUI.closeWaiting();//关闭系统等待对话框
								if(name == 'wgt'){
									console.log("安装wgt文件失败["+e.code+"]:"+e.message);
									plus.nativeUI.alert("安装wgt文件失败["+e.code+"]:"+e.message);
								}else{
									console.log("安装apk文件失败["+e.code+"]:"+e.message);
									plus.nativeUI.alert("安装apk文件失败["+e.code+"]:"+e.message);
								}
								
							})
							
						}else{
							alert("Download failed:"+status);
						}
					})
					
					//弹出框是否下载最新版本
					 this.$showModal({
						title:'更新',
						concent:'有新版本,是否更新~',
						cancelVal:'下次再说',
						confirmVal:'立即更新'
						}).then(res=>{
							dtask.start();
							let prg = 0;  
							let showLoading = plus.nativeUI.showWaiting("正在下载");  
							dtask.addEventListener('statechanged', function(task, status) {  
							// 给下载任务设置一个监听 并根据状态  做操作  
							switch (task.state) {  
							    case 1:  
							      showLoading.setTitle("正在下载");  //显示loading提示框,title为提示的文字内容,显示在loading的下方
							      break;  
							    case 3:  
							      prg = parseInt((parseFloat(task.downloadedSize) / parseFloat(task.totalSize)) * 100);  
							      showLoading.setTitle("  正在下载" + prg + "%  ");  
							      break;  
							    case 4:  
							      plus.nativeUI.closeWaiting();  
							      //下载完成  
							      break;  
							      }  
							})
							/* plus.runtime.openURL(this.$store.state.url); */ 
						//确认
						}).catch(res=>{
						//取消
						// 不更新
						// console.log(res);
						})
				}else{
				}
			}
		})
		
	},

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 index.js

	getAppInfo(state,response){//获取版本号
		state.version = response.version;
		state.versionCode = response.versionCode
	},
	AppVersion(state,response){//服务器版本
		state.serverversion = response.versionname
		state.serverversionCode = response.versioncode
		state.url = response.url
	}, 

1 2 3 4 5 6 7 8 9 使用情况及注意事项 不支持的情况

SDK 部分有调整,比如新增了 Maps 模块等,不可通过此方式升级,必须通过整包的方式升级。 如果是老的非自定义组件编译模式,之前没有 nvue 文件,但更新中新增了 nvue 文件,不能使用此方式。因为非自定义组件编译模式如果没有nvue文件是不会打包weex引擎进去的,原生引擎无法动态添加。自定义组件模式默认就含着weex引擎,不管工程下有没有nvue文件。 原生插件的增改,同样不能使用此方式。 注意事项

条件编译,仅在 App 平台执行此升级逻辑。 appid 以及版本信息等,在 HBuilderX 真机运行开发期间,均为 HBuilder 这个应用的信息,因此需要打包自定义基座或正式包测试升级功能。 plus.runtime.version 或者 uni.getSystemInfo() 读取到的是 apk/ipa 包的版本号,而非 manifest.json 资源中的版本信息,所以这里用 plus.runtime.getProperty() 来获取相关信息。 安装 wgt 资源包成功后,必须执行 plus.runtime.restart(),否则新的内容并不会生效。 如果App的原生引擎不升级,只升级wgt包时需要注意测试wgt资源和原生基座的兼容性。平台默认会对不匹配的版本进行提醒,如果自测没问题,可以在manifest中配置忽略提示,详见ask.dcloud.net.cn/article/356… www.example.com 是一个仅用做示例说明的地址,实际应用中应该是真实的 IP 或有效域名,请勿直接复制粘贴使用。 关于热更新是否影响应用上架 应用市场为了防止开发者不经市场审核许可,给用户提供违法内容,对热更新大多持排斥态度。

但实际上热更新使用非常普遍,不管是原生开发中还是跨平台开发。

Apple曾经禁止过jspatch,但没有打击其他的热更新方案,包括cordovar、react native、DCloud。封杀jspatch其实是因为jspatch有严重安全漏洞,可以被黑客利用,造成三方黑客可篡改其他App的数据。

使用热更新需要注意:

上架审核期间不要弹出热更新提示 热更新内容使用https下载,避免被三方网络劫持 不要更新违法内容、不要通过热更新破坏应用市场的利益,比如iOS的虚拟支付要老老实实给Apple分钱 如果你的应用没有犯这些错误,应用市场是不会管的。

四:跳转到浏览器下载apk 1.步骤 获取服务器下载地址,通过调用plus.runtime.openURL(url); 去第三方浏览器打开一个网址去下载相应apk。

前端关键代码 //弹出框是否下载最新版本 this.showModal({ title:'更新', concent:'有新版本,是否更新~', cancelVal:'下次再说', confirmVal:'立即更新' }).then(res=>{ plus.runtime.openURL(this.store.state.url);//url为服务器端下载地址 //确认 }).catch(res=>{ //取消 // 不更新 // console.log(res); })

版权声明:本文为CSDN博主「圣焱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/Bruce_byan/…