React Native集成到现有原生Android应用

82 阅读5分钟

使用React Native(以下简称RN)从头开始制作一个新的应用会是一个非常好的选择。但如果只想给现有的原生应用中添加一两个视图或是业务流程,RN也同样不在话下。只需简单几步,就可以给原有应用加上新的基于RN的特性、画面和视图等。

一、核心概念

把 React Native 组件集成到 Android 应用中有如下几个主要步骤:

  1. 配置好项目结构。

  2. 安装必要的 JavaScript 依赖。

  3. 在 Gradle 中配置 React Native 依赖。

  4. 创建 ts 文件,编写 React Native 组件的 ts 代码。

  5. 使用 ReactActivity 来把 React Native 集成到你的 Android 项目代码中。

  6. 运行 Metro 服务,验证集成结果。

二、开发环境准备

在正式讲解之前,我们需要按照开发环境搭建安装RN在Android平台上所需的一切依赖条件,包括Node、Yarn以及原生Android运行环境。

1,配置项目目录结构

首先,创建一个空目录用于存放RN项目,然后在其中创建一个/android子目录,把现有的 Android 项目拷贝到/android子目录中。

2,安装 JavaScript 依赖包

在根目录下运行以下命令:

curl -O https://raw.githubusercontent.com/react-native-community/template/refs/heads/0.75-stable/template/package.json

上面的命令会把RN 社区模板 中的 package.json 文件复制到你的项目中。接下来我们使用 yarn 或 npm(两者都是 node 的包管理器)来安装必要的模块。

npm install 
//或者
yarn install

执行完上面的命令后,所有 JavaScript 依赖模块都会被安装到项目根目录下的node_modules/目录中。

我们还需要把node_modules/目录记录到.gitignore文件中(即不上传到版本控制系统,只保留在本地)。可以参考 React Native 社区模板 中的.gitignore文件

三、将RN添加到原生Android应用

配置 Gradle

首先,打开原生Android项目的settings.gradle文件,添加如下React Native Gradle Plugin 来配置项目的依赖项和设置。

// 此处配置用于自动链接第三方原生库的 React Native Gradle 插件
pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") }
plugins { id("com.facebook.react.settings") }
extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() }
// 如果使用 .gradle.kts 文件:
// extensions.configure<com.facebook.react.ReactSettingsExtension> { autolinkLibrariesFromCommand() }
includeBuild("../node_modules/@react-native/gradle-plugin")


// 在这里引入你已有的其他 Gradle 模块。
// include(":app")

然后,需要打开最外层的 build.gradle 文件并添加这一行。

buildscript {
    repositories {
        google()
        mavenCentral()
    }
    dependencies {
       //添加下面这行
       classpath("com.facebook.react:react-native-gradle-plugin")
    }
}

上面的脚本将确保 React Native Gradle Plugin 在项目中可用,同步一下工程。 最后,在 app/build.gradle 文件中添加以下行:

apply plugin: "com.facebook.react"


repositories {
    mavenCentral()
}


dependencies {
    // Other dependencies here
    implementation "com.facebook.react:react-android"
    implementation "com.facebook.react:hermes-android"
}


react {
   autolinkLibrariesWithApp()
}

最后,需要打开应用的 gradle.properties 文件并添加以下行:

reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64
newArchEnabled=true
hermesEnabled=true

配置权限

在 AndroidManifest.xml 清单文件中声明网络权限:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">


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


    <application
      android:name=".MainApplication">
    </application>
</manifest>

然后,需要在 AndroidManifest.xml 中启用 允许明文传输 (在src/debug/AndroidManifest.xml 中)添加如下代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">


    <application
       android:usesCleartextTraffic="true"
       tools:targetApi="28"
    />
</manifest>

从 Android 9 (API level 28)开始,默认情况下明文传输(http 接口)是禁用的,只能访问 https 接口,这将阻止应用程序连接到Metro bundler。添加usesCleartextTraffic之后将允许进行明文通信。

四、代码集成

index.js文件

现在我们将修改原生 Android 应用程序以集成 RN。打开RN项目下的index.js文件,index.js是 RN 应用在 Android 上的入口文件,而且它是不可或缺的。

import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';


AppRegistry.registerComponent(appName, () => App);

创建 App.tsx 文件

接下来,我们修改RN项目App.tsx 文件。这是一个 TypeScript 文件,可以包含 JSX 表达式。它包含了我们将在 Android 应用中集成的根 React Native 组件。

import React from 'react';
import {
  SafeAreaView,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  useColorScheme,
  View,
} from 'react-native';


import {
  Colors,
  DebugInstructions,
  Header,
  ReloadInstructions,
} from 'react-native/Libraries/NewAppScreen';


function App(): React.JSX.Element {
  const isDarkMode = useColorScheme() === 'dark';


  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };


  return (
    <SafeAreaView style={backgroundStyle}>
      <StatusBar
        barStyle={isDarkMode ? 'light-content' : 'dark-content'}
        backgroundColor={backgroundStyle.backgroundColor}
      />
      <ScrollView
        contentInsetAdjustmentBehavior="automatic"
        style={backgroundStyle}>
        <Header />
        <View
          style={{
            backgroundColor: isDarkMode
              ? Colors.black
              : Colors.white,
            padding: 24,
          }}>
          <Text style={styles.title}>Step One</Text>
          <Text>
            Edit <Text style={styles.bold}>App.tsx</Text> to
            change this screen and see your edits.
          </Text>
          <Text style={styles.title}>See your changes</Text>
          <ReloadInstructions />
          <Text style={styles.title}>Debug</Text>
          <DebugInstructions />
        </View>
      </ScrollView>
    </SafeAreaView>
  );
}


const styles = StyleSheet.create({
  title: {
    fontSize: 24,
    fontWeight: '600',
  },
  bold: {
    fontWeight: '700',
  },
});


export default App;

集成到原生Android代码中

首先,我们需要在原生Android项目的Application类中正确的初始化RN,如下所示。

import android.app.Application
import com.facebook.react.PackageList
import com.facebook.react.ReactApplication
import com.facebook.react.ReactHost
import com.facebook.react.ReactNativeHost
import com.facebook.react.ReactPackage
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.soloader.SoLoader
import com.facebook.react.soloader.OpenSourceMergedSoMapping


class MainApplication : Application(), ReactApplication {


 override val reactNativeHost: ReactNativeHost =
      object : DefaultReactNativeHost(this) {
        override fun getPackages(): List<ReactPackage> = PackageList(this).packages
        override fun getJSMainModuleName(): String = "index"
        override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
        override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
        override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
      }


 override val reactHost: ReactHost
   get() = getDefaultReactHost(applicationContext, reactNativeHost)


  override fun onCreate() {
    super.onCreate()
   SoLoader.init(this, OpenSourceMergedSoMapping)
   if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
     load()
   }
  }
}

接下来,我们需要创建一个新的 Activity,它将扩展 ReactActivity 并托管 RN 代码。此Activity将负责启动 React Native 运行时并渲染 React 组件。

import com.facebook.react.ReactActivity
import com.facebook.react.ReactActivityDelegate
import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
import com.facebook.react.defaults.DefaultReactActivityDelegate


class MyReactActivity : ReactActivity() {


    override fun getMainComponentName(): String = "HelloWorld"


    override fun createReactActivityDelegate(): ReactActivityDelegate =
        DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
}

注意:getMainComponentName方法返回的名称需要和RN项目中index.js文件中registerComponent的名称相对应。

每当创建一个新的 Activity 时,都需要将其添加到原生Android项目的AndroidManifest.xml 文件中。并且,还需要将 MyReactActivity 的主题设置为 Theme.AppCompat.Light.NoActionBar(或任何非 ActionBar 主题),否则你的应用程序将在 React Native 屏幕顶部呈现 ActionBar。

<manifest xmlns:android="http://schemas.android.com/apk/res/android">


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


    <application
      android:name=".MainApplication">


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

测试集成

到此,我们已经完成将 RN集成到Android应用程序的所有基本步骤。现在我们将启动 Metro工具,将您的 TypeScript 应用程序代码构建为一个bundle包。打开RN项目的 metro.config.js 文件,然后添加如下代码。

const {getDefaultConfig} = require('@react-native/metro-config');
module.exports = getDefaultConfig(__dirname);

配置文件准备好后,就可以运行打包工具了。在项目的根目录中运行以下命令:

yarn start

现在,打开Android Studio,然后运行您的Android应用。一旦应用打开从开发服务器加载 JavaScript 代码并显示。

EmbeddedAppAndroidVideo.gif

创建发布包

等待RN的功能开发完成之后,我们可以使用 Android Studio 创建发布版本。它的创建过程和与之前创建原生 Android 应用的发布版本是一样的。其中,React Native Gradle 插件将负责将 JS 代码捆绑在您的 APK/App Bundle 中。以下是打包命令:

cd android
# For a Release APK
./gradlew :app:assembleRelease
# For a Release AAB
./gradlew :app:bundleRelease