原生Android集成React Native

使用React Native從零開始開發一款移動應用是一件很愜意的事情,但對於一些已經上線的產品,徹底摒棄原有應用的歷史沉澱,全面轉向React Native是不現實的。所以,使用React Native去統一原生Android、iOS應用的技術棧,把它做爲已有原生應用的擴展模塊,是目前混合開發的最有效方式。
首先,在原生Android項目目錄下執行如下命令建立一個package.json文件。node

yarn init

而後,根據提示輸入對應的配置信息。等待命令執行完成以後,咱們會發現Android項目的根目錄多了一個package.json文件。
接下來,使用以下命令添加React和React Native運行環境的支持腳本。react

yarn add react react-native

執行完命令後,會發現Android項目的根目錄下多了一個node_modules文件夾,裏面包含了React Native開發也運行所需的依賴模塊,原則上這個目錄是不能複製、移動和修改的。
接下來,使用文本編輯器打開package.json文件,配置React Native的啓動腳本,以下代碼。android

"scripts": {
    "start": "yarn react-native start",
  },

此時,package.json文件的完整內容以下所示。web

{
  "name": "AndroidDemo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "dependencies": {
    "react": "^17.0.1",
    "react-native": "^0.63.4"
  },
  "scripts": {
    "start": "yarn react-native start"
  }
}

而後,在Android項目的根目錄下建立一個index.js文件,該文件是React Native的入口文件,代碼以下。json

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, React Native</Text>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
    },
    hello: {
        fontSize: 20,
        textAlign: 'center',
        margin: 10,
    },
});

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

接下來,咱們使用Android Studio打開原生Android項目,並在app目錄的build.gradle文件的dependencies代碼塊中添加React Native和JSC引擎依賴,以下所示。react-native

dependencies {
    ...
    implementation "com.facebook.react:react-native:+" 
    implementation "org.webkit:android-jsc:+"
}

若是不指定依賴的版本,那麼默認使用的是package.json文件中React Native對應的版本。而後,在項目的build.gradle文件的allprojects代碼塊中添加React Native和JSC引擎的路徑,以下所示。網絡

allprojects {
    repositories {
        maven {
            url "$rootDir/../node_modules/react-native/android"
        }
        maven {
            url("$rootDir/../node_modules/jsc-android/dist")
        }
        ...
    }
    ...
}

而後,打開AndroidManifest.xml清單文件,添加網絡權限代碼,以下所示。app

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

若是須要訪問開發者調試菜單,還須要在AndroidManifest.xml清單文件中註冊DevSettingsActivity界面,以下所示。maven

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

接下來,新建一個Activity做爲React Native的容器頁面,並在Activity中建立一個ReactRootView對象,而後在這個對象之中啓動React Native應用代碼,以下所示。編輯器

public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        SoLoader.init(this, false);
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setCurrentActivity(this)
                .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 boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
}

可使用Android Studio的【Alt + Enter】快捷鍵自動導入缺失的語句,而且BuildConfig是編譯時自動生成的,無需額外引入。
因爲React Native應用調試還須要懸浮窗權限,因此在須要在Android項目的代碼中添加懸浮窗權限邏輯,以下所示。

private final int OVERLAY_PERMISSION_REQ_CODE = 1; 

private void requestPermission() {
        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);
            }
        }
}

@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
            }
        }
    }
    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
}

接下來,咱們在AndroidManifest.xml清單文件中註冊MyReactActivity,此處咱們直接使用MyReactActivity替換MainActivity做爲應用的主頁面,以下所示。

<activity
      android:name=".MyReactActivity"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
          <action android:name="android.intent.action.MAIN" />
          <category android:name="android.intent.category.LAUNCHER" />
      </intent-filter>
</activity>

完成上述操做後,咱們在src/main目錄下建立一個assets資源文件夾,而後執行以下打包命令。

react-native bundle --platform android --entry-file index.js --bundle-output app/src/main/assets/index.android.bundle --dev false

接着,執行yarn start命令啓動React Native服務,從新運行原生Android項目便可看到以下圖所示。
在這裏插入圖片描述

相關文章
相關標籤/搜索