什么是CodePush
CodePush是一个微软开发的云服务器。通过它,开发者可以直接在用户的设备上部署手机应用更新。CodePush相当于一个中心仓库,开发者可以推送当前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然后应用将会查询是否有更新。
接入流程
- 安装 CodePush CLI
- 注册 CodePush账号
- 在CodePush服务器注册App
- RN代码中集成CodePush
- 原生应用中配置CodePush
- 发布更新的版本
1. 安装 CodePush CLI
安装CodePush指令,直接在终端上输入如下命令即可,注意:这个CodePush指令只需要全局安装一次即可,如果第一次安装成功了,那后面就不在需要安装
npm install -g code-push-cli
2、注册 CodePush账号
注册CodePush账号也很简单,同样是只需简单的执行下面的命令,同样这个注册操作也是全局只需要注册一次即可
code-push register
注意:当执行完上面的命令后,会自动打开一个授权网页,让你选择使用哪种方式进行授权登录,这里我们统一就选择使用GitHub即可
当注册成功后,CodePush会给我们一个key
我们直接复制这个key,然后在终端中将这个key填写进去即可,填写key登录成功显示效果如下
我们使用下面的命令来验证我的登录是否成功
code-push login
CodePush注册登录相关命令:
- code-push login 登陆
- code-push loout 注销
- code-push access-key ls 列出登陆的token
- code-push access-key rm
删除某个 access-key
3、在CodePush服务器注册App
为了让CodePush服务器有我们的App,我们需要CodePush注册App,输入下面命令即可完成注册,这里需要注意如果我们的应用分为iOS和Android两个平台,这时我们需要分别注册两套key
应用添加成功后就会返回对应的production 和 Staging 两个key,production代表生产版的热更新部署,Staging代表开发版的热更新部署,在ios中将staging的部署key复制在info.plist的CodePushDeploymentKey值中,在android中复制在Application的getPackages的CodePush中
添加iOS平台应用
code-push app add iOSrn_app ios react-native
添加Android平台应用
code-push app add Androidrn_app Android react-native
我们可以输入如下命令来查看我们刚刚添加的App
code-push app list
CodePush管理App的相关命令:
- code-push app add 在账号里面添加一个新的app
- code-push app remove 或者 rm 在账号里移除一个app
- code-push app rename 重命名一个存在app
- code-push app list 或则 ls 列出账号下面的所有app
- code-push app transfer 把app的所有权转移到另外一个账号
- code-push release-react
-t 版本 -d 环境 --des 描述 -m true (强制更新)// 发布 - code-push deployment clear
Production or Staging // 清除历史部署记录 - code-push rollback
Production --targetRelease v4(codepush服务部署的版本号) // 回滚
// 应用信息相关
- code-push deployment add
部署 - code-push deployment rm
删除部署 - code-push deployment rename
重命名 - code-push deployment ls
列出应用的部署情况 - code-push deployment ls
-k 查看部署的key - code-push deployment history
查看历史版本
4、RN代码中集成CodePush
首先我们需要安装CodeoPush组件,然后通过link命令添加原生依赖,最后在RN根组件中添加热更新逻辑代码
安装组件
npm install react-native-code-push --save
添加原生依赖,这里添加依赖我们使用自动添加依赖的方式(RN0.60版本以上的 cli里集成了AutoLink,不用手动link资源了)
react-native link react-native-code-push
我们在RN项目的根组件(例如App.js)中添加热更新逻辑代码如下
~
import codePush from "react-native-code-push";
const codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };
export default class App extends Component<{}> {
componentDidMount(){
codePush.sync({
updateDialog: true,
installMode: codePush.InstallMode.IMMEDIATE,
mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
//deploymentKey为刚才生成的,用Platform判断下平台(填写你自己的)
deploymentKey: Platform.OS === 'ios'?'sYvpLUxuBU9FxICqJ5sccL2GDUPZcc988a73-c917-4dba-bd40-1837998442a6':'fqdFCqLyL4XclNZjWvNN3KNhImR5cc988a73-c917-4dba-bd40-1837998442a6',
});
}
~
5,模拟器上运行项目
react-native run-ios
react-native run-android
5.1 如图下所显打包过程中可能遇到的
错误发生在java编译器执行过程中
看到出来是刚刚引入的Code-Push包,实例化的时候getString方法获取我们之前的DeploymentKey失败.
getString是android 开发中Context类上的一个获取字符串的方法,在RN中会从根目录下/android/app/src/main/res/values/strings.xml文件中获取值。
我们打开strings.xml文件后添加这样一行代码:
xxxxxxx你刚刚注册DeploymentKey
例如
再次react-native run-android即可成功运行
6. deployment-key的设置与获取bundle路径 (关于Grande)
- 在上述代码中我们在创建CodePush实例的时候需要设置一个deployment-key,因为deployment-key分生产环境与测试环境两种,所以建议大家在build.gradle中进行设置。在build.gradle中的设置方法如下:
打开android/app/build.gradle文件,找到android { buildTypes {} }然后添加如下代码即可:
buildTypes {
release {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
signingConfig signingConfigs.config
+ buildConfigField "String", "CODE_PUSH_KEY", CODE_PUSH_KEY_PRODUCTION
+ buildConfigField "boolean", "IS_CODE_PUSH", "true"
}
debug {
+ buildConfigField "String", "CODE_PUSH_KEY", CODE_PUSH_KEY_STAGING
+ buildConfigField "boolean", "IS_CODE_PUSH", "true"
}
}
心得:另外,我们也可以将deployment-key存放在gradle.properties中:
CODE_PUSH_KEY_PRODUCTION="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
CODE_PUSH_KEY_STAGING="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
在android/app/build.gradle设置好deployment-key之后呢,我们就可以这样使用了:
MainApplication.java下的ReactNativeHost方法中添加
@Override
protected String getJSBundleFile() {
// gradlew assembleRelease会把所有用到的JavaScript代码都打包内置到APK中
if (BuildConfig.IS_CODE_PUSH) {
return CodePush.getJSBundleFile(); // code-push热更新
}
//return UpdateContext.getBundleUrl(MainApplication.this); // pushy热更新
}
7.修改versionName和引入code-push设置。
在 android/app/build.gradle中有个 android.defaultConfig.versionName属性,我们需要把 应用版本改成 1.0.0(默认是1.0,但是codepush需要三位数)。
android{
defaultConfig{
versionName "1.0.0"
}
}
//文件最下方
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
\android\app\src\main\java\com\ysty_app3\MainApplication.java添加包
import com.microsoft.codepush.react.CodePush;
至此Code Push for Android的SDK已经集成完成。
8、发布更新的版本
在使用之前需要考虑的是检查更新时机,更新是否强制,更新是否要求即时等
更新时机
一般常见的应用内更新时机分为两种,一种是打开App就检查更新,一种是放在设置界面让用户主动检查更新并安装
- 打开APP就检查更新
最为简单的使用方式在React Natvie的根组件的componentDidMount方法中通过
codePush.sync()(需要先导入codePush包:import codePush from 'react-native-code-push')方法检查并安装更新,如果有更新包可供下载则会在重启后生效。不过这种下载和安装都是静默的,即用户不可见。如果需要用户可见则需要额外的配置。具体可以参考codePush官方API文档,部分代码,完整代码请参照文档上面
codePush.sync({
updateDialog: true,//code-push 接管更新
installMode: codePush.InstallMode.IMMEDIATE,
mandatoryInstallMode:codePush.InstallMode.IMMEDIATE,
//deploymentKey为刚才生成的,用Platform判断下平台
deploymentKey: Platform.OS === 'ios'?'IOSKey':'andoridKey',
});
上面的配置在检查更新时会弹出提示对话框, mandatoryInstallMode表示强制更新,
- 用户点击检查更新按钮
在用户点击检查更新按钮后进行检查,如果有更新则弹出提示框让用户选择是否更新,如果用户点击立即更新按钮,则会进行安装包的下载(实际上这时候应该显示下载进度,这里省略了)下载完成后会立即重启并生效(也可配置稍后重启),部分代码如下
codePush.checkForUpdate(deploymentKey).then((update) => {
if (!update) {
Alert.alert("提示", "已是最新版本--", [
{
text: "Ok", onPress: () => {
console.log("点了OK");
}
}
]);
} else {
codePush.sync({
deploymentKey: deploymentKey,
updateDialog: {
optionalIgnoreButtonLabel: '稍后',
optionalInstallButtonLabel: '立即更新',
optionalUpdateMessage: '有新版本了,是否更新?',
title: '更新提示'
},
installMode: codePush.InstallMode.IMMEDIATE,
},
(status) => {
switch (status) {
case codePush.SyncStatus.DOWNLOADING_PACKAGE:
console.log("DOWNLOADING_PACKAGE");
break;
case codePush.SyncStatus.INSTALLING_UPDATE:
console.log(" INSTALLING_UPDATE");
break;
}
},
(progress) => {
console.log(progress.receivedBytes + " of " + progress.totalBytes + " received.");
}
);
}
}
更新是否要求即时
在更新配置中通过指定installMode来决定安装完成的重启时机,亦即更新生效时机
codePush.InstallMode.IMMEDIATE :安装完成立即重启更新
codePush.InstallMode.ON_NEXT_RESTART :安装完成后会在下次重启后进行更新
-
codePush.InstallMode.ON_NEXT_RESUME :安装完成后会在应用进入后台后重启更新
如何发布CodePush更新包
工程根目录新增 bundles文件夹:
mkdir bundles
1.自动生成bundles文件发布:
code-push release-react 《app名称》《平台》 -t 《版本号》 -d Production --des "描述" -m true
例如
code-push release-react weather android --t 1.0.0 -d Production --dev false --des "1.优化操作流程,2.我裂开" --m false
2.手动生成bundles文件发布, 首先在根目录创建bundles文件夹(每次重新生成文件时需删除上次的文件)
- 单js文件
1. 创建bundles里的文件
打包命令
react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试
打包整个项目的js文件,例如:
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --dev false
2. 发布更新
发布命令:
code-push release <应用名称> <对应的应用版本> --deploymentName 更新环境 --description 更新描述 --mandatory 是否强制更新
例如:
code-push release CodePushDemo-android ./bundles/index.android.bundle 1.0.0 --deploymentName Production --description "热更新" --mandatory true
- js文件+图片资源,–assets-dest 后就是放图片的文件夹路径
打包命令:–assets-dest 后就是放图片的文件夹路径
react-native bundle --platform android --entry-file index.js --bundle-output ./bundles/index.android.bundle --assets-dest ./bundles --dev false
发布bundles文件:
code-push <版本号> --deploymentName 更新环境 --description 更新描述 --mandatory 是否强制更新
例如:
code-push release CodePushDemo-android ./bundles 1.0.0 //省略默认是发布Staging
code-push release CodePushDemo-android ./bundles 1.0.0 -d Production --des "热更新" --mandatory true
需要注意的是:
- 输出的bundle文件名不叫其他,而是 index.android.bundle,是因为 在debug模式下,
工程读取的bundle就是叫做 index.android.bundle。 - 平台可以选择 android 或者 ios。
查看发布信息
查看已add appName
code-push app list
查看部署的历史版本信息
code-push deployment ls CodePushDemo-android -k
9,自定义更新窗口
我们再次打开 app是就可以看到,code-push弹出的 更新提示弹框
这是code-push提供的弹窗,如果需要自定义文字
修改更新弹出框内容
进入node_modules->react-native-code-push->Codepush.js修改以下内容
需要更多自定义设置参考https://blog.csdn.net/weixin_42613755/article/details/104964557
可能出现的问题(react-native run-android)
- What went wrong:
Execution failed for task ':app:mergeDebugResources'.
Could not read path 'E:\cli3\weather2\android\app\build\intermediates\incremental\mergeDebugResources\merged.dir\values'.
cd android 执行 gradlew clean解决 - [Error:Execution failed for task ':app:transformClassesWithDexForDebug]
在项目android/app/build.gradle下添加
defaultConfig {
...
multiDexEnabled true
}
本片内容借鉴至https://segmentfault.com/a/1190000016273902?utm_source=tag-newest
可访问 查阅关于ios端的热更新