对于移动app,尤其是webapp,如何更新一直是比较重要的话题。以前的大部分app都是从应用商店进行版本更新,但是对于webapp来说,使用增量更新可以节省流量;更重要的是,它免去了新版本在应用商店的审核流程,使上架时间可以更加提前了。
一、前提
环境:使用html5plus作为webview与手机平台交互的中间件;关于html5plus,请自行参考 http://www.html5plus.org/#home
需求:点击“检查更新”,app在线检查版本是否有更新,如果有,下载并更新;
更新包后缀名为.wgt,制作方式:使用zip打包所有项目根目录下的html/js/css/images/manifest.json;其中:manifest.json不能有注释,否则在ios下将会更新失败;
二、 实现:
1. 检查更新按钮:
2. update.js:
function CheckUpdate(auto) {
//API的GET请求地址
var CheckUrl = "http://app.zimayun.com/REST/CheckUpdate?appkey=" + APPKey + "&clientversion="
+ plus.runtime.version;
var RequestResponse = new Object();
RequestResponse.Success = function(Result) {
UnLoading();
var ResultObject = JSON.parse(Result);
if (ResultObject.apicode == 0) { //当api返回code为0表示成功
if (ResultObject.needupdate) {
// MessageBox("需要更新", function() {
// MessageBox("下载包地址:" + ResultObject.url, function() {
ConfirmBox("有新版本,是否更新?", function() {
document.getElementById("Progress_Button").style.cssText = "display: block;";
console.log(document.getElementById("Progress_Button").style.cssText);
UpdateKey = ResultObject.updatekey;
// DownLoadFile(ResultObject.url);
DownLoadFile(serverHost + "/app/update.wgt");
}, function() {
return;
});
// });
// });
} else {
if (!auto) {
MessageBox("不需要更新", function() {});
}
}
} else {
if (!auto) {
ShowError();
}
}
}
RequestResponse.Error = function(Result) {
UnLoading();
ShowError();
}
console.log(CheckUrl);
//发送请求
SendData(CheckUrl, RequestResponse); //发送POST
}
//完成更新
function FinishUpdate() {
//API的GET请求地址
var UpdateUrl = "http://app.zimayun.com/REST/FinishUpdate?updatekey=" + UpdateKey;
UpdateUrl = UpdateUrl + "&model=" + encodeURIComponent(GetDeviceInfo().Model);
UpdateUrl = UpdateUrl + "&vendor=" + encodeURIComponent(GetDeviceInfo().Vendor);
UpdateUrl = UpdateUrl + "&uuid=" + encodeURIComponent(GetDeviceInfo().UUID);
UpdateUrl = UpdateUrl + "&screen=" + encodeURIComponent(GetDeviceInfo().Screen);
UpdateUrl = UpdateUrl + "&dpi=" + encodeURIComponent(GetDeviceInfo().DPI);
UpdateUrl = UpdateUrl + "&networkinfo=" + encodeURIComponent(GetDeviceInfo().NetworkInfo);
UpdateUrl = UpdateUrl + "&oslanguage=" + encodeURIComponent(GetDeviceInfo().OS.Language);
UpdateUrl = UpdateUrl + "&osversion=" + encodeURIComponent(GetDeviceInfo().OS.Version);
UpdateUrl = UpdateUrl + "&osname=" + encodeURIComponent(GetDeviceInfo().OS.Name);
UpdateUrl = UpdateUrl + "&osvendor=" + encodeURIComponent(GetDeviceInfo().OS.Vendor);
var RequestResponse = new Object();
RequestResponse.Success = function(Result) {
var ResultObject = JSON.parse(Result);
if (ResultObject.apicode == 0) { //当api返回code为0表示成功
} else {
//ShowError();
}
}
RequestResponse.Error = function(Result) {}
//发送请求
SendData(UpdateUrl, RequestResponse); //发送POST
}
//下载
function DownLoadFile(url) {
var d = plus.downloader.createDownload(url, {}, function(f, s) {
document.getElementById("Progress_Button").style.cssText = "display: none;";
ConfirmBox("下载完成,是否立即更新", function() {
// console.log(f.filename)
/*
* unzip the folder..
*/
// plus.zip.decompress( f.filename, "_doc/", function(){alert("decompress success!")}, function(err){
// alert(JSON.stringify(err));
// });
plus.runtime.install(f.filename, {force:true}, function() {
//完成更新向服务器进行通知
alert("更新完毕,将重启应用!");
FinishUpdate();
plus.runtime.restart();
},function(err){
alert(JSON.stringify(err));
mui.toast("安装升级失败");
});
}, function() {
return;
});
}, function() {
MessageBox("下载失败", function() {});
});
d.addEventListener('statechanged', function(download, status) {
// console.log(JSON.stringify(download));
if (download.state == 3 && status == 200) {
var percent = Math.round((download.downloadedSize / download.totalSize) * 100);
document.getElementById("Progress_Button").innerHTML = (percent + "%");
} else if (download.state == 4) {}
}, false);
d.start();
}
//确认消息
function ConfirmBox(MSG, OKFN, CancelFN) {
plus.nativeUI.confirm(MSG, function(e) {
if (e.index == 0) {
OKFN();
} else {
CancelFN();
}
}, "提示", ["确定", "取消"]);
}
//发送数据
function SendData(URL, ResponseObject) {
var MyXMLHttpRequest = new plus.net.XMLHttpRequest();
MyXMLHttpRequest.onreadystatechange = function() {
switch (MyXMLHttpRequest.readyState) {
case 0:
break;
case 1:
break;
case 2:
break;
case 3:
break;
case 4:
if (MyXMLHttpRequest.status == 200) {
ResponseObject.Success(MyXMLHttpRequest.responseText);
} else {
plus.nativeUI.toast("检查更新出错");
}
break;
}
}
MyXMLHttpRequest.open("GET", URL);
MyXMLHttpRequest.send();
}
//获得系统信息
function GetDeviceInfo() {
var device = {
IMEI: plus.device.imei,
IMSI: "",
Model: plus.device.model,
Vendor: plus.device.vendor,
UUID: plus.device.uuid,
Screen: plus.screen.resolutionWidth * plus.screen.scale + " x " + plus.screen.resolutionHeight * plus.screen.scale + "",
DPI: plus.screen.dpiX + " x " + plus.screen.dpiY,
OS: new Object()
};
for (var i = 0; i < plus.device.imsi.length; i++) {
device.IMSI += plus.device.imsi[i];
}
var types = {};
types[plus.networkinfo.CONNECTION_UNKNOW] = "未知";
types[plus.networkinfo.CONNECTION_NONE] = "未连接网络";
types[plus.networkinfo.CONNECTION_ETHERNET] = "有线网络";
types[plus.networkinfo.CONNECTION_WIFI] = "WiFi网络";
types[plus.networkinfo.CONNECTION_CELL2G] = "2G蜂窝网络";
types[plus.networkinfo.CONNECTION_CELL3G] = "3G蜂窝网络";
types[plus.networkinfo.CONNECTION_CELL4G] = "4G蜂窝网络";
device.NetworkInfo = types[plus.networkinfo.getCurrentType()];
device.OS = {
Language: plus.os.language,
Version: plus.os.version,
Name: plus.os.name,
Vendor: plus.os.vendor
};
return device;
}
其中,
plus.runtime.install(f.filename, {force:true}, function() {
这一行,{force:true} 这个参数必不可少。这是由于在安卓下目前还有一些bug,必须要加上。
实现效果:当用户点击检查更新,先检查是否更新;如果需要更新,则下载zip格式的.wgt文件,调用plus.runtime.install进行安装,安装成功后弹出成功,然后自动重启应用。