window下Android專案整合React Native的正確姿勢
React Native的專案中分為Android與IOS,但是若在現有的Android專案中,整合RN,不能按照那個包結構來,我們統一在app資料夾下處理。
一、整合步驟:
1.新增js檔案
(1)在app資料夾下輸入命令 npm init,生成package.json檔案。這裡會讓你輸入name等資訊,除了name,其他可不輸入。開啟package.json檔案,在scripts節點下,新增如下程式碼,注意逗號隔開"test"節點。
完整的package.json,我也貼出來:"start": "node node_modules/react-native/local-cli/cli.js start"
(2)安裝React 和React Native:app下繼續命令{ "name": "app", "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" }, "author": "", "license": "ISC", "dependencies": { "react": "^16.2.0", "react-native": "^0.52.1" } }
npm install --save react react-native
這裡需要一段時間,完成後,會在app目錄下生成一個node_modules資料夾。
(3)配置其他檔案。
a:將RN HelloWorld專案中的.flowconfig檔案和.watchmanconfig檔案拷貝過來;
b:將RN HelloWorld專案中的index.js和App.js檔案拷貝過來,並將index.js檔案中註冊元件的名字與package.json中的名字一致(我使用的RN版本中已沒有index.android.js檔案了)。
AppRegistry.registerComponent('app', () => App);
2.專案配置
(1)配置app下的build.gradle檔案。
a:新增RN庫。
b:處理RN引用的so檔案:RN中提供的libreactnativejni.so檔案是32位,而Android專案中用了一些64位的so檔案,導致不相容。解決辦法就是禁止使用那些64位的so檔案。
c:appcompat-v7版本為23.0.1(只能使用該版本下的v7/v4包)。
貼下整個的配置:
android{
ndk {
abiFilters "armeabi-v7a", "x86"
}
}
packagingOptions {
exclude "lib/arm64-v8a"
}
dependencies {
compile "com.facebook.react:react-native:+" // From node_modules.
compile 'com.android.support:appcompat-v7:23.0.1'
}
(2)專案的build.gradle中新增依賴
allprojects {
repositories {
google()
jcenter()
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/app/node_modules/react-native/android"
}
}
}
3.建立Activity
(1)建立MyRNActivity,繼承ReactActivity,重寫getMainComponentName()方法,返回值為package.json中的name值。
(2)建立MyApplication,繼承Application,實現ReactApplication介面。
public class MyApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
protected List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
};
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
(3)清單檔案註冊Activity和Application,並新增網路許可權和DevSettingsActivity。至此,整合結束。貼下整合的目錄:
二、執行
先在app目錄下,啟動node.js。再執行Android專案就可以了。
npm start
三、異常
(1)v4/v7包版本不對,只能使用23.0.1版本構建。如果你用的是自己已釋出的專案,要注意引用庫中v4/v7包的版本,必要的時候,將引用庫中的v4/v7包排除掉。
IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.<init>()
(2)so檔案不統一。可以排除掉64位的so檔案,具體配置見第二節。
java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so
(3)缺失 index.android.bundle檔案。
Got JS Exception: ReferenceError: Can't find variable: __fbBatchedBridge
--> Unable to load script from assets: index.android.bundle
解決辦法:
手動新增assets目錄,建立index.android.bundle檔案,使用命令打包js到該檔案中。
react-native bundle --entry-file index.js --bundle-output ./src/main/assets/index.android.bundle --platform android --assets-dest ./src/main/res/ --dev false
(4) ReactNativeJS報錯
ReactNativeJS: undefined is not a function (evaluating '(d.remoteModuleConfig||[]).forEach(function(e,n){var t=u(e,n);t&&(t.module?v[t.name]=t.module:h(v,t.name,{get:function(){return l(t.name,n)}}))})')
原因:專案下的build.gradle檔案,引用node_modules路徑錯誤,正確的如下:
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/app/node_modules/react-native/android"
}
(5)Cannot find entry file index.android.js in any of the roots。找不到index.android.js檔案。檢視官網的issue,找到了解決方案:複製index.js檔案,命名為index.android.js即可。 連結地址:https://github.com/facebook/react-native/issues/18217