CodePush 热更新配置及使用
1. 安装 CodePush :npm install g code push cli 2. 登陆:code push login 3. 注销:code push logout 4. ...
基本使用命令
-
安装
CodePush:npm install -g code-push-cli -
登陆:code-push login
-
注销:code-push logout
-
添加项目:code-push app add [app名称]
-
删除项目:code-push app remove [app名称]
-
列出账号下的所有项目:code-push app list
-
打包命令:react-native bundle —platform 平台 —entry-file 启动文件 —bundle-output 打包js输出文件 —assets-dest 资源输出目录 —dev 是否调试
注:
此处的
--bundle-output和--assets-dest的路径建议使用同一路径,否则在使用CodePush进行更新版本后会出现本地资源文件加载不到的现象 -
发布更新命令:code-push release <应用名称> <Bundles所在目录> <对应的应用版本> —deploymentName 更新环境 —description 更新描述 —mandatory 是否强制更新
注:
- 此处的
对应的应用版本为app对应的版本 否则不提示更新 - 此处的
Bundles所在目录为 js 打包命令中对应的输出目录,即--bundle-output后紧跟的路径 - 此处的
deploymentName的默认值为Staging,若需更新Staging版本时可不填写,对应值为Staging或Production - 此处的
mandatory为是否强制更新选项,对应值为true或false,设置为false时程序会在更新后在下次进入时显示新版本内容,若设置为true则会在更新后立即重启应用并显示新版本内容
- 此处的
-
修改更新:code-push patch
[—label 注:
- —label, -l 指定标签版本更新,默认最新版本 [string] [默认值: null]
- —description, —des 描述 [string] [默认值: null]
- —disabled, -x 是否禁用该更新 [boolean] [默认值: null]
- —mandatory, -m 是否强制更新 [boolean] [默认值: null]
- —rollout, -r 此更新推送用户的百分比,此值仅可以从先前的值增加。 [string] [默认值: null]
-
回滚更新:code-push rollback
[—targetRelease ] 注:
—targetRelease, -r 指定回归到哪个标签,默认是回滚到上一个更新 [string] [默认值: null]
-
查看历史版本:code-push deployment history
(Production 或者 Staging) -
清除历史版本:code-push deployment clear
集成配置信息(android)
Js 部分配置
更新模式分为自动模式与手动模式两种
- 自动模式
CodePush.sync()
CodePush.sync() 函数为 sync(options?: SyncOptions, syncStatusChangedCallback?: SyncStatusChangedCallback, downloadProgressCallback?: DowloadProgressCallback)
SyncOptions内包含有deploymentKey、installMode、mandatoryInstallMode、minimumBackgroundDuration、updateDialog属性,此处属性的对应介绍可见其源码注释部分,很详细SyncStatusChangedCallback为更新的状态回调方法,可通过添加此方法来监听更新的状态,如检查到更新、更新完成、更新失败等状态,对应代码为
codePushStatusDidChange(syncStatus) {
switch(syncStatus) {
case CodePush.SyncStatus.CHECKING_FOR_UPDATE:
console.log("更新===检查更新中");
break;
case CodePush.SyncStatus.DOWNLOADING_PACKAGE:
console.log("更新===下载更新包");
break;
case CodePush.SyncStatus.AWAITING_USER_ACTION:
console.log("更新===检查到新版本,等待用户操作");
break;
case CodePush.SyncStatus.INSTALLING_UPDATE:
console.log("更新===正在安装更新");
break;
case CodePush.SyncStatus.UP_TO_DATE:
console.log("更新===已是最新版本");
break;
case CodePush.SyncStatus.UPDATE_IGNORED:
console.log("更新===用户取消更新");
break;
case CodePush.SyncStatus.UPDATE_INSTALLED:
console.log("更新===已安装更新,将在重新启动时应用");
break;
case CodePush.SyncStatus.UNKNOWN_ERROR:
console.log("更新===发生了一个未知错误");
break;
}
}
DowloadProgressCallback为更新下载进度的回调方法,可通过添加此方法监听下载的进度, 其属性值为totalBytes和totalBytes, 分别为更新包的总大小与当先下载进度
具体使用示例:
CodePush.sync(
{
installMode: CodePush.InstallMode.ON_NEXT_RESTART,
updateDialog: {
appendReleaseDescription: true,
descriptionPrefix:'更新内容:\n',
title:'更新',
mandatoryUpdateMessage:' ',
mandatoryContinueButtonLabel:'更新',
},
},
this.codePushStatusDidChange.bind(this),
this.codePushDownloadDidProgress.bind(this)
);
// 也可以直接使用 CodePush.sync() 方法进行更新
注:
在程序的入口处需添加以下代码
let codePushOptions = { checkFrequency: CodePush.CheckFrequency.MANUAL };
<填写该类名> = CodePush(codePushOptions)(<填写该类名>);
AppRegistry.registerComponent('<填写此处为创建时的应用名>', () => <填写该类名>);
手动模式暂时未研究 具体 API 可参见官方文档
原生部分设置
- build.gradle
此处分两种情况,一种为不需要改动
CodePush原生代码; 另一种为需要改动CodePush的原生代码,此时如果该项目是插件类型的话还需要将改动后的CodePush的代码上传到私库,否则通过远程库的引用方式无法引用到该部分代码,若不使用远程库引用的话只需拷贝代码即可,此处需要注意的是其源码内codepush.gradle文件必须调用,否则打包后CodePush会因查找不到CODE_PUSH_APK_BUILD_TIME此字段而导致程序停止运行;若是该程序只是一个普通的项目的话则没有这些顾虑,尽管改就可以了
此处指的是
app下面的build.gradle
添加配置代码:
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
android {
...
buildTypes {
// 此处需注意CodePush不支持在DeBug模式下使用
releaseStaging {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_staging")+'"'
...
}
releaseProduction {
...
buildConfigField "String", "CODEPUSH_KEY", '"'+properties.getProperty("code_push_key_production")+'"'
...
}
}
}
- local.properties
项目最外层该文件下添加一下两个属性值
code_push_key_production=该应用的 production 版本的Key
code_push_key_staging=该应用的 staging 版本的Key
- MainApplication
public class MainApplication extends Application implements ReactApplication {
private static final String code_push_key_production="zYDSBi96YCB7fISlK9wJTanpbcnFd4eb246d-c057-4aa7-8dfd-a6f32494bd71";
private static final String code_push_key_staging="g5e_Ttrw183uWyZRuVP4VUzAXlTvd4eb246d-c057-4aa7-8dfd-a6f32494bd71";
// 这两个值也可以通过读取 local.properties 文件获得
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new CodePush(code_push_key_production, getApplicationContext())
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
@Override
public void onCreate() {
super.onCreate();
SoLoader.init(this, /* native exopackage */ false);
}
}
还有一种情况,那就是不定义
Application的情况下使用,此时则可以在MainActivity中如下配置:
public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CodePush codePush = new CodePush(code_push_key_production,this);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
...
.setJSBundleFile(codePush.getJSBundleFile("index.android.bundle"))
.addPackage(codePush)
...
.setUseDeveloperSupport(true)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "<对应RN中注册的名字>", null);
setContentView(mReactRootView);
mReactInstanceManager.addReactInstanceEventListener(new ReactInstanceManager.ReactInstanceEventListener() {
@Override
public void onReactContextInitialized(ReactContext context) {
reactContext = context;
}
});
}
...
}
至此大功告成。