网络知识 娱乐 UNIAPP中IOS和安卓应用热更新和整包更新app的方法

UNIAPP中IOS和安卓应用热更新和整包更新app的方法

文章目录

  • 前言
  • 一、在应用启动的APP.VUE里增加版本检测代码
  • 二、第二步增加hotupdate包用于处理热更新下载安装包
    • 三、服务器端需要增加一个接口用于查询是否有新版本
  • 总结


前言

公司有一个项目《配送APP》是用uniapp开发的,用于公司几百号骑士员工使用,功能已经很完备,具有分配配送任务,接单,取餐,完成,打卡等功能,用得一直很好,但唯一一个缺点是,当APP功能上有升级时需要通知全体骑手手动把旧版本卸载了,再手工下载新版本安装,更新升级是十分麻烦,尤其年龄稍大一些人员在升级和更新时操作上有些困难,为了解决了这个问题,反反复复百度了一下相关的UNIAPP热更新方案是可以做到的,那我们来一步步的为项目增加热更新和升级的功能

在这里插入图片描述
此方法经验证可以实现android app ,ios app,企业版iosapp的热更新


一、在应用启动的APP.VUE里增加版本检测代码

1.APP.VUE里引入hotupdate包

  import hotupdate from './common/hotupdate.js';
// #ifdef APP-PLUS
			console.log('APP-PLUS 1');
			plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
				uni.setStorageSync("curversion", widgetInfo.version);
				let curversion = widgetInfo.version;
				console.log("当前版本", curversion);
				hotupdate.getAppByVersion(curversion, true);
			});
			// #endif

完整代码如下:

<script>
  // import api from './api/api.js';
  import websocket from './common/websocketStore.js';
  import hotupdate from './common/hotupdate.js';
	export default {
		onLaunch: function() {
			
			console.log('App Launch 1');
			// #ifdef APP-PLUS
			console.log('APP-PLUS 1');
			plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
				uni.setStorageSync("curversion", widgetInfo.version);
				let curversion = widgetInfo.version;
				console.log("当前版本", curversion);
				hotupdate.getAppByVersion(curversion, true);
			});
			// #endif
			
			// 初始换 建立websocket连接
			websocket.dispatch('WEBSOCKET_INIT', "ws://1.1.1.1:9501");
		},
		onShow: function() {
			console.log('App Show')
		},
		onHide: function() {
			console.log('App Hide')
		},
	}
</script>

<style>
	/*每个页面公共css */
</style>

二、第二步增加hotupdate包用于处理热更新下载安装包

1.在项目录的common目录新增加hotupdate.js文件

import api from '../api/api.js';
async function getversion(success, fail) {
	let params = {};
	if (uni.getSystemInfoSync().platform == "ios") {
		params = {
			app: "kdapp",
			type: "ios",
		};
	} else {
		params = {
			app: "kdapp",
			type: "android",
		};
	}
	console.log("api");

	api.version(params, function(res) {
		console.log('version res');
		console.log(res);
		if(res.status == 0)
		{
			if(res.data.version != 1)
			{
				
			}
		}
		else
		{
			console.log('error');
			uni.showToast({
				title: res.msg,
				icon: 'none',    //如果要纯文本,不要icon,将值设为'none'
				duration: 3000    //持续时间为 2});
		}
	});
}
 
function update(fileName) {
	let downURL =  fileName;
	console.log('下载地址', downURL);
	//后台显示进度条
	let dtask = plus.downloader.createDownload(
		downURL, {},
		function(d, status) {
			//下载完成
			uni.showModal({
				title: "更新提示",
				content: "新版本已经准备好,是否更新应用?",
				success: (res) => {
					if (res.confirm) {
						install(d, status);
					}
				},
			});
		}
	);
	start(dtask);
};
 
function start(dtask) {
	try {
		dtask.start(); //开启下载任务
		let prg = 0;
		let showLoading = plus.nativeUI.showWaiting("正在下载");
		dtask.addEventListener("statechanged", function(task, status) {
			switch (task.state) {
				case 1:
					showLoading.setTitle("正在下载");
					break;
				case 2:
					showLoading.setTitle("已连接到服务器");
					break;
				case 3:
					prg = parseInt(
						(parseFloat(task.downloadedSize) /
							parseFloat(task.totalSize)) *
						100
					);
					showLoading.setTitle("  正在下载" + prg + "%  ");
					break;
				case 4:
					plus.nativeUI.closeWaiting();
					break;
			}
		});
 
	} catch (err) {
		plus.nativeUI.closeWaiting();
		uni.showToast({
			title: "更新失败-03",
			mask: false,
			duration: 1500,
		});
	}
};
 
function install(d, status) {
	//下载完成
	if (status === 200) {
		plus.runtime.install(d.filename, {
			force: false
		}, function() {
			plus.nativeUI.closeWaiting();
			plus.nativeUI.alert("应用资源更新完成!是否重启应用!", function() {
				plus.runtime.restart();
			});
		}, function(e) {
			plus.nativeUI.closeWaiting();
			console.log("安装wgt文件失败[" + e.code + "]:" + e.message);
			plus.nativeUI.alert("安装wgt文件失败[" + e.code + "]:" + e.message);
		});
	} else {
		uni.showToast({
			title: "下载失败",
			mask: false,
			duration: 1500,
		});
	}
};
 
function close(version) {
	try {
		console.log( '保存要跳过的版本', version)
	    uni.setStorageSync('skip_version', version);
	} catch (e) {
	    // error
	}
};
 
function signOut() {
	// #ifdef APP-PLUS
	plus.runtime.quit();
	// #endif
}
 
export default{
	getAppByVersion(curversion, back) {
		console.log("came in");
		let params = {};
		if (uni.getSystemInfoSync().platform == "ios") {
			params = {
				app: "kdapp",
				type: "ios",
				appversion: curversion,
			};
		} else {
			params = {
				app: "kdapp",
				type: "android",
				appversion: curversion,
			};
		}
		api.version(params, function(res) {
			console.log('version res');
			console.log(res);
			if (res.status == 0 && res.data) {
				let result = res.data;
				if(back){
					try {
					    const value = uni.getStorageSync('skip_version');
						console.log( '是否跳过当前版本',value, result.version)
					    if (value && value === result.version) {
					        return;
					    }
					} catch (e) {
						
					}
				}
				if (result.version != curversion) {
					console.log('有新版本要更新', result);
					console.log('新版本', result.version);
					console.log('目前版本', curversion);
					result.back = back;
					if (uni.getSystemInfoSync().platform != "ios") {
						plus.nativeUI.confirm("系统提示", function(e) {
							console.log(e); 
							if (e.index == 0) {
								console.log('update');
								update(result.downurl);
							} else if (result.strategy == 'force') {
								signOut();
							} else if (result.strategy == 'recommend') {
								close(result.version);
							}
						}, {
							"title": "新版本",
							"buttons": ["立即更新", result.strategy == 'force' ? "退出应用" : "暂不更新"]
						});
					}
					else
					{
						uni.showModal({
							title:"更新提示",
							content: "请点击按钮复制链接,粘贴到Safari浏览器打开,下载最新版本",
							confirmText: "点击复制",
							showCancel:false,
							success:()=>{
								uni.setClipboardData({
									data:"https://xxxx.xxxxx.xxxx/upload/peisong/index.html",
									success:()=>{
										uni.showToast({
											title:"复制链接成功,请粘贴到Safari浏览器打开"
										})
									}
								})
							}
						});
					}
				} else if (!back) {
					//plus.nativeUI.alert("当前已是最新版本!");
				}
			}
			else if (res.status != 0)
			{
				console.log('error');
				uni.showToast({
					title: res.msg,
					icon: 'none',    //如果要纯文本,不要icon,将值设为'none'
					duration: 3000    //持续时间为 2});
			}else if (!back) {
					//plus.nativeUI.alert("当前已是最新版本!");
			}
		});
		
	}
	
}

三、服务器端需要增加一个接口用于查询是否有新版本

如果有返回新版本的详细信息,包括下载地址,这里简单提供一下存储app版本的mysql数据表结构,每个版本的每一端存放一条记录

CREATE TABLE `my_db`.`dbpree_app_version`(
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `type` varchar(20)  NOT NULL default '' COMMENT 'type: android ios ',
  `version` varchar(32)  NOT NULL default '' COMMENT 'app版本号',
  `is_new` tinyint(1)  NOT NULL default '0' COMMENT '是否最新版本',
  `des` varchar(255)  NOT NULL default '' COMMENT '版本描述',
  `downurl` tinyint(1)  NOT NULL default '0' COMMENT '下载地址',
  `add_time` int(10) UNSIGNED NOT NULL default 0 COMMENT '添加时间',
  PRIMARY KEY (`id`),
  INDEX `type`(`type`),
  INDEX `version`(`version`),
  INDEX `is_new`(`is_new`)
)ENGINE=InnoDB AUTO_INCREMENT=1;

简单的PHP查询数据库后返回的版本信息:

if($receive_data['c'] == 'version'){
    $type = $_REQUEST['type'] ? trim($_REQUEST['type']) : '';
    $sql = "select * from " . $GLOBALS['site']->table('app_version') . " where is_new=1 and type='$type'";
    $version = $db->getRow($sql);
    if($version){
        appMake_json_result($version);
    }else{
        appMake_json_error(3001, "没有查到对应版本信息");
    }
}

基本上这样就实现的uniapp打包的anorid和ios app的热更新的效果,非常好用


总结

uniapp实现app热更新,经过简单改进就可以用上,挺不错的,分亨出来供大家参考。最后,提醒一下,android,ios 和企业版ios的应用下载方式和不一样:
android 直接下载就可以了
ios 可以提示跳到苹果的应用市场
企业版的ios 可以提示复制下载地址后,到Safari浏览器粘贴地址下载的方式实现更新

文章中的方法项目组中的张同学也参与了开发与测试

如有问题请留言反馈,若对您有帮助,请帮点个赞,谢谢!