接口约定
如下数据接口约定仅为示例,开发者可以自定义接口参数。
请求地址:https://www.xxxx.com/update
请求方法:GET
请求数据:
{
"appid": plus.runtime.appid, //包名
"version": plus.runtime.version,//版本
"name":plus.os.name
}
响应数据:
{
"status":1, // 升级标志,0:无需更新 1:整包更新 2 热更新;
"note": "修复bug1", // 更新描述
"url": "http://www.xxxx.com/uniapp.apk" //更新包下载地址
}
客户端实现
App启动时,向服务端上报当前版本号,服务端判断是否提示升级。
在App.vue的onLaunch中,发起升级检测请求,如下:
<script>
export default {
onLaunch: function() {
//#ifdef APP-PLUS
var server = "https://www.xxxx.com/update"; //检查更新地址
var req = { //升级检测数据
"appid": plus.runtime.appid,
"version": plus.runtime.version,
"name": plus.os.name
};
uni.request({
url: server,
data: req,
success: (res12) => {
// 整包更新
if (res12.statusCode == 200 && res12.data.status === 1) {
uni.showModal({
title: "版本更新",
content: res12.data.note,
confirmText: '立即更新',
cancelText: '稍后进行',
success: function(res) {
if (res.confirm) {
var downloadApkUrl = res12.data.url;//apk下载的地址
var dtask = plus.downloader.createDownload(downloadApkUrl, {},function(d, status) {//新建下载任务
if (status == 200) {//当下载完成
plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {}, {}, function(error) {//安装应用
uni.showToast({
title: '安装失败',
duration: 1500,
icon: 'none'
});
})
} else {
uni.showToast({
title: '更新失败',
duration: 1500,
icon: 'none'
});
}
})
dtask.start();
var prg = 0;
var 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;
}
});
}
}
})
}
// 热更新
if (res12.statusCode == 200 && res12.data.status === 2) {
uni.downloadFile({
url: res12.data.url,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
plus.runtime.install(downloadResult.tempFilePath, {
force: false
}, function() {
console.log('install success...');
plus.runtime.restart();
}, function(e) {
console.error('install fail...');
});
}
}
});
}
}
})
//#endif
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
<style>
/*每个页面公共css */
</style>
后端
注:state设为0则无需更新,设为1则整包更新,设2则为热更新
<?php
header("Content-type:text/json");
$appid = $_GET["appid"];
$version = $_GET["version"]; //客户端版本号
$name = $_GET['name'];
$rsp = array("status" => 0); //默认返回值,不需要升级
if (isset($appid) && isset($version)) {
if ($appid === "__UNI__Cxxxxx5") { //校验appid
if ($version !== "1.0.1") { //这里是示例代码,真实业务上,最新版本号及relase notes可以存储在数据库或文件中
// 1为整包更新,2为热更新
$rsp["status"] = 1;
if( $rsp["status"]==1){
$rsp["note"] = "修复bug1;\n修复bug2;"; //release notes
if ($name=="Android") {
$rsp["url"] = "https://xxxx.com/sc.apk"; // Android下载地址
}else{
$rsp["url"] = "itms-apps://itunes.apple.com/cn/app/******"; // IOS下载地址
}
}else{
$rsp["url"]='http://www.xxxx.com/__UNI__Fxxxxx5.wgt'; // 热更新包
}
}
}
}
echo json_encode($rsp);
exit;
注意以下只能整包更新:
(1)SDK 部分有调整,比如新增了 Maps 模块等,不可通过此方式升级,必须通过整包的方式升级。
(2)原生插件的增改,使用整包更新方式。
(3)对于老的非自定义组件编译模式,这种模式已经被淘汰下线。但以防万一也需要说明下,老的非自定义组件编译模式,如果之前工程没有 nvue 文件,但更新中新增了 nvue 文件,不能使用此方式。因为非自定义组件编译模式如果没有nvue文件是不会打包weex引擎进去的,原生引擎无法动态添加。自定义组件模式默认就含着weex引擎,不管工程下有没有nvue文件。