RN集成原生Android应用
1.设置目录结构
创建一个空目录用于存放 React Native 项目,然后在其中创建一个/android
子目录,把你现有的 Android 项目拷贝到/android
子目录中。
2.安装javascript依赖包
在项目根目录下创建一个名为package.json
的空文本文件,然后填入以下内容:
{
"name": "rntestthree",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "16.8.3",
"react-native": "^0.59.5"
}
}
scripts
中是用于启动 packager 服务的命令。dependencies
中的 react 和 react-native 的版本取决于你的具体需求。一般来说我们推荐使用最新版本。你可以使用npm info react
和npm info react-native
来查看当前的最新版本。另外,react-native 对 react 的版本有严格要求,高于或低于某个范围都不可以。本文无法在这里列出所有 react native 和对应的 react 版本要求,只能提醒读者先尝试执行 npm install,然后注意观察安装过程中的报错信息,例如require react@某.某.某版本, but none was installed
,然后根据这样的提示,执行npm i -S react@某.某.某版本
。如果你使用多个第三方依赖,可能这些第三方各自要求的 react 版本有所冲突,此时应优先满足react-native
所需要的react
版本。其他第三方能用则用,不能用则只能考虑选择其他库。
接下来我们使用 npm(node 包管理器,Node package manager)来安装 React 和 React Native 模块。 请打开一个终端/命令提示行,进入到项目目录中(即包含有 package.json 文件的目录),然后运行下列命令来安装:
$ npm install
这些模块会被安装到项目根目录下的node_modules/
目录中(所有通过 npm install 命令安装的模块都会放在这个目录中。这个目录我们原则上不复制、不移动、不修改、不上传,随用随装)。
3.把React Native项目添加到你的应用中
3.1 在你的 app 中 build.gradle
文件中添加 React Native 依赖:
dependencies { ... compile "com.facebook.react:react-native:+" // From node_modules. }
如果想要指定特定的 React Native 版本,可以用具体的版本号替换 +
,当然前提是你从 npm 里下载的是这个版本 。
在项目的 build.gradle
文件中为 React Native 添加一个 maven 依赖的入口,必须写在 "allprojects" 代码块中:
allprojects { repositories { ... maven { // All of React Native (JS, Android binaries) is installed from npm url "$rootDir/../node_modules/react-native/android" } } ... }
3.2 屏蔽某些平台产生的错误
在app的build.gradle中的defaultConfig配置
ndk {
abiFilters "armeabi-v7a", "x86"
}
一些SDK版本也可能产生错误,minSdkVersion 16以上
android { compileSdkVersion 28 compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 } defaultConfig { applicationId "com.example.wind.my_react_app" minSdkVersion 16 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" ndk { abiFilters "armeabi-v7a", "x86" } } packagingOptions { exclude "lib/arm64-v8a/librealm-jni.so" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' compile "com.facebook.react:react-native:+" testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'}
3.2 配置权限:
接着,在 AndroidManifest.xml
清单文件中声明网络权限:
如果需要访问 DevSettingsActivity
界面(即开发者菜单),则还需要在 AndroidManifest.xml
中声明:
4. 代码集成:
4.1 React Native 组件
创建一个index.js
文件
首先在项目根目录中创建一个空的index.js
文件。(注意在 0.49 版本之前是 index.android.js 文件)
index.js
是 React Native 应用在 Android 上的入口文件。而且它是不可或缺的!它可以是个很简单的文件,简单到可以只包含一行require/import
导入语句。本教程中为了简单示范,把全部的代码都写到了index.js
里
import React from "react";import { AppRegistry, StyleSheet, Text, View } from "react-native";class HelloWorld extends React.Component { render() { return ( Hello, World ); }}var styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center" }, hello: { fontSize: 20, textAlign: "center", margin: 10 }});AppRegistry.registerComponent("MyReactNativeApp", () => HelloWorld);
4.2 配置运行RN的原生activity
我们还需要添加一些原生代码来启动 React Native 的运行时环境并让它开始渲染。首先需要在一个Activity
中创建一个ReactRootView
对象,然后在这个对象之中启动 React Native 应用,并将它设为界面的主视图。
如果你想在安卓 5.0 以下的系统上运行,请用 com.android.support:appcompat
包中的 AppCompatActivity
代替 Activity
。
import android.content.Context;import android.content.Intent;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.KeyEvent;import com.facebook.react.ReactInstanceManager;import com.facebook.react.ReactRootView;import com.facebook.react.common.LifecycleState;import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;import com.facebook.react.shell.MainReactPackage;public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler { private ReactRootView mReactRootView; private ReactInstanceManager mReactInstanceManager; public static void start(Context context) { context.startActivity(new Intent(context, MyReactActivity.class)); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); 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(); // 注意这里的MyReactNativeApp必须对应“index.js”中的 // “AppRegistry.registerComponent()”的第一个参数 mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null); setContentView(mReactRootView); } @Override public void invokeDefaultOnBackPressed() { super.onBackPressed(); } @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); }}
如果你使用的是 Android Studio , 可以使用Alt + Enter
快捷键来自动为 MyReactActivity 类补上缺失的 import 语句。注意BuildConfig
应该是在你自己的包中自动生成,无需额外引入。千万不要从com.facebook...
的包中引入!
我们需要把 MyReactActivity
的主题设定为 Theme.AppCompat.Light.NoActionBar
,因为里面有许多组件都使用了这一主题。
5.测试集成结果
5.1 启动开发服务器:
运行应用首先需要启动开发服务器(Packager)。你只需在项目根目录中执行以下命令即可:
$ npm start
如果Packager服务器启动成功,则http://localhost:8081/index.android.bundle?platform=android
能看到如下信息:
var __DEV__=true,__BUNDLE_START_TIME__=this.nativePerformanceNow?nativePerformanceNow():Date.now(),process=this.process||{};process.env=process.env||{};process.env.NODE_ENV="development";(function (global) { "use strict"; global.__r = metroRequire; global.__d = define; global.__c = clear; global.__registerSegment = registerSegment; var modules = clear(); var EMPTY = {}; var _ref = {}, hasOwnProperty = _ref.hasOwnProperty; function clear() { modules = Object.create(null); return modules; } if (__DEV__) { var verboseNamesToModuleIds = Object.create(null); var initializingModuleIds = []; }
否则,会出现错误信息。
可以重置包服务器:
adb reverse tcp:8081 tcp:8081
npm start
5.2 运行应用:
保持 packager 的窗口运行不要关闭,然后像往常一样编译运行你的 Android 应用(在命令行中执行./gradlew installDebug
或是在 Android Studio 中编译运行)。
如果你是使用 Android Studio 来编译运行,有可能会导致 packager 报错退出。这种情况下你需要安装watchman。但是 watchman 目前没有稳定的 Windows 版本,所以在 Windows 下这种崩溃情况暂时没有特别好的解决方案。
编译执行一切顺利进行之后,在进入到 MyReactActivity 时应该就能立刻从 packager 中读取 JavaScript 代码并执行和显示:
更多相关文章
- android 权限定义的文件,位置
- Android Studio中src/main/res/values中strings.xml文件中字符串
- 【Android开源项目分析】android轻量级开源缓存框架——ASimpleC
- android 应用自身检测版本并下载
- Android之SDK、NDK、JNI和so文件
- Android:系统信息(内存、cpu、sd卡、电量、版本)的获取
- android通过chmod命令实现文件权限修改
- Android心得3.2--用SAX解析器解析xml文件内容
- Android 用style简化layout布局文件