最近,在项目DYTT集成了热更新,简单来讲,就是不用从新下载安装包便可达到更新应用的目的,也不算教程吧,这里记录一下。java
目前网上大概有两个比较普遍的方式,分别是react
前者是由ReactNative中文网推出的代码热更新服务,后者是由微软老大哥推出的,固然不只仅是为React Native
,还包括其余原生方式。android
综合考虑之下,选择了react-native-code-push
。ios
1.安装code-pushgit
npm install -g code-push-cli
2.注册登陆帐号github
code-push register
这时候会自动启动浏览器打开网页并提供一个codePush AccessKey
,而后命令行里出现须要输入access key
shell
输入以后就登陆成功了。npm
(貌似在本机上之后都不用登陆了,暂不清楚保持登陆持续多久)react-native
3.添加一个CodePush应用api
code-push app add myProject android react-native
注意填写app的名称,OS(android
/ios
),平台(react-native
),而且android
和ios
须要建立两个应用
建立完成会出现两个key
name | Deployment Key |
---|---|
Production | (一串37位的key) |
Staging | (一串37位的key) |
Production
是对应生产环境的,Staging
是对应开发环境的。
这个对于咱们来讲其实没什么区别,只是为了方便测试,因此搞了两个环境
1.安装react-native-code-push
yarn add react-native-code-push # link react-native link react-native-code-push
2.原生配置
目前只测试了android
,ios
有兴趣的能够自行测试
上面提到了两个key
值,如今须要配置在原生目录里
1.打开android/app/build.gradle
android { ... buildTypes { debug { ... // Note: CodePush updates should not be tested in Debug mode as they are overriden by the RN packager. However, because CodePush checks for updates in all modes, we must supply a key. buildConfigField "String", "CODEPUSH_KEY", '""' ... } releaseStaging { ... buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_STAGING_KEY>"'//注意这里的引号 ... } release { ... buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"' ... } } ... }
若是遇到打包错误,可加上matchingFallbacks = ['release', 'debug']
,不知道是否是个别状况,若是没有的请忽略。
修改versionName
为3位数的版本号(code-push要求)
defaultConfig { applicationId "com.dytt" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 2 versionName "2.1.0"//默认为2位版本号 // ndk { // abiFilters "armeabi-v7a", "x86" // } }
release { //... matchingFallbacks = ['release', 'debug']//加上这一句 buildConfigField "String", "CODEPUSH_KEY", '"<INSERT_PRODUCTION_KEY>"' //... }
2.打开MainApplication.java
@Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( ... new CodePush(BuildConfig.CODEPUSH_KEY, MainApplication.this, BuildConfig.DEBUG), // Add/change this line. ... ); }
这样就实现了key
的动态部署,即在什么环境下使用什么key
1.导入react-native-code-push
这里须要在应用的根组件上添加CodePush
配置
import CodePush from "react-native-code-push";
若是你的环境支持Decorator(修饰符)
,能够这样
@codePush(options: CodePushOptions) class MyApp extends Component<{}> {}
普通的写法
class MyApp extends Component<{}> {} MyApp = codePush(codePushOptions)(MyApp); export default MyApp;
这里的codePushOptions
是更新的配置选项
codePush.CheckFrequency.ON_APP_START
。codePush.InstallMode.ON_NEXT_RESTART
。详细的配置可参考https://github.com/Microsoft/react-native-code-push/blob/master/docs/api-js.md
2.更新策略
默认状况下,CodePush
会在app
每次启动的时候去检测是否有更新,若是有,app
会自动下载并在下次打开app
时安装
这种更新方式是静默的,用户根本察觉不到。
若是咱们须要给一点更新提示,可使用默认的弹出框,也就是react-native
自带的Alert
,点击后当即安装
class MyApp extends Component {} MyApp = codePush({ updateDialog: true, installMode: codePush.InstallMode.IMMEDIATE })(MyApp);
固然,你能够对弹出框作少许的自定义,好比标题,按钮的文字等
updateDialog: { optionalIgnoreButtonLabel: '稍后', optionalInstallButtonLabel: '当即更新', optionalUpdateMessage: '有新版本了,是否更新?', title: '更新提示' },
这些是默认的更新方式,那么如何自定义呢。
咱们能够用到CodePush.checkForUpdate
来手动检查更新,而后弹出一个自定义窗口
const RemotePackage = await CodePush.checkForUpdate(deploymentKey); if(RemotePackage){ this.modal.init(RemotePackage);//打开弹窗 }
这里须要注意的是,在checkForUpdate
(或其余须要填写deploymentKey的地方)的时候,若是在debug
模式下,若是不填写deploymentKey
,会提示缺乏deploymentKey
,咱们能够临时写一个固定的方便测试。在正式环境下,这里是不须要填写,它会根据系统自动获取咱们在以前配置的那些deploymentKey
值
而后能够经过RemotePackage.download
和LocalPackage.install
来完成下载和安装
install = async () => { LayoutAnimation.easeInEaseOut(); this.setState({status:1})//download const LocalPackage = await this.RemotePackage.download((progress)=>{ this.setState({ receivedBytes:progress.receivedBytes }) Animated.timing( this.width, { toValue: parseFloat(progress.receivedBytes / progress.totalBytes).toFixed(2), duration: 150 } ).start(); }) this.setState({status:2})//downloadComplete await LocalPackage.install(LocalPackage.isMandatory?CodePush.InstallMode.IMMEDIATE:CodePush.InstallMode.ON_NEXT_RESUME); if(!LocalPackage.isMandatory){ this.setState({status:3}) this.setVisible(false); }else{ ToastAndroid && ToastAndroid.show('下次启动完成更新', ToastAndroid.SHORT); } }
具体实现能够参考项目DYTT
3.打包Release
cd android # 生成Release(Production)包 gradlew assembleRelease # 生成Release(Staging)包 gradlew assembleReleaseStaging
其实都同样,只是环境区别
这一步很简单,集成了打包和发布
code-push release-react dyttAndroid android --t 2.1.0 --dev false --d Production --des "1.修复了已知BUG\n 2.测试code push" --m true
这里注意--t 2.1.0
,有如下几种规则
1.2.3 仅仅只有1.2.3的版本 * 全部版本 1.2.x 主要版本1,次要版本2的任何修补程序版本 1.2.3 - 1.2.7 1.2.3版本到1.2.7版本 >=1.2.3 <1.2.7 大于等于1.2.3版本小于1.2.7的版本 ~1.2.3 大于等于1.2.3版本小于1.3.0的版本 ^1.2.3 大于等于1.2.3版本小于2.0.0的版本
--d
表示开发版本,可选择Production
和Staging
--m
表示是否强制更新
固然还有不少操做,好比删除某些更新,回滚等,能够参考官方文档https://github.com/Microsoft/react-native-code-push
总的来讲,此次热更新集成仍是挺容易,里面碰到的几个误区在上面也已经提到过,欢迎你们多多关注个人项目DYTT^^