问题:
使用code-push更新以后,关闭app重新打开会回滚到更新之前的版本,查看日志发现有这么一句话
Update did not finish loading the last time, rolling back to a previous version
更新判断代码如下
CodePush.checkForUpdate().then((update) => {
if (update) {
CodePush.sync({
updateDialog: {
appendReleaseDescription: false,
descriptionPrefix: '\n\n更新内容:\n',
title: '发现新版本',
mandatoryUpdateMessage: '更新内容:\n' + update.description,
mandatoryContinueButtonLabel: '确定'
}
},
this.codePushStatusDidChange.bind(this),
this.codePushDownloadDidProgress.bind(this))
}
})
解决:
检查发现,是由于没有仔细阅读官方文档,文档中有这么一句话:
翻译为:如果您没有在app启动时调用sync(例如在根组件的componentDidMount中),则需要在app启动时显式调用notifyApplicationReady,否则,插件将认为您的更新失败并回滚。
至于为什么要加,看下Android源码:
//CodePush.js 177行
void initializeUpdateAfterRestart() {
...
JSONObject pendingUpdate = mSettingsManager.getPendingUpdate();
if (pendingUpdate != null) {
//有新的更新包可用
JSONObject packageMetadata = this.mUpdateManager.getCurrentPackage();
if (!isPackageBundleLatest(packageMetadata) && hasBinaryVersionChanged(packageMetadata)) {
//版本不符
CodePushUtils.log("Skipping initializeUpdateAfterRestart(), binary version is newer");
return;
}
try {
boolean updateIsLoading = pendingUpdate.getBoolean(CodePushConstants.PENDING_UPDATE_IS_LOADING_KEY);
if (updateIsLoading) {
// Pending package已经被init过, 但是 notifyApplicationReady 没有被调用.因此认为这是个无效的更新并且rollback.
CodePushUtils.log("Update did not finish loading the last time, rolling back to a previous version.");
sNeedToReportRollback = true;
rollbackPackage();
} else {
// 现在有个新的更新包可以运行,开始init这个更新包如果它崩溃了,需要在下一次启动时rollback
mSettingsManager.savePendingUpdate(pendingUpdate.getString(CodePushConstants.PENDING_UPDATE_HASH_KEY), /* isLoading */true);
}
} catch (JSONException e) {
// Should not happen.
throw new CodePushUnknownException("Unable to read pending update metadata stored in SharedPreferences", e);
}
}
}
下载好更新包后,将这个更新包标志位pending package,并且isloading为false,将previousPacakge置为currentPackage,currentPackage置为下载的更新包。
在加载更新包时会判断这个更新包是否是pending package,如果是则判断isloading是否为false,如果为false则代表这个pending package是第一次加载,如果为true则代表这个pending被加载后调用notifyApplicationReady前发生崩溃,需要回滚。
如果发生回滚会将pending package置空,将previouPackage赋值给currentPackage。
在正确加载更新包后,应该手动触发notifyApplicationReady将pending package置空,代表这个更新包被正确installed。
1.解决办法一:
如果是入口处每次都调用了CodePush.sync则不会有问题,因为CodePush.sync函数中会调用notifyApplicationReady函数。
2.解决办法二:
根页面加载完成后调用CodePush.notifyAppReady函数,告知它已经加载成功了,可以清空记录了。
CodePush.checkForUpdate().then((update) => {
if (update) {
CodePush.sync({
updateDialog: {
appendReleaseDescription: false,
descriptionPrefix: '\n\n更新内容:\n',
title: '发现新版本',
mandatoryUpdateMessage: '更新内容:\n' + update.description,
mandatoryContinueButtonLabel: '确定'
}
},
this.codePushStatusDidChange.bind(this),
this.codePushDownloadDidProgress.bind(this))
} else {
CodePush.notifyAppReady()
}
})