背景说明
最近参与公司开发一款移动端App,由于原生开发成本较大(没有人会原生开发),最终公司决定采用H5+cordova实现web打包App。再多次尝试之后,我们开发出来了第一版系统,并成功发版。不可避免的(bug、新的需求)提上来了,对系统进行修改之后,升级就成了一个大难题(技术不熟练)。我们采用了每次升级让用户卸载再重新下载新的版本安装。在用户体验上成了老大难....
解决方案
查阅相关资料,我们发现web打包app升级主要分为两种方式:手动升级、和自动更新。这两种方式各有优缺点。下面是我的踩坑之旅
手动升级
百度H5 APP cordova 升级,获取到的大多数都是下面的自动更新的方法,在我们的App升级中很多时候不满足使用要求,针对新增cordova插件等情况也完全不够用;另外一种就是借助各种cordova插件,由于我们App具有一些特殊需求,网上的自动升级插件在很多方面不能实现期望的效果。最终只能自己想办法解决。在经过一轮讨论之后,我们定下了如下流程:
下面我们就跟着上面的流程图来实现相关功能。
获取当前版本号
借助cordova-plugin-app-version插件,可以获取当前版本信息,具体使用方法如下:
// 安装插件cordova-plugin-app-version(命令如下,不会用的百度cordova插件安装)
cordova plugin add cordova-plugin-app-version
// 获取版本号
var getVersion = function() {
cordova.getAppVersion.getVersionNumber().then(version => {
console.log(version)
})
}
注意:
- 该方法获取的版本号是Cordova项目下config.xml中所设置的version值(如下图所示)
- 该方法在H5中使用必须在window.onload执行之后(H5DOM元素加载完毕)
获取最新版本号
此处我采用的是建立一个web服务器,并在该服务器中建了一个json文件,在json文件中保存app历次版本信息(根据自己的情况来定,此处不做说明)
提示最新的版本
展示历史版本信息
下载最新版本并安装
借助cordova-plugin-file、cordova-plugin-file-transfer和cordova-plugin-file-opener2插件。其中cordova-plugin-file获取程序相关目录,cordova-plugin-file-transfer实现文件上传功能,cordova-plugin-file-opener2实现打开本地文件。
// 定义全局下载函数
document.addEventListener("deviceready", onDeviceReady, false)
function onDeviceReady() {
console.log(FileTransfer)
}
// 设置文件本地保存目录
var saveUrl = cordova.file.externalDataDirectory + 'fileName'
// 下载保存并安装
var down = new FileTransfer()
down.download(
url: '远程文件所在目录',
saveUrl,
function(entry) {
let url = entry.toURL()
cordova.plugins.fileOpener2.open(url, fileMIMEType, {
error: function(e) {
console.log('open fail')
},
success: function() {
console.log('open successfully')
}
})
}
)
fileMIMEType可取的值
{".3gp", "video/3gpp"},
{".apk", "application/vnd.android.package-archive"},
{".asf", "video/x-ms-asf"},
{".avi", "video/x-msvideo"},
{".bin", "application/octet-stream"},
{".bmp", "image/bmp"},
{".c", "text/plain"},
{".class", "application/octet-stream"},
{".conf", "text/plain"},
{".cpp", "text/plain"},
{".doc", "application/msword"},
{".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
{".xls", "application/vnd.ms-excel"},
{".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
{".exe", "application/octet-stream"},
{".gif", "image/gif"},
{".gtar", "application/x-gtar"},
{".gz", "application/x-gzip"},
{".h", "text/plain"},
{".htm", "text/html"},
{".html", "text/html"},
{".jar", "application/java-archive"},
{".java", "text/plain"},
{".jpeg", "image/jpeg"},
{".jpg", "image/jpeg"},
{".js", "application/x-javascript"},
{".log", "text/plain"},
{".m3u", "audio/x-mpegurl"},
{".m4a", "audio/mp4a-latm"},
{".m4b", "audio/mp4a-latm"},
{".m4p", "audio/mp4a-latm"},
{".m4u", "video/vnd.mpegurl"},
{".m4v", "video/x-m4v"},
{".mov", "video/quicktime"},
{".mp2", "audio/x-mpeg"},
{".mp3", "audio/x-mpeg"},
{".mp4", "video/mp4"},
{".mpc", "application/vnd.mpohun.certificate"},
{".mpe", "video/mpeg"},
{".mpeg", "video/mpeg"},
{".mpg", "video/mpeg"},
{".mpg4", "video/mp4"},
{".mpga", "audio/mpeg"},
{".msg", "application/vnd.ms-outlook"},
{".ogg", "audio/ogg"},
{".pdf", "application/pdf"},
{".png", "image/png"},
{".pps", "application/vnd.ms-powerpoint"},
{".ppt", "application/vnd.ms-powerpoint"},
{".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
{".prop", "text/plain"},
{".rc", "text/plain"},
{".rmvb", "audio/x-pn-realaudio"},
{".rtf", "application/rtf"},
{".sh", "text/plain"},
{".tar", "application/x-tar"},
{".tgz", "application/x-compressed"},
{".txt", "text/plain"},
{".wav", "audio/x-wav"},
{".wma", "audio/x-ms-wma"},
{".wmv", "audio/x-ms-wmv"},
{".wps", "application/vnd.ms-works"},
{".xml", "text/plain"},
{".z", "application/x-compress"},
{".zip", "application/x-zip-compressed"},
{"", "*/*"}
————————————————
cordova-plugin-file 可获取的本地文件目录
//当前程序的目录
console.info(cordova.file.applicationDirectory);
//程序的数据目录
console.info(cordova.file.applicationStorageDirectory);
//程序的数据目录
console.info(cordova.file.dataDirectory);
//程序的暂存目录
console.info(cordova.file.cacheDirectory);
//Android扩展存储应用目录
console.info(cordova.file.externalApplicationStorageDirectory);
//Android扩展存储数据目录
console.info(cordova.file.externalDataDirectory);
//Android扩展存储缓存目录
console.info(cordova.file.externalCacheDirectory);
//Android扩展根目录
console.info(cordova.file.tempDirectory);
/**iOS中的目录**/
//临时目录
console.info(cordova.file.tempDirectory);
//云存储目录
console.info(cordova.file.syncedDataDirectory);
//文档目录
console.info(cordova.file.documentsDirectory);
//共享目录
console.info(cordova.file.sharedDirectory);
注意:
- Android8.0以上对软件做了限制,不允许打开未知来源的软件。解决办法:
<!--config.xml添加以下内容-->
<platform name="android">
<config-file parent="/manifest" target="AndroidManifest.xml" xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
</config-file>
</platform>
- 虽然cordova-plugin-file 插件提供了很多获取文件的方法,但在android里面通用的只有externalDataDirectory这个方法,其他方法获取的路径实际上不可用如下图所示(原因未明,有大佬知道可以讲解一下,求解)。