口语描述
- 全量更新: 全量更新是指发APP包更新,对应的iOS是指发IPA包到appstore,Android发apk包到商城。
- 增量更新: 指uni-app提供的热更新生成的wgt文件,可以下载完自动安装,然后重启APP即可完成更新(iOS开发者泪奔ing)。
- 基座: Hybrid框架的打包都是依赖于框架自身的编译环境的。uni-app则是HBuilderX这款IDE。由于HBuilderX的不定时更新(可以看到会修复很多bug),造成了我们发增量包时编译环境的不同。所以,我的原则是,如果发新的增量包,需要保持编译环境一致,不然就需要发全量更新包。
背景描述
原来的更新策略是这样的,用户登录成功后跳转到home主页,然后在onShow
方法中做更新检测:
onShow() {
if (!this.isNew) { // isNew 默认false
this.isNewVersion()
}
},
methods: {
// 获取最新版本
isNewVersion() {
this.$api.getNewVersion().then(res => {
if (res.is_newest) { //后台告诉我们是新版本,那么将标识符isNew置为true
this.isNew = true
} else { //有新版本,分为增量更新和全量更新
// #ifdef APP-PLUS
if (res.is_update_now) {//增量更新
if (res.down_link !== 'none') {
this.checkUpdate(res.down_link)
}
} else { //全量更新
if (uni.getSystemInfoSync().platform == 'ios') {//iOS,提示用户去APP store下载最新
tip.showModal('请前往App Store下载最新版本', false)
} else {
tip.showModal('发现新版本', false).then(res => {//Android,跳转到fir上用户手动点击下载
if (res) {
plus.webview.open('https://fir.im/hgxgjzs')
}
})
}
}
// #endif
}
})
},
// 下载增量包
checkUpdate(url) {
plus.nativeUI.showWaiting('下载更新...')
plus.downloader
.createDownload(url, { filename: '_doc/update/' }, (d, status) => {
if (status === 200) {
this.installWgt(d.filename)
} else {
plus.nativeUI.alert('下载更新失败!')
}
plus.nativeUI.closeWaiting()
})
.start()
},
// 安装增量包
installWgt(path) {
plus.nativeUI.showWaiting('安装资源文件中...')
plus.runtime.install(
path,
{},
() => {
plus.nativeUI.closeWaiting()
plus.nativeUI.alert('应用资源更新完成!', () => {
plus.runtime.restart()
})
},
e => {
plus.nativeUI.closeWaiting()
plus.nativeUI.alert('资源更新失败,原因:' + e.message)
}
)
},
}
上面的更新策略代码有不完善的地方,需要改进。为帮助理解,现在结合用户使用场景进行描述。
众所周知,Hybrid框架在Android设备上的体验一直不是很让人满意,表现最明显的就是卡顿现象。在产品交付后,Android用户会遇到一些机型造成的页面崩溃,比如选择日期造成的崩溃和打开网页造成的崩溃:
一般出现这种问题,我们都需要更新基座来尝试解决,也就是需要发新的全量包(apk 和ipa),让用户从版本A升级到版本B。我们再发增量包时,希望用户从B升级到C。
用户使用版本A-->新更新基座版本B-->新增量包版本C
不过,这只是理想场景。如果用户使用A版本发生了崩溃,而未及时升级到B版本的新基座,而我们此时已经发了增量包版本C。按照现在的代码更新逻辑,用户则直接跳过B 版本,直接从A版本更新到C。这样,如果用户仍旧反馈出现页面崩溃,而告诉我们他当前的版本号已经是C版本,作为开发者,就无法得知用户究竟是否更新过基座B。
优化更新策略
为了避免用户跳过基座的情况出现,新的更新策略加入了基座版本的设定,如果用户想要从A版本更新到C版本,那么就判断用户当前使用的版本是否是指定的基座版本,是的话则直接为用户进行增量更新,不是则需要用户先更新基座版本(也就是全量更新),在为其做增量更新。
代码实现如下:
onShow() {
if (!this.hasCheckedVersion) { //默认hasCheckedVersion为false
//没有检测过版本,则需要检测版本
this.checkVersion()
}
},
//针对Android用户的返回键,防止更新过程中点击返回按钮,造成下载APK失败
onBackPress(options) {
//值为 true 时,才表示不执行默认的返回,自行处理此时的业务逻辑
return !this.allowBack
},
methods: {
checkVersion() {
//检测版本号
// #ifdef APP-PLUS
this.$api.getNewVersion().then(res => {
if (res.status === 1) {
//是最新版本,标记为已检测,下次onshow不需要重复请求后台进行检测
this.hasCheckedVersion = true
} else if (res.status === 2) {
// 非最新版本,且此时用户的基座满足要求, 直接进行在线更新
this.readyForUpdate(res.url)
} else if (res.status === 3) {
// 非最新版本,但是此时用户的基座不满足要求,需要先下载APK/IPA
if (uni.getSystemInfoSync().platform == 'ios') {
tip.showModal('发现了新版本\n即将前往App Store更新', false).then(() => {
let url = 'itms-apps://itunes.apple.com/cn/app/id1478581650?mt=8'
plus.runtime.openURL(url)
})
} else {
tip.showModal('发现新版本 建议您立即更新', false).then(callback => {
tip.showLoading('正在更新 预估耗时1分钟...')
this.updateForAndroidAPK(res.url)
})
}
}
})
// #endif
},
// 准备下载最新的增量更新包
readyForUpdate(url) {
this.allowBack = false
plus.nativeUI.showWaiting('正在为您更新资源...')
plus.downloader
.createDownload(url, { filename: '_doc/update/' }, (d, status) => {
if (status === 200) {
this.allowBack = true
this.installWgt(d.filename)
} else {
plus.nativeUI.alert('下载更新失败!')
}
plus.nativeUI.closeWaiting()
})
.start()
},
// 安装增量包
installWgt(path) {
plus.nativeUI.showWaiting('正在为您安装新的资源...')
plus.runtime.install(
path,
{},
() => {
plus.nativeUI.closeWaiting()
plus.nativeUI.alert('应用资源更新完成!', () => {
plus.runtime.restart()
})
},
e => {
plus.nativeUI.closeWaiting()
plus.nativeUI.alert('资源更新失败,原因:' + e.message)
}
)
},
//为Android用户自动下载APK
updateForAndroidAPK(url) {
this.allowBack = false
plus.downloader
.createDownload(url, {}, (d, status) => {
tip.hideLoading()
if (status === 200) {
this.allowBack = true
plus.runtime.install(d.filename)
} else {
plus.nativeUI.alert('下载更新失败!')
this.allowBack = true
}
})
.start()
},
}
除了优化了更新策略,还为Android的“呆萌用户”解决了不知道怎么下载apk包这个世纪难题,为iOS用户解决了在APP store查找不到APP这个“奇异bug”。