Android项目接入React Native详细分析及跳坑

RN嵌入app所踩的坑

本篇文章不会包括RN中的相关概念,生命周期等内容,
只包括在接入过程中所遇到的一些问题,
接入RN的平台为Android,开发环境为mac.

官方文档

首当其冲抛出官方文档,接入是基于官方文档的.
下面会列出接入的步骤以及所遇到的问题.
官方文档

问题及注意点汇总

先描述接入过程中遇到的问题及注意事项,后面会在接入过程中给出相关解决办法.

  1. android项目依赖的RN版本不对.
  2. react 引入版本不对.
  3. 真机调试
  4. 运行时libgnustl_shared.so使用的版本不对

接入步骤

创建android项目

正常使用Android Studio创建Android项目.
目前创建的项目就是常规的项目,跟RN还没有任何关系.

添加RN相关依赖

使用npm命令创建项目并添加依赖

按照顺序在项目根目录执行下面的命令

//初始化package.json
$ npm init
//安装react react-native并保存.此处可能会导致一些问题,参见后面的问题
$ npm install --save react react-native
//获取.flow的配置文件
$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

上面三步是项目接入RN的基础,因为需要通过npm来下载RN相关的环境依赖.

需要注意如下几点

  1. 初始化项目,需要注意根目录的位置,也就是执行npm init时所在的目录,
    此处是我遇到的第一个坑,导致问题1的产生.无论时我们创建的项目本身,还是用到的RN的第三方库,
    都需要引用RN框架,RN框架的引入是通过本地maven库的方式引入的,而对RN项目引入的路径是在build.gradle中写死的(引入的第三方库).
    所以如果RN的初始化的目录不对,会导致找不到RN框架,或者RN框架的版本不对.(因为不指定本地库的话,默认时从jcenter中拉取的,但是RN的最新版本是没有提交到jcenter的,所以会出错,或者拉取的版本不对).
    下图为目录结构图,reactnativeintergration为root目录.android目录下,是我们创建的android项目的代码.我们的项目及第三方的RN库对RN本身的依赖都是通过$rootDir/../node_modules/react-native/android来查找的.所以如果相对路径不对,则会出现该问题Failed to resolve: com.facebook.react:react-native.

目录结构图

按照这样的目录结构,我们执行npm init的位置应该是在reactnativeintegration目录下.

2.由于执行npm install时未指定RN以及react的版本,所以获取的版本并不一定是我们需要的.
此处遇到了另外的坑,也就是问题2.
未指定版本时,使用默认安装的,则react安装的版本为15.x.
而使用15.x是会报该错误的Unable to resolve module react/lib/ReactDebugCurrentFrame
解决的办法就是指定依赖的react版本为16.xx.

npm install -save react@~16.0.0-alpha.6

参考文章
3.flow的作用.
第三个命令时复制flow的配置文件,没什么问题.
flow是Facebook用来给js添加静态类型的库,
详细可以参考flow官网

添加运行命令

在package.json中的的scripts标签下添加如下命令.
添加之后可以直接运行npm start启动bundle server.

"start": "node node_modules/react-native/local-cli/cli.js start"

创建index.android.js文件

此处是添加一个RN的页面.具体代码不贴,参照代码index.android.js.

为Android项目中添加RN依赖

RN在native层是需要项目进行依赖的.所以需要在build.gradle中添加项目依赖.
示例项目中是依赖RN0.43.4版本的.需要注意的是,对于本地maven库的添加,如果不指定maven库的地址则会通过jcenter仓库去获取,但是RN最新版本的库是没有传到jcenter中的.所以需要在build.gradle中添加maven中心库,添加的maven库需要指向node_modules中,就是因为这个原因,所以需要在第一步通过npm init初始化项目时,将目录位置指定正确,否则就会遇到问题1

//添加RN库的依赖,指定版本
//app/build.gradle
dependencies {
    ...
    compile "com.facebook.react:react-native:0.43.4" // From node_modules.
}
//添加maven本地库
//root/build.gradle
allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
    ...
}

添加权限

访问网络的权限时必须的.
<uses-permission android:name="android.permission.INTERNET" />
overlay的权限根据不同的target api进行不同的处理.
我的示例中的target-api设置的为22.所以没有适配新的权限系统.
也就是说,如果你是22以上的项目,则需要动态获取下在其他界面之上绘制内容的权限.
添加权限

添加Native代码

RN是需要一个运行渲染环境的,我的代码中将这些操作放在一个Activity中,
当然也可以放在Fragment中.此处需要注意的是,Activity的theme需要设置为@style/Theme.AppCompat.Light.NoActionBar,因为有些第三方的组件依赖该theme.
具体代码参考示例RNContainerActivity类.

运行app

1.正常安装app
2.执行adb reverse tcp:8081 tcp:8081
这么做是为了做端口转发,端口转发后,当手机访问http://localhost:8081时,
会被转发到执行该命令的电脑上的8081端口.
从而访问到bundle.js文件.此处对应问题3.
推荐一篇文章关于reverse命令的
3.运行时提示出现so找不到的问题.
java.lang.UnsatisfiedLinkError: dlopen failed: "/data/data/reactnative.com.yftx.reactnativeintegration/lib-main/libgnustl_shared.so" is 32-bit instead of 64-bit
我的测试手机时pixel xl,由于cpu架构不同,会导致找不到so库,
因为在初始化创建项目时,没有指定需要包含哪些cpu架构的so文件.
通过参照通过react-native init创建的项目中的build.gradle添加上相关so依赖即可.

总结及代码

接入过程总体来说不是很复杂,暂时先写这么多.
只需要注意一下上面提到的几个问题就行了.
欢迎关注我的这个项目,技术含量没有,但是后面会有比较详细的接入的注释.
项目代码

未完成的部分

1.RN项目同Native项目之间通讯.
2.Native类容器ReactInstanceManager的使用.
3.bundle的打包及部署.
4.热更新的方式.
5.RN的裁剪.
上面几块会分别写还是更新改文档还不确定,欢迎大家关注.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容