項(xiàng)目連接: RNHelloWorld
ReactNative使用手冊
重要說明:
本文和ReactNative從零到完整項(xiàng)目-嵌入到安卓原生應(yīng)用(方式一)步驟上從第八步開始不一樣其它都一樣五慈,之所以分開成兩篇俏拱,一是我自己本來就是兩個(gè)項(xiàng)目按兩種方式完成的,二是為了看起來更清晰衩茸,如果看過上一篇,那么這一篇可以直接跳到第八步開始看慢叨,文章結(jié)尾給出參考博客鏈接
把React Native組件植入到Android應(yīng)用
第一步:引入react-native
在androidstudio的Terminal窗口中輸入 npm init
,接著會提示你輸入一些東西(除了項(xiàng)目名字其他都可直接回車使用默認(rèn)值)
當(dāng)我們輸完的時(shí)候?qū)⒐こ糖袚Q到project模式下寺渗,可以看到工程多了一個(gè)package.json的文件
{
"name": "rnhello",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "賴天兵",
"license": "ISC"
}
看到這個(gè)文件有一種很熟悉但又陌生的感覺,但是它的作用都應(yīng)該猜到了扭倾,這個(gè)和我們build.gradle中的配置是一樣的作用,其實(shí)就是配置工程的一些屬性
第二步:添加react和react_native模塊
在Terminal窗口中輸入:npm install --save react react-native
并執(zhí)行挽绩,然后就是靜靜的等待膛壹,如果有報(bào)錯(cuò),自己手動(dòng)敲"--"這個(gè)符號唉堪,因?yàn)樵诓煌南到y(tǒng)下“--”可能是不一樣的,完成后就可以看到工程多了一個(gè)node_modules模塊
第三步:在命令行中運(yùn)行curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
(這步對Windows來說真的坑)
直接運(yùn)行會提示你:'curl' 不是內(nèi)部或外部命令模聋,也不是可運(yùn)行的程序
所以看來我的首先處理Windows運(yùn)行curl命令的問題了
curl是利用URL語法在命令行方式下工作的開源文件傳輸工具。它被廣泛應(yīng)用在Unix唠亚、多種Linux發(fā)行版中链方,并且有DOS和Win32、Win64下的移植版本灶搜。
所以首先要解決Windows下支持curl
命令的問題Windows下安裝使用curl命令
提示有可能你找不到| curl-7.33.0-win64-ssl-sspi.zip
再提示一下當(dāng)你按照上面Windows下安裝使用curl命令走到了下圖步驟時(shí)
這時(shí)候應(yīng)該在命令窗口中輸入curl -v -X OPTIONS https://www.baidu.com/
祟蚀,這是文檔沒有說的,而是直接輸入到命令行里了割卖,第一次看如果不知道這個(gè)前酿,那會很懵逼的
不過遺憾的是我按照上門的連接文檔一步步走下來還是無法在任何地方使用curl命令(我的電腦win10 64位)
所以我用了最簡單的方法,直接復(fù)制我們下載的curl.exe
到工程根目錄鹏溯,這樣在本工程的根目錄就能運(yùn)行curl命令了
但是:真想爆粗口罢维,還是生成不了.flowconfig
文件,
所以真正最直接的解決方式來了:自己在項(xiàng)目的根目錄下創(chuàng)建.flowconfig
文本文件丙挽,然后打開.flowconfig連接復(fù)制文本到剛剛創(chuàng)建的文件中即可
走到這里突然想感嘆一句言津,我饒了一大圈到底是為了啥
第三步:在package.json文件中的scripts
里面配置啟動(dòng)腳本"start": "node node_modules/react-native/local-cli/cli.js start",
{
"name": "rnhello",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node node_modules/react-native/local-cli/cli.js start",
"bundle-android": "react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false"
},
"author": "賴天兵",
"license": "ISC",
"dependencies": {
"react": "^16.2.0",
"react-native": "^0.53.3"
}
}
其實(shí)在官方文檔中第三步已經(jīng)完了攻人,但是畢竟我是踏過了很多巨坑的,看了很多篇博客的我告訴你這步還沒完悬槽,照常理這里還應(yīng)該配置打包用index.android.js生成index.andriod.bundle的配置(你也可以嘗試不做,絕對會出現(xiàn)一些經(jīng)典的bug瞬浓,這里就不提了初婆,我會有一篇專門的文章記錄這些bug)
配置生成發(fā)布、打包時(shí)所需要bundle文件的配置
在很多博客中會這樣解決這個(gè)問題猿棉,像上面完整package.json中的scripts
代碼一樣添加
, "bundle-android": "react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false"
這一句在官方文檔中沒有說明磅叛,但是最好加上(雖然我加上后,至少我這里沒有卵用萨赁,據(jù)說是新版本的RN不支持自動(dòng)生成打包所需的bundle文件了)弊琴,但是這里需要修改一下,很多博客都直接是
"bundle-android": "react-native bundle –platform android –dev false –entry-file index.android.js –bundle-output android/app/src/main/assets/index.android.bundle –sourcemap-output android/app/src/main/assets/index.android.map –assets-dest android/app/src/main/res/"
但是這是錯(cuò)的杖爽,打包的時(shí)候我們都要根據(jù)自己項(xiàng)目目錄的結(jié)果做一些調(diào)整敲董,不過在上面package.json中我已經(jīng)做過調(diào)整了,但是還是無法自動(dòng)完成打包bundle
解決:我們先在main下面創(chuàng)建asserts文件夾慰安,然后進(jìn)入工程根目錄打開cmd輸入
react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false
(注意-output后面的參數(shù)根據(jù)自己的項(xiàng)目目錄結(jié)構(gòu)來寫)
成功后的項(xiàng)目
你或許看過很多在安卓原始項(xiàng)目中嵌套RN腋寨,并按照他們步驟一步步完成了,但是最后就是看不到效果化焕,這里就是其中一個(gè)重要的原因
如果這步完成了萄窜,那么恭喜你,你基本上能看到效果了撒桨,后面可能還要出bug查刻,但是都是些容易解決的固定的了
第四步:在項(xiàng)目根目錄中創(chuàng)建index.android.js
文件
在index.android.js中編寫我們的代碼
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
class HelloWorldApp extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello world! I am from ReactNattive!!</Text>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
//這里的第一個(gè)參熟名字要和我們創(chuàng)建的這個(gè)工程項(xiàng)目名一樣
AppRegistry.registerComponent('RNHelloWorld', () => HelloWorldApp);
提示:在本系列RN博客的第二篇?jiǎng)?chuàng)建HelloWorld的時(shí)候說過,registerComponent()注冊時(shí)名字必須和項(xiàng)目名字保持一致
第五步:添加ReactNative依賴
首先在APP的build.gradle
中添加
dependencies { ... compile "com.facebook.react:react-native:+" // From node_modules. }
其次在工程的build.gradle
中添加進(jìn)入本地ReactNative倉庫的路徑凤类,但是官方源文檔寫的路徑是
$rootDir/../node_modules/react-native/android
如果你直接復(fù)制使用穗泵,恭喜你你又入坑了
因?yàn)槲覀兺ㄟ^之前第二步添加的添加react和react_native模塊,默認(rèn)是項(xiàng)目的根目錄下踱蠢,而官方文檔給出的路徑其實(shí)是多了“../”所以這就是一個(gè)坑(說到這里提一句火欧,網(wǎng)上很多文章都是直接用的官方路徑,但是項(xiàng)目結(jié)構(gòu)又和我的一樣茎截,我真懷疑他們寫那個(gè)文章的時(shí)候只是copy別人文章苇侵,自己根本沒有成功,這也是很多人按照別人文章一步步到最后還是報(bào)錯(cuò)的又一個(gè)原因)企锌,這里路徑應(yīng)該對應(yīng)自己工程中module的路徑
我的工程目錄
所以我的路徑應(yīng)該是
allprojects {
repositories {
...
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/node_modules/react-native/android"
}
}
...
}
添加完成后記得同步以下哦榆浓,不過等待的時(shí)間過于漫長(最好開VPN,我是開了VPN才同步完成的)撕攒,可以先往后繼續(xù)看文章
第六步:在清單文件中添加網(wǎng)絡(luò)請求權(quán)限,必須添加的
官方原話Next, make sure you have the Internet permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
以及調(diào)試需要用到的權(quán)限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
第七步:在清單文件中注冊DevSettingsActivity
,此步驟可以省略,功能就是重載JavaScript
如果您需要訪問DevSettingsActivity添加到您的AndroidManifest.xml:
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
這只在開發(fā)服務(wù)器重新加載JavaScript時(shí)才真正用于開發(fā)模式陡鹃,因此烘浦,如果需要,可以在發(fā)布版本中將其剝離萍鲸。
第八步:新建一個(gè) ReactNativeActivity 闷叉,并在清單文件中設(shè)置成啟動(dòng)頁面,用來展示 React Native 的頁面:
public class ReactNativeActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "RNHelloWorld";
}
}
看過上一篇的人脊阴,再回頭看看上一篇握侧,應(yīng)該覺得很吃驚,原來可以這么簡潔嘿期,而且成功的避開了RN版本不同可能找不到.setJSMainModuleName("index.android")
這個(gè)方法的坑品擎。
接下來(這個(gè)步驟是可以跳過的),我們需要將一些活動(dòng)生命周期回調(diào)傳遞給ReactInstanceManager:
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this, this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onDestroy();
}
}
注意:如果你直接copy官網(wǎng)中代碼的話备徐,是會出錯(cuò)的萄传,因?yàn)镽eactNative版本更新了,方法名字更改和安卓更加同步了
(也是可跳過的)我們還需要將按鈕事件傳遞給React Native:
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
作用:這允許JavaScript控制用戶按下硬件后退按鈕時(shí)發(fā)生的情況(例如蜜猾,實(shí)現(xiàn)導(dǎo)航)秀菱。當(dāng)JavaScript不處理背按時(shí),您的invokeDefaultOnBackPressed方法將被調(diào)用瓣铣。默認(rèn)情況下答朋,這只是完成你的Activity。
最后(這個(gè)步驟也是可以跳過的)棠笑,我們需要連接開發(fā)菜單梦碗。默認(rèn)情況下,這是通過(憤怒)激發(fā)設(shè)備來激活的蓖救,但這在模擬器中并不是很有用洪规。所以我們在按下硬件菜單按鈕時(shí)顯示它(Ctrl + M如果您使用的是Android Studio模擬器,請使用它):
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
第九步(此步驟可以跳過):配置權(quán)限以便開發(fā)中的紅屏錯(cuò)誤能正確顯示
如果您的應(yīng)用定位到Android API level 23
或更高版本循捺,請確保您已overlay
為開發(fā)版本啟用權(quán)限斩例。你可以檢查它Settings.canDrawOverlays(this);
。這在開發(fā)版本中是必需的从橘,因?yàn)楸仨氃谒衅渌翱谥巷@示原始開發(fā)錯(cuò)誤念赶。由于在API級別23中引入了新的權(quán)限系統(tǒng),用戶需要批準(zhǔn)它恰力。這可以通過將以下代碼添加到onCreate()方法中的Activity文件中來實(shí)現(xiàn)叉谜。OVERLAY_PERMISSION_REQ_CODE是將負(fù)責(zé)將結(jié)果傳遞回活動(dòng)的類的字段。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
}
}
最后踩萎,onActivityResult()
必須重寫該方法(如下面的代碼所示)以處理一致UX的權(quán)限Accepted或Denied停局。
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!Settings.canDrawOverlays(this)) {
// SYSTEM_ALERT_WINDOW permission not granted...
}
}
}
}
最后在明確下index.android.js和mReactRootView.startReactApplication(mReactInstanceManager, "HelloRN", null)
和package.json及項(xiàng)目名字,到底那幾個(gè)保持一致(我也是集成了5次以上,總結(jié)出來的董栽,如果有不對請留言指出)
必須一樣的:工程名字(RNHelloWorld)和AppRegistry.registerComponent('RNHelloWorld', () => HelloWorldApp);
以及protected String getMainComponentName()返回的名字
三者必須一樣码倦。
當(dāng)你出現(xiàn)以下錯(cuò)誤,基本就是這個(gè)原因了
運(yùn)行應(yīng)用
- 首先運(yùn)行服務(wù)
在項(xiàng)目的根文件夾下锭碳,命令行運(yùn)行如下命令袁稽,啟動(dòng)測試服務(wù)器(可以直接在Androidstudio的Termin中輸入,但是注意當(dāng)前所在位置)工禾。
npm start
或者:
react-native start
- 接下來像開發(fā)安卓項(xiàng)目一樣直接運(yùn)行項(xiàng)目
效果(這里使用的上一篇的效果圖和真實(shí)的只是title不一樣)
有了上一篇的經(jīng)驗(yàn)运提,這次我一次就完成了將RN嵌入原生項(xiàng)目,真順暢
如果報(bào)錯(cuò)
或是
解決:在app的build.gradle 中添加
|
|
ndk {
abiFilters "armeabi-v7a", "x86"
}
}```
參考鏈接:
其實(shí)我已經(jīng)在坑了爬了三天了闻葵,看了幾十篇博客,以及一些問題解決的網(wǎng)頁癣丧,下面就指出我覺得最有用的槽畔,和影響最深刻的
官方文檔嵌入到現(xiàn)有原生應(yīng)用
Android項(xiàng)目中集成React Native
React Native 學(xué)習(xí)筆記十二(嵌入原生應(yīng)用 甚是坑啊)
印象最深刻就是:現(xiàn)有Android項(xiàng)目引入ReactNative--九步大法,因?yàn)槭区櫻蟠笊裢扑]的所以也是我首選看的資料胁编,我還結(jié)合了官網(wǎng)資料一起看厢钧,沒想到就入坑了,作者文章的工程目錄結(jié)構(gòu)和我一樣嬉橙,但是在在填寫本地倉庫的路徑卻和官網(wǎng)一樣(猜想:如果作者的項(xiàng)目能運(yùn)行早直,再看看作者的目錄圖片應(yīng)該是蘋果,我用的Windows市框,可能系統(tǒng)不一樣所以路徑可能存在一點(diǎn)差異)
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
這也就是我入坑的第一步了霞扬,原因我在文章第五步已經(jīng)說明,以至于"一入坑難起來啊"枫振,當(dāng)然說這個(gè)不是為了針對作者喻圃,只是給更多的人提個(gè)醒,以免再次入坑
喜歡請點(diǎn)贊粪滤,或是關(guān)注斧拍,后續(xù)將完善發(fā)布更多的文章,你的鼓勵(lì)就是我的動(dòng)力(程序員最大的動(dòng)力莫過于同行的鼓勵(lì))