Android 集成 React Native

涂溪叠
2023-12-01

集成步骤

  • 配置好React Native 依赖和项目结构
  • 创建 .js 文件,编写 React Native 组件的js代码
  • 通过活动添加一个ReactRootView,来承载你的React Native 组件容器
  • 启动 React Native 的 metro 服务。运行应用

开发环境的准备,参考官网来做


项目结构创建

根据如下创建初始目录
/ ReactNativeApp 用来存放React Component 代码
/ Android 用来存放你的原生项目

+ ReactNativeApp
	+ android

终端执行命令

// 创建package.json
npm init
// 下载依赖
yarn add react react-native

下载react 和 react-native 注意版本必须匹配目前最新的匹配版本如下

"dependencies": {
	"react": "17.0.1",
    "react-native": "0.64.0",
}

添加script命令

"start": "yarn react-native start"

为你的应用添加 react 依赖

$rootDir / app / build.gradle

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

$rootDir / build.gradle

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

启用原生模块自动链接

$rootDir / settings.gradle

apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

$rootDir / app / build.gradle 在最底下添加

apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

配置权限

声明网络权限

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

启用开发者菜单 (发布app 时可以去掉这个 activity)

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

允许明文传输

android 9 开始, 默认情况下明文传输是禁止的,只能访问 https 接口,导致你的应用程序链接Metro 获取js bundler 失败

  1. 启用 usesCleartextTraffic
<application
  android:usesCleartextTraffic="true">
  <!-- ... -->
</application>

创键入口文件

在项目的根目录创建一个index.js 文件,作为 react native 在android 上的入口文件。

import {AppRegistry} from 'react-native';
import App from './App';

AppRegistry.registerComponent("ReactNativeApp", () => App)

在项目根目录创建一个App.js 文件,作为根组键

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

const styles = StyleSheet.create({
	container: {
		flex: 1,
		justifyContent: 'center',
		alignItems: 'center',
	},
	text: {
		textAlign: 'center'
	}
})

export default () => (
	<View style={styles.container}>
      <Text style={styles.text}>Hello React Native</Text>
    </View>
)

配置红屏提示

该提示会在 js bundle 运行时异常时,将错误信息显示在模拟器或真机屏幕

private final int OVERLAY_PERMISSION_REQ_CODE = 1;
···
// 在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);
    }
}

最后,必须重写onActivityResult()方法(如下面的代码所示),以便为一致的UX处理接受或拒绝权限的情况。此外,为了集成使用startActivityForResult的本地模块,我们需要将结果传递给ReactInstanceManager实例的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
            }
        }
    }
    mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
}

核心组件:ReactRootView

创建一个新的Activity 来承载 React Component

public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
	private ReactRootView mReactRootView;
	private ReactInstanceManager mReactInstanceManager;
	
	@Override
	protected void onCreate(Bundle saveInstanceState) {
		super.onCreate(saveInstanceState);
		SoLoader.init(this, false);
		
		mReactRootView = new ReactRootView(this);
		List<ReactPackage> packages = new PackageList(getApplication()).getPackages();
		
		mReactInstanceManager = ReactInstanceManager.builder()
			.setApplication(getApplication())
			.setCurrentActivity(this)
			.setBundleAssetName("index.android.bundle")
			.setJSMainModulePath("index")
			.addPackages(packages)
			.setUseDeveloperSupport(BuildConfig.DEBUG)
			.setInitialLifecycleState(LifecycleState.RESUMED)
			.build();
		mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
		setContentView(mReactRootView);
	}
	
	@Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }
}

注意 BuildConfig 不需要导入任何包,该配置由项目自动生成,无需额外引入。同时为MyReactActivity 设置主题

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

调整生命周期

@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);
    }
    if (mReactRootView != null) {
        mReactRootView.unmountReactApplication();
    }
}

/**
调整回退按钮的点击
*/
@Override
 public void onBackPressed() {
    if (mReactInstanceManager != null) {
        mReactInstanceManager.onBackPressed();
    } else {
        super.onBackPressed();
    }
}

/**
调整虚拟设备调用开发者菜单的方式
**/
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
        mReactInstanceManager.showDevOptionsDialog();
        return true;
    }
    return super.onKeyUp(keyCode, event);
}

运行

  1. 先启动 metro 服务,编译js bundle

    yarn start

  2. 启动 android 项目,当进入MyReactActivity 时会立刻从Metro 中读取 js bundle 并显示React 组件

本文的项目地址
github地址

 类似资料: