React-Native學習筆記——正確整合到現有Android工程中
背景
我們可能需要將react-native整合到已有工程的某個module中,而不是從頭建立一個新工程。下面記錄了筆者一個demo的整合過程。
已有工程結構
下圖中,app為application型別module,rntrial為library型別的module,就是我用來整合react-native的
準備工作
開始整合
1、移花接木
執行命令 :react-native init [工程名] 建立一個全新的rn工程,如下
(注意工程名在下圖示識的三個檔案中均有出現)
刪掉這個新工程android目錄下的內容,將原工程根目錄的所有檔案拷貝到這個android目錄下
這樣原工程就變成了一個標準的rn工程,在工程根目錄下可以使用npm、react-native等命令來操作了
2、建立一個具有RN功能的Activity
rntrail目錄中的build.gradle如下
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
api 'com.facebook.react:react-native:0.51.0'
}
建立RntrialActivity作為rn的主介面,並實現DefaultHardwareBackBtnHandler,主要程式碼如下(請務必注意程式碼中的註釋)
public class RntrailActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private static final int OVERLAY_PERMISSION_REQ_CODE = 0x01;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//這裡不加許可權判斷 6.0或以上機型會閃退
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);
}
}
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
//這是設定assets目錄下的打包過的js檔名 這個檔案可用命令生成 但除錯期間我們使用npm server動態注入 釋出時才將它打進assets
.setBundleAssetName("index.android.bundle")
//這裡設定js入口檔案 舊一點的api可能是setJSMainModuleName 但我的版本是0.51.0 取而代之的是setJSMainModulePath方法
.setJSMainModulePath("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意這裡的“Rnfeel”必須
// 對應index.js”中的“AppRegistry.registerComponent()”的第一個引數值
// 對應“package.json”中的“name”屬性值
// 最好也將“app.json”中的“name”和“displayName”改成它
mReactRootView.startReactApplication(mReactInstanceManager, "Rnfeel", null);
setContentView(mReactRootView);
}
...
@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...
}
}
}
}
}
3、檢查相關檔案內容
以下幾個檔案中的相關內容務必保證一致
app.json中的name和displayName屬性值
{
"name": "Rnfeel",
"displayName": "Rnfeel"
}
index.js中registerComponent的第一個引數值
AppRegistry.registerComponent('Rnfeel', () => App);
package.json中的name屬性值
"name": "Rnfeel",
4、在真機上執行和除錯
首先連線usb,一臺電腦只連一部手機(電腦上的模擬器也要關閉,不然有些操作會失敗)
執行命令:react-native run-android 將應用安裝到裝置上
在編譯的同時會彈出node server的介面,這個服務可以通過usb繫結裝置實現js熱更新
執行命令adb reverse tcp:8081 tcp:8081與裝置建立連線
修改js內容,搖晃手機彈出rn設定選單, 選擇reload更新介面
rn設定選單中選擇 Debug JS Remotely開啟遠端除錯