什么是codepush?
CodePush是一个微软开发的云服务器。通过它,开发者可以直接在用户的设备上部署手机应用更新。CodePush相当于一个中心仓库,开发者可以推送当前的更新(包括JS/HTML/CSS/IMAGE等)到CoduPush,然后应用将会查询是否有更新。
集成流程
-
安装CodePush Cli
-
注册CodePush帐号
-
在CodePush服务器注册App
-
在React Native中集成CodePush
-
在React Native中运行CodePush
-
如何发布CodePush更新包
一、安装CodePush Cli
CodePush指令只需要在终端上输入指令即可,而且只需要全局输入一次。
$ npm install -g code-push-cli
二、注册CodePush帐号
注册CodePush只需要运行下面的指令后跟着他的步骤走就可以了,也是只需要注册一次即可。
$ code-push register
注意:运行完当前指令后会打开一个授权网页,让你选择当前注册的方式。这里我选择的是Github。
注册完之后你会拿到一个CodePush的一个Key值 然后将它复制粘贴到终端 成功后会出现Successfully的提示如果你想验证一下是否注册成功,可以通过$ code-push login
进行验证
CodePush注册登录的相关命令有:
code-push register
注册code-push login
登录code-push logout
登出
三、在CodePush服务器注册App
为了让CodePush服务器有我们的App,我们需要在CodePush中注册App,输入下面命令即可完成注册。这里需要注意的是注册分为IOS和Android两个平台,这里只讲解Android的,下一篇写IOS的。
应用添加成功后就会返回对应的Production 和 Staging 两个key,Production代表生产版的热更新部署,Staging代表开发版的热更新部署
添加android平台
$ code-push app add 你的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的所有权转移到另外一个账号
四、在React Native中集成CodePush
首页需要在项目中安装组件,然后再android文件夹中进行一些配置
- 安装组件
$ npm install react-native-code-push --save
注意:由于RN6.0以后会自动进行依赖,所以我们不需要再去link
- 在
android/app/build.gradle
文件中添加codepush.gradle
...
apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
...
- 更新
MainApplication.java
文件(android/app/src/main/java/com/youApp/MainApplication.java
)
...
// 1. 导入CodePush
import com.microsoft.codepush.react.CodePush;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
...
// 2. 覆盖getJSBundleFile方法
// the CodePush runtime determine where to get the JS
// bundle location from on each app start
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
};
}
- 将部署密钥添加到
strings.xml
(android/app/src/main/res/values/strings.xml
)
<resources>
<string name="app_name">youApp</string>
<string moduleConfig="true" name="CodePushDeploymentKey">你的staging值</string>
</resources>
你可以通过code-push deployment ls <appName> -k
来检索你的App中Production值和Staging值。
- 在
build.gradle
(android/app/build.gradle
)中加上production和staging的CODEPUSH_KEY
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://facebook.github.io/react-native/docs/signed-apk-android.
signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
buildConfigField "String", "CODEPUSH_KEY", '"你的Production CodePushKey"'
}
releaseStaging {
minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
buildConfigField "String", "CODEPUSH_KEY", '"你的Staging CodePushKey"'
}
}
注意:在这步的时候,网上的文章都需要在MainApplication.java
文件中加上下面的代码
@Override
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
packages.add(new CodePush(getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey), getApplicationContext(), BuildConfig.DEBUG));
// packages.add(new CodePush(BuildConfig.CODEPUSH_KEY, getApplicationContext(), BuildConfig.DEBUG, getResources().getString(R.string.reactNativeCodePush_androidDeploymentKey)));
return packages;
}
上面的两种方式我都试了,但是都报了下面错误,后面我将它注释掉了以后就不报错了,我也不知道为啥。
五、在React Native中运行CodePush
在使用之前需要考虑的是检查更新时机,更新是否强制,更新是否要求即时等
更新时机
一般常见的应用内更新时机分为两种,一种是打开App就检查更新,一种是放在设置界面让用户主动检查更新并安装
- 打开App就更新
此时只需要将更新的代码放在componentDidMount
中即可
import React from 'react'
import Router from './app/routes/routes'
import CodePush from 'react-native-code-push'
const codePushOptions = {
// 设置检查更新的频率
// ON_APP_RESUME APP 恢复到前台的时候
// ON_APP_START APP 开启的时候
// MANUAL 手动检查
checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
updateDialog: true,
installMode: CodePush.InstallMode.IMMEDIATE
}
class App extends React.Component {
render () {
return (
<Router />
)
}
update = () => {
CodePush.sync({
// 安装模式
// ON_NEXT_RESUME 下次恢复到前台时
// ON_NEXT_RESTART 下一次重启时
// IMMEDIATE 马上更新
installMode: CodePush.InstallMode.IMMEDIATE,
// 对话框
updateDialog: {
// 是否显示更新描述
appendReleaseDescription: true,
// 更新描述的前缀。 默认为"Description"
descriptionPrefix: '更新内容:',
// 强制更新按钮文字,默认为continue
mandatoryContinueButtonLabel: '立即更新',
// 强制更新时的信息. 默认为"An update is available that must be installed."
mandatoryUpdateMessage: '必须更新后才能使用',
// 非强制更新时,按钮文字,默认为"ignore"
optionalIgnoreButtonLabel: '稍后',
// 非强制更新时,确认按钮文字. 默认为"Install"
optionalInstallButtonLabel: '后台更新',
// 非强制更新时,检查到更新的消息文本
optionalUpdateMessage: '有新版本了,是否更新?',
// Alert窗口的标题
title: '更新提示'
}
})
}
async componentWillMount () {
CodePush.disallowRestart() // 禁止重启
this.update() // 开始检查更新
}
componentDidMount () {
CodePush.allowRestart() // 在加载完了,允许重启
}
}
App = CodePush(codePushOptions)(App)
export default App
- 用户点击检查更新按钮
在用户点击检查更新按钮后进行检查,如果有更新则弹出提示框让用户选择是否更新,如果用户点击立即更新按钮,则会进行安装包的下载(实际上这时候应该显示下载进度,这里省略了)下载完成后会立即重启并生效(也可配置稍后重启),部分代码如下:
update = () => {
const deploymentKey = '你的CodePush Key'
CodePush.checkForUpdate(deploymentKey).then(update => {
if (!update) {
Alert.alert('提示', '已是最新版本', [
{
text: 'Ok',
onPress: () => {
console.log('点了OK')
}
}
])
} else {
CodePush.sync({
// 安装模式
// ON_NEXT_RESUME 下次恢复到前台时
// ON_NEXT_RESTART 下一次重启时
// IMMEDIATE 马上更新
installMode: CodePush.InstallMode.IMMEDIATE,
// 对话框
updateDialog: {
// 是否显示更新描述
appendReleaseDescription: true,
// 更新描述的前缀。 默认为"Description"
descriptionPrefix: '更新内容:',
// 强制更新按钮文字,默认为continue
mandatoryContinueButtonLabel: '立即更新',
// 强制更新时的信息. 默认为"An update is available that must be installed."
mandatoryUpdateMessage: '必须更新后才能使用',
// 非强制更新时,按钮文字,默认为"ignore"
optionalIgnoreButtonLabel: '稍后',
// 非强制更新时,确认按钮文字. 默认为"Install"
optionalInstallButtonLabel: '后台更新',
// 非强制更新时,检查到更新的消息文本
optionalUpdateMessage: '有新版本了,是否更新?',
// Alert窗口的标题
title: '更新提示'
}
},
(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.')
})
}
})
}
最后得到的界面如下:
六、如何发布CodePush更新包
在将React Native的bundle放到CodePush服务器之前,我们需要先生成bundle,在将bundle上传到CodePush
生成bundle
- 在RN项目的根目录下创建bundle文件夹,然后创建android文件夹
- 生成bundle命令
react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件 --assets-dest 资源输出目录 --dev 是否调试
$ react-native bundle --platform android --entry-file index.js --bundle-output ./bundle/android/main.jsbundle --assets-dest ./bundle/android --dev false
上传bundle
- 将生成的bundle文件上传到CodePush,我们直接执行下面的命令即可
$ code-push release-react <Appname> <Platform> --t <本更新包面向的旧版本号> --des <本次更新说明>
$ code-push release-react androidApp android --t 1.0.0 --dev false --d Staging --des "这是第一个更新包" --m true
注意:--m true
表示强制更新
查看历史bundle
查看发布的历史记录,命令如下
- 查询Production
$ code-push deployment history projectName Production
- 查询Staging
$ code-push deployment history projectName Staging