React Native 實(shí)現(xiàn)熱更新并自動(dòng)簽名打包功能
項(xiàng)目背景:手動(dòng)link的安卓App
1.下載 react-native-code-push
npm install --save react-native-code-push
2.在android/settings.gradle文件下新增:
include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
3.在android\app\src\main\java\com\app\MainApplication.java
文件中修改
... // 1. Import the plugin class. import com.microsoft.codepush.react.CodePush; public class MainApplication extends Application implements ReactApplication { private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { ... // 2. Override the getJSBundleFile method in order to let // the CodePush runtime determine where to get the JS // bundle location from on each app start @Override protected String getJSBundleFile() { return CodePush.getJSBundleFile(); } //手動(dòng)link需要修改的地方,自動(dòng)link應(yīng)該不需要改 @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.CodePushDeploymentKey), getApplicationContext(), BuildConfig.DEBUG, getResources().getString(R.string.reactNativeCodePush_androidServerURL))); return packages; } }; } //CodePushDeploymentKey對(duì)應(yīng)string.xml里面的 Deployment key的name //reactNativeCodePush_androidServerURL對(duì)應(yīng)string.xml里面熱更新服務(wù)地址的name
4.string.xml的修改:首先要將你的app添加到推送中心,并獲取你需要的環(huán)境分支的key
4.1.登錄熱更新服務(wù)器
4.2.推送中心創(chuàng)建項(xiàng)目:(針對(duì)第一次部署)
code-push app add 項(xiàng)目名稱(chēng) android react-native
4.3 添加環(huán)境分支dev:code-push deployment add 項(xiàng)目名稱(chēng) dev (針對(duì)第一次部署)
將項(xiàng)目打包至對(duì)應(yīng)的環(huán)境分支,需要將環(huán)境分支對(duì)應(yīng)的key和熱更新地址配置到項(xiàng)目文件中:(strings.xml)
4.4 準(zhǔn)備工作已經(jīng)做好了,現(xiàn)在我們來(lái)修改string.xml文件吧
... apply from: "../../node_modules/react-native/react.gradle" apply from: "../../node_modules/react-native-code-push/android/codepush.gradle" ... dependencies { implementation project(':react-native-code-push') //最好手動(dòng)加上,否則可能會(huì)有坑 implementation fileTree(dir: "libs", include: ["*.jar"]) .... } ....
5.修改android/app/build.gradle文件
STACK TRACE AND/OR SCREENSHOTS :app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.). C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:6: error: package com.microsoft.codepush.react does not exist import com.microsoft.codepush.react.CodePush; ^ C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:23: error: cannot find symbol return CodePush.getJSBundleFile(); ^ symbol: variable CodePush C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:35: error: cannot find symbol new CodePush(null, getApplicationContext(), BuildConfig.DEBUG), ^ symbol: class CodePush 3 errors :app:compileDebugJavaWithJavac FAILED FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:compileDebugJavaWithJavac'. > Compilation failed; see the compiler error output for details.
采坑:react-native-code-push需要手動(dòng)添加依賴(lài),否則會(huì)報(bào)錯(cuò):
STACK TRACE AND/OR SCREENSHOTS
:app:compileDebugJavaWithJavac - is not incremental (e.g. outputs have changed, no previous execution, etc.).
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:6: error: package com.microsoft.codepush.react does not exist
import com.microsoft.codepush.react.CodePush;
^
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:23: error: cannot find symbol
return CodePush.getJSBundleFile();
^
symbol: variable CodePush
C:\Stock Api\stock_app\android\app\src\main\java\com\stock_app\MainApplication.java:35: error: cannot find symbol
new CodePush(null, getApplicationContext(), BuildConfig.DEBUG),
^
symbol: class CodePush
3 errors
:app:compileDebugJavaWithJavac FAILED
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':app:compileDebugJavaWithJavac'.
> Compilation failed; see the compiler error output for details.
6.采坑:手動(dòng)link react-native-code-push的app,需要禁止autolink,否則會(huì)報(bào)錯(cuò):
java.lang.IllegalStateException: Native module CodePush tried to override CodePushNativeModule. Check the getPackages() method in MainApplication.java, it might be that module is being created twice. If this was your intention, set canOverrideExistingModule=true
所以需要加上一個(gè)配置文件,禁止自動(dòng)link
在項(xiàng)目根目錄創(chuàng)建react-native.config.js文件
module.exports = { dependencies: { 'react-native-code-push': { platforms: { android: null, // disable Android platform, other platforms will still autolink }, }, }, };
7.熱更新配置完成,現(xiàn)在我們需要在項(xiàng)目啟動(dòng)的時(shí)候檢測(cè)熱更新,并提示
在項(xiàng)目入口文件App.js中:
import React,{ Component } from 'react'; import Root from './src/inner'; import configureStore from './src/inner/store'; import UpdateDialog from './src/common/components/updateDialog' import CodePush from "react-native-code-push"; const { persistor, store } = configureStore(); class App extends Component { state = { visitDialog: false, current: 0, total: 100 } componentDidMount() { CodePush.sync({ //安裝模式 //ON_NEXT_RESUME 下次恢復(fù)到前臺(tái)時(shí) //ON_NEXT_RESTART 下一次重啟時(shí) //IMMEDIATE 馬上更新 installMode: CodePush.InstallMode.IMMEDIATE, //對(duì)話框 updateDialog: { //是否顯示更新描述 appendReleaseDescription: true, //更新描述的前綴。 默認(rèn)為"Description" descriptionPrefix: "更新內(nèi)容:", //強(qiáng)制更新按鈕文字,默認(rèn)為continue mandatoryContinueButtonLabel: "立即更新", //強(qiáng)制更新時(shí)的信息. 默認(rèn)為"An update is available that must be installed." mandatoryUpdateMessage: "必須更新后才能使用", //非強(qiáng)制更新時(shí),按鈕文字,默認(rèn)為"ignore" optionalIgnoreButtonLabel: '稍后', //非強(qiáng)制更新時(shí),確認(rèn)按鈕文字. 默認(rèn)為"Install" optionalInstallButtonLabel: '后臺(tái)更新', //非強(qiáng)制更新時(shí),檢查到更新的消息文本 optionalUpdateMessage: '有新版本了,是否更新?', //Alert窗口的標(biāo)題 title: '更新提示' }, }, (status) => { console.log(status, 'status') if (status == 7) { this.setState({ visitDialog: true }) } }, (progress) => { let receivedBytes = progress.receivedBytes / 1024 / 1024; let totalBytes = progress.totalBytes / 1024 / 1024; this.setState({ current: receivedBytes, total: totalBytes }) if (receivedBytes === totalBytes) { setTimeout(() => { this.setState({ visitDialog: false }) }, 1000) } console.log(progress, 'progress') } ); } render() { console.log(this.state.visitDialog, 'visitDialog'); return ( <> <Root store={store} persistor={persistor} /> {this.state.visitDialog && <UpdateDialog title={this.state.current === this.state.total ? '已完成' : '正在下載更新文件'} describe={this.state.current === this.state.total ? '歡迎使用' : '請(qǐng)耐心等待'} current={this.state.current} total={this.state.total}></UpdateDialog>} </> ) } }; let codePushOptions = { //設(shè)置檢查更新的頻率 //ON_APP_RESUME APP恢復(fù)到前臺(tái)的時(shí)候 //ON_APP_START APP開(kāi)啟的時(shí)候 //MANUAL 手動(dòng)檢查 checkFrequency: CodePush.CheckFrequency.ON_APP_START }; export default CodePush(codePushOptions)(App);
UpdateDialog :是我自己封裝的熱更新下載進(jìn)度條的組件,下載提示,可根據(jù)自己的心情隨便寫(xiě),這里我就不貼自己的代碼了!(寫(xiě)的不好,不好意思)
現(xiàn)在我們熱更新配置好了,打包正式的apk吧!
1. 生成簽名文件:在項(xiàng)目根目錄下運(yùn)行命令:
keytool -genkey -v -keystore 我的簽名-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias 我的簽名
2.將生成的簽名文件拷貝至目錄:android/app目錄下
3.配置gradle.properties
android.useAndroidX=true android.enableJetifier=true MYAPP_RELEASE_STORE_FILE=wms-app-key.jks //生成的簽名密鑰 MYAPP_RELEASE_KEY_ALIAS=ydh //別名 MYAPP_RELEASE_STORE_PASSWORD=簽名時(shí)設(shè)置的密碼 MYAPP_RELEASE_KEY_PASSWORD=簽名時(shí)設(shè)置的密碼
4.修改android/app/build.gradle
signingConfigs { debug { ... } release { if (project.hasProperty('MYAPP_RELEASE_STORE_FILE')) { storeFile file(MYAPP_RELEASE_STORE_FILE) storePassword MYAPP_RELEASE_STORE_PASSWORD keyAlias MYAPP_RELEASE_KEY_ALIAS keyPassword MYAPP_RELEASE_KEY_PASSWORD } } }
5..打包(android目錄下): .\gradlew.bat assembleRelease
app打包成功,將apk拷貝到手機(jī)安裝即可
6..推送代碼:(需要更新時(shí),推送代碼到你想要更新的環(huán)境分支)
推送到dev環(huán)境:code-push release-react 項(xiàng)目名稱(chēng) android -d dev
推送到production環(huán)境:-m true 代表強(qiáng)制更新,不加代表不強(qiáng)制更新
code-push release-react 項(xiàng)目名稱(chēng) android -d Production -m true
然后重啟app,就可以看到更新提示啦
總結(jié)
到此這篇關(guān)于React Native 實(shí)現(xiàn)熱更新并自動(dòng)簽名打包的文章就介紹到這了,更多相關(guān)React Native簽名打包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android Activity與Service通信(不同進(jìn)程之間)詳解
這篇文章主要介紹了Android Activity與Service通信(不同進(jìn)程之間)的相關(guān)資料,這里提供了三種方法,需要的朋友可以參考下2016-10-10android在異步任務(wù)中關(guān)閉Cursor的代碼方法
android在異步任務(wù)中如何關(guān)閉Cursor?在我們開(kāi)發(fā)應(yīng)用的時(shí)候,很多時(shí)候會(huì)遇到這種問(wèn)題,下面我們就看看代碼如何實(shí)現(xiàn)2013-11-11Android中的Bmob移動(dòng)后端云服務(wù)器功能
這里介紹一個(gè)移動(dòng)后端云服務(wù)器平臺(tái)bmob,這不僅可以實(shí)現(xiàn)云數(shù)據(jù)庫(kù)儲(chǔ)存,還可以獲取手機(jī)驗(yàn)證等,隨時(shí)隨地都很輕松,下面寫(xiě)一個(gè)小demo,實(shí)現(xiàn)一個(gè)登陸注冊(cè)功能,認(rèn)識(shí)增刪查改2018-01-01Android dip,px,pt,sp 的區(qū)別詳解
本篇文章是對(duì)Android中dip,px,pt,sp的區(qū)別進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-06-06Android Force Close 出現(xiàn)的異常原因分析及解決方法
本文給大家講解Android Force Close 出現(xiàn)的異常原因分析及解決方法,forceclose意為強(qiáng)行關(guān)閉,當(dāng)前應(yīng)用程序發(fā)生了沖突。對(duì)android force close異常分析感興趣的朋友一起通過(guò)本文學(xué)習(xí)吧2016-08-08Android實(shí)現(xiàn)可播放GIF動(dòng)畫(huà)的ImageView
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)可播放GIF動(dòng)畫(huà)的ImageView,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09Android實(shí)現(xiàn)短信驗(yàn)證碼獲取自動(dòng)填寫(xiě)功能(詳細(xì)版)
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)短信驗(yàn)證碼獲取自動(dòng)填寫(xiě)功能,很實(shí)用的功能分享給大家,感興趣的小伙伴們可以參考一下2016-08-08安裝時(shí)加入外部數(shù)據(jù)庫(kù)示例(android外部數(shù)據(jù)庫(kù))
這篇文章主要介紹了android打包安裝時(shí)加入外部數(shù)據(jù)庫(kù)的示例,需要的朋友可以參考下2014-03-03Android自定義view實(shí)現(xiàn)圓的擴(kuò)散效果
這篇文章主要為大家詳細(xì)介紹了Android自定義view實(shí)現(xiàn)圓的擴(kuò)散效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-01-01