本文基于React Native开发环境搭建,默认已搭建好XXProject的react native项目。本文appcenter cli版本为2.10.0,本文法布时,coderova已停用,codepush已被弃用,因此直接使用更加傻瓜式接入的appcenter cli。本文基于react版本17.0.2、react-native版本0.67.3,使用mac开发。
XXProject根目录下执行
npm install -g appcenter-cli
安装appcenter cli,然后再运行
appcenter login
即可调起App Center网页,新建账户(此处不再赘述)结束后,页面会生成新的API token
将token复制后粘贴到刚才输入appcenter login的终端,按enter后即刻登陆App Center应用页面以及运行cli命令,如果不是centeros等无gui系统的话,建议使用网页新增应用以及配置管理,比使用命令方便很多。
本文只讨论使用AppCenter接入React Native,首先新建App:
需要注意,rn产出的android包与ios包一般都是有区别的,因此需要新建两个app,一般默认命名都是类似于XXProject-Android,XXProject-IOS,如果不使用网页新建,则对应新建项目命令为
appcenter apps create -p React-Native -o Android -d XXProject-Android -r Production -n xxproject-android-url-name --description 'Android示例项目'
appcenter apps create --platform React-Native --os iOS --display-name XXProject-IOS --release-type Production --name xxproject-ios-url-name --description 'IOS示例项目'
特别注意,-d只是显示的名称,后续命令中的项目是用的是-n指定的,一般使用-d即可,默认同名。所有的cli详细命令可参见1,如不熟悉命令,可在appcenter相应命令后使用 --help查看详细说明。
在appcenter分别建立Android与ios项目后,在XXProject根目录中使用以下命令中集成CodePush:
npm install --save react-native-code-push
点击按钮创建默认的两个发布环境:预发布环境Staging,与生产环境Production:
请特别注意,一般正式项目流程是直接使用上一篇中的yarn acd命令进行开发与调试,不需要打出bundle包,以方便开发,在交付给测试时,使用预发布环境Staging并打出Staging的离线bundle集成到app,测试通过后使用生产环境Production。
以上创建发布环境如需要使用命令,则先查看现有app:
appcenter apps list
拷贝对应项目,分别执行新建部署:
appcenter codepush deployment add -a name/xxproject-android-url-name Staging
appcenter codepush deployment add -a name/xxproject-android-url-name Production
IOS项目部署创建也是相同的操作。
include ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
// 上一篇集成rn时已经引入,无需重复引入
// apply from: "../../node_modules/react-native/react.gradle"
apply from: "../../node_modules/react-native-code-push/android/codepush.gradle"
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush
...
class MainApplication : Application(), ReactApplication {
override fun onCreate() {
CodePush.setReactInstanceHolder(mReactNativeHost)
super.onCreate()
...
}
override fun getReactNativeHost() = mReactNativeHost
private val mReactNativeHost: CodePushReactNativeHost = CodePushReactNativeHost(this)
inner class CodePushReactNativeHost(appContext: Application) : ReactNativeHost(this),
ReactInstanceHolder {
override fun getUseDeveloperSupport(): Boolean {
return BuildConfig.DEBUG
}
// Override the getJSBundleFile method to let
// the CodePush runtime determine where to get the JS
// bundle location from on each app start
override fun getJSBundleFile(): String? {
return CodePush.getJSBundleFile()
}
override fun getPackages(): List<ReactPackage> {
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
// 比如rn桥接
return PackageList(this).packages
}
override fun getJSMainModuleName(): String {
return "index"
}
}
}
appcenter codepush deployment list -a ownername/XXProject-Android -k
获取部署key如下图:
将所需部署环境的key放到strings.xml:
<resources>
...
<string moduleConfig="true" name="CodePushDeploymentKey">DeploymentKeystring>
resources>
注意,部署key的环境需要与以下部署命令的一致,XXProject中,默认debug版使用Staging,release版使用Production(一般还需要一个预发布环境,此处测试项目就省略了,正式项目务必需要三个环境)。
更推荐的做法,是不使用strings.xml定义,而将key使用gradle配置:
android {
...
buildTypes {
debug {
...
// CodePush更新不应在开发时使用,因为codepush会覆盖rn开发包。但是CodePush sdk会在所有模式下都去检查更新,因此需要提供key。XXProject中,直接使用Staging环境的key
resValue "string", "CodePushDeploymentKey", '""'
...
}
releaseStaging {
...
// 预发布环境Staging的key,XXProject由于历史原因,直接使用了debug
resValue "string", "CodePushDeploymentKey", '""'
// matchingFallbacks表示找不到的依赖使用release类似配置,https://www.jianshu.com/p/7e2d0e59a2bb
matchingFallbacks = ['release']
...
}
release {
...
// 正式环境Production的key
resValue "string", "CodePushDeploymentKey", '""'
...
}
}
...
}
cd ios && pod install && cd ..
未完待续
接入Android与IOS原生SDK后,需要配置react native以确定codepush更新检查与安装时机。
const codePushOptions = {
//设置检查更新的频率
//ON_APP_RESUME APP恢复到前台的时候
//ON_APP_START APP开启的时候
//MANUAL 手动检查
checkFrequency: CodePush.CheckFrequency.ON_APP_START
};
var that = null
class RNAPP extends Component {
...
}
App = CodePush(codePushOptions)(RNAPP)
export default App
codePushOptions可以不传,默认行为为app启动时检查更新,有更新时静默下载,并在再次冷启动时安装更新。codePushOptions详细介绍此处不赘述,有两个是常用的:
class RNAPP extends Component {
...
componentWillMount() {
// 更新重启之后,防止回滚
CodePush.notifyAppReady()
}
如果业务需求在有更新时,弹窗提示更新,就需要用到两个常用的函数CodePush.checkForUpdate和CodePush.sync:
class RNAPP extends Component {
...
const codePushOptions = {
// 设置检查更新的频率
// ON_APP_RESUME APP恢复到前台的时候
// ON_APP_START APP开启的时候
// MANUAL 手动检查
// 1、设定为手动更新
checkFrequency: CodePush.CheckFrequency.MANUAL
};
syncCodePush() {
// 3、应用更新
CodePush.sync({
// 安装模式
// ON_NEXT_RESUME 下次恢复到前台时
// ON_NEXT_RESTART 下一次重启时
// IMMEDIATE 马上更新
installMode: CodePush.InstallMode.IMMEDIATE,
// 后台30秒以上才更新
// minimumBackgroundDuration: 30
// 不要使用原生对话框!!!!,需要的话自行配置,2022/3/9新版android codepush源码CodePushDialog直接在非主线程mqt_native_modules上show
// updateDialog:true
});
}
componentWillMount() {
// 更新重启之后,防止回滚
CodePush.notifyAppReady();
// 在加载完了可以允许重启
CodePush.disallowRestart();
}
componentDidMount() {
that = this
//在加载完了可以允许重启
CodePush.allowRestart();
// 2、检查是否有更新
CodePush.checkForUpdate().then((update)=>{
if(!update){
console.log("The app is up to date!");
} else {
// 自定义弹窗提示新版本,或其他操作,此处省略
that.syncCodePush()
}
});
}
...
}
以上步骤走完,rn就可以”热更“了。根据上一篇文章操作,离线包已被打进app里,此时随意修改App.js的显示,保存后,使用命令发布更新:
appcenter codepush release-react -a ownername/xxproject-android-url-name -d Staging -t 0.0.1
即可在0.0.1版本的Android app上更新rn页面。同样强烈建议通读发布更新命令参数详解。
appcenter-cli仓库
React Native客户端 SDK
React Native 客户端 SDK API 参考
使用CLI发布codepush更新 ↩︎