RN與現有的原生app集成


https://facebook.github.io/react-native/docs/integration-with-existing-apps.html

  RN可以很好地支持往一個原生的app上添加RN的組件。通過簡單的步驟,我們可以添加RN基礎的特征、組件等。后面以android為例。

關鍵思想(概要)

  1. 設置RN的依賴和結構目錄
  2. 用JS開發RN組件
  3. 添加一個ReactRootView到android app上,這會作為RN組件的容器
  4. 開啟RN服務器和運行原生app
  5. 檢查RN組件是否正常工作

預備知識

  按照官方指引,設置好RN開發環境。

  1. 設置目錄結構。把android項目“內容”復制到RN項目根目錄下的android文件夾中(初始化的RN項目中就已經有這樣一個文件夾了,里面有初始的android項目內容)
  2. 安裝JS依賴。在RN項目創建一個package.json,內容如下(初始的RN項目也有這些內容了)
    {
      "name": "MyReactNativeApp",
      "version": "0.0.1",
      "private": true,
      "scripts": {
        "start": "node node_modules/react-native/local-cli/cli.js start"
      }
    }

    然后安裝react和react-native依賴

    npm install --save react@16.0.0-beta.5 react-native

把RN添加到app中

配置maven倉庫

  把RN依賴添加到android/app/build.gradle中(測試發現不能使用+,應該指定版本,將+替換為npm中對應的RN版本號,如package.json中 ^0.5,則將+替換為0.5):

dependencies {
    ...
    compile "com.facebook.react:react-native:+" // From node_modules.
}

  光光以上這么配置,gradle會找不到這個依賴,需要在android/build.gradle中配置一個倉庫告訴gradle去哪里找依賴(確保添加到allproject這個塊中,而且要在所有其他maven倉庫之上。同時確保下面的url是正確的):

allprojects {
    repositories {
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
        ...
    }
    ...
}

配置權限

  往AndroidManifest.xml清單文件中加上:

<uses-permission android:name="android.permission.INTERNET" />

  如果需要在原生app中打開開發者菜單,也需要在清單文件中加上(如果要發布則把下面這行去掉):

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

代碼集成

  在項目的根目錄創建一個index.js,這是RN程序的入口點,往index.js中添加如下內容

import React from 'react';
import {AppRegistry, StyleSheet, Text, View} from 'react-native';

class HelloWorld extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, World</Text>
      </View>
    );
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld);

ReactRootView

  現在需要寫一些原生代碼來啟動RN runtime和渲染界面。在activity中創建ReactRootView,並作為主內容顯示:

public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);

        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }
}

  以上的ReactInstanceManager可以在多個activity和fragment之間共享。接着使RN與activity的生命周期同步(這是為了讓JS代碼能處理這些生命周期,如JS可以檢測到用戶按了后退):

@Override
protected void onPause() {
    super.onPause();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostPause(this);
    }
}

@Override
protected void onResume() {
    super.onResume();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostResume(this, this);
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();

    if (mReactInstanceManager != null) {
        mReactInstanceManager.onHostDestroy(this);
    }
}

@Override
 public void onBackPressed() {
    if (mReactInstanceManager != null) {
        mReactInstanceManager.onBackPressed();
    } else {
        super.onBackPressed();
    }
}

  如果API大於23,需要配置開發模式下錯誤信息的顯示權限,因為錯誤信息必須要顯示在所有窗口之上。在activity的onCreate中添加如下代碼:

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); } }

  接着需要重寫activity的onActivityResult方法

@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...  } } } }

  接着設置開發者菜單的彈出:  

@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
        mReactInstanceManager.showDevOptionsDialog();
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

  最后,在清單文件中對這個activity進行聲明

<activity
  android:name=".MyReactActivity"
  android:label="@string/app_name"
  android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>

運行

  到根目錄下執行npm start來打包生成js bundle。然后直接構建app(如使用android studio)啟動app看效果。

實踐

  通過android studio創建一個項目,項目目錄指定為root/android/。

  項目地址:https://github.com/947133297/rn-ntegration-with-existing-apps


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM