Android 集成React Native 到现有的项目踩坑记录
集成步骤
官方文档:https://facebook.github.io/react-native/docs/0.54/integration-with-existing-apps
借鉴博客:https://blog.csdn.net/u012455070/article/details/78926526
(1)配置react-native的开发环境
(2)创建一个react-native 的项目
(3)把项目中的android目录里面的东西换成现有的项目
(4)配置android项目的build.gradle文件以及各种依赖
(5)运行项目,运行服务,设置ip端口调试。
(6)各种踩坑问题,比如不支持64位手机的so库问题,找不到服务,由于react native 版本问题导致的各种错误等等
官方文档的集成步骤;
1、安装 node.js python2 jdk 8
这个安装过程就不说了。网上一大堆
2、下载更新React Native CLI
命令:npm install -g react-native-cli
执行这行命令就可以使用react-native 命令了。比如 使用命令运行
3、android 环境配置和模拟器或者手机连接
由于我是做android的,所以这些就跳过了,不清楚的看官方文档或者上网查
4、创建新的应用程序
重点来了,创建应用的时候执行命令:react-native init AwesomeProject
这里的AwesomeProject是项目名称可以随便换,但是必须以字母开头。 由于下载是在国外所以特别慢,所以我们要添加以下国内镜像。
npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist
这两个都可以,会显著提高下载速度。设置了镜像,然后再执行创建的命令。
5、运行新应用的采坑记录
指定react 和react-native 的版本。
项目目录下的 node_modules 文件夹是 reactnative 所依赖的js的一些东西。
如果没有,我们可以再项目跟目录执行 npm install
命令下载
这个时候我们要注意一下版本号,因为这里遇到坑了。目前最新的react–native可能是0.56 会出现一个bug
比如最新版本
react-native-cli: 2.0.1
react-native: 0.56.0
但是运行的时候出现 Unable to resolve module ‘AccessibilityInfo’ 这个错误,所以建议还是版本低一点,这里使用稳定版
切换步骤:
(1)先将旧版卸载
npm uninstall -g react-native-cli
npm uninstall -g react-native
(2)再安装指定版本
npm install -g react-native@0.55.4
npm install -g react-native-cli@1.2.0
可以再项目初始化的时候指定下,不指定的话,只要版本对也没问题,自己查看下
react-native init --version="0.55.4" myFirstApp
6、解决红屏错误:Module build failed: Error: Plugin 0 specified in “base” … provided an invalid property of “default”
如果出现上面错误执行下面命令
npm install --save-dev babel-preset-react-native@2.1.0
7、解决 React_Native 无法运行再64位机器上
“/data/data/com.xxx.xxx/lib-main/libgnustl_shared.so” is 32-bit instead of 64-bit 这个错误
参考文章:https://blog.csdn.net/u013531824/article/details/53931307
Android不能同时加载32和64位本机库。 如果您至少有一个依赖库使用ARM64支持编译的扩展,而另外一些依赖库仅支持ARM32,就会出现问题。 系统将检测ARM64依赖关系,加载它,然后拒绝加载仅ARM32的so库,就可能导致应用程序崩溃。
所以,要再项目中excute 64位的几个so库,使用32位的。
这个根据不同项目设置,查一下自己项目用到了哪些64位的so库,都设置一遍
我的项目需要移除这些,然后就不报错了。Native Libs Monitor 这个软件很好用
ndk {
//设置支持的SO库架构
abiFilters 'armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
packagingOptions {
exclude "lib/arm64-v8a/libgnustl_shared.so"
exclude "lib/arm64-v8a/libijkffmpeg.so"
exclude "lib/arm64-v8a/libijkplayer.so"
exclude "lib/arm64-v8a/libijksdl.so"
exclude "lib/arm64-v8a/libimagepipeline.so"
exclude "lib/arm64-v8a/librtmp-jni.so"
}
8、把android 原生项目拷贝到reactnative 项目的android 目录下
上面步骤可以运行一个react-native 的简单项目,接下来时怎么集成到现有的Android 项目
react-native 项目结构如下:
我们做android的话,是用Android studio 打开 android 这个目录的。
6、修改gradle 的依赖配置
dependencies {}闭包下 所有的compile 替换位implementation 或者api因为我的Android studio是3.1.3,老报错说compile 2018年底要删除已废弃。另外我的gradle是4.4 build gradle 工具 是3.1.3
(1)Android 项目根目录的 build.gradle文件修改
如下:如果还是不行,建议跟我一样,加上google(). .可能如果是最新版 jencter有问题,用的时候调整下顺序试一试。尽量不要用最新版本的react-native
allprojects {
repositories {
google()
jcenter()
maven { url "https://jitpack.io" }
//添加这个maven地址,不然无法下载 react-native库
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
}
}
再app 的build.gradle 中添加依赖
使用api 或者implementation 都可以, 这里我也制定了版本。
dependencies {
.........
api "com.facebook.react:react-native:0.55.4"
}
7、配置权限
<uses-permission android:name="android.permission.INTERNET" />
//我还要添加一个权限,建议也添加了
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
再调试的时候我们一般需要访问DevSettingsActivity,所以也需要添加到AndroidManifest.xml:
手机摇一摇,或者菜单,设置 电脑服务的ip地址和端口要用到
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
8、代码集成
刚刚创建的最简单的react-native 已经有了。我们就再我们Android 项目中加载这个最简单的页面
public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
private final int OVERLAY_PERMISSION_REQ_CODE = 1;
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这里不加权限判断 6.0或以上机型会闪退
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);
}
}
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
//这是设置assets目录下的打包过的js文件名 这个文件可用命令生成 但调试期间我们使用npm server动态注入 发布时才将它打进assets
.setBundleAssetName("index.android.bundle")
//这里设置js入口文件 旧一点的api可能是setJSMainModuleName 但我的版本是0.51.0 取而代之的是setJSMainModulePath方法
.setJSMainModulePath("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意这里的“FirstApp”必须
// 对应index.js”中的“AppRegistry.registerComponent()”的第一个参数值
// 对应“package.json”中的“name”属性值
// 最好也将“app.json”中的“name”和“displayName”改成它
mReactRootView.startReactApplication(mReactInstanceManager, "FirstApp", null);
setContentView(mReactRootView);
}
@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)) {
}
}
}
}
@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);
}
}
以上是我的activity,大概意思和官网一样。。代码直接复制就行,需要注意的是:
代码制定的文件名一定要和 配置文件中的一致,要检查
app.json中的name和displayName属性值
ndex.js中registerComponent的第一个参数值
package.json中的name属性值
这几个值要保持一致
9、在真机上运行项目
直接在 reat-native 项目根目录运行命令 react-native run-android , 跳转到上面activity
然后运行起来如果是红屏,说是连不上服务,就摇一摇手机,选择 Debug server host 啥的,设置电脑的ip:8081 这样就能打开了。
或者,直接用Android studio 运行自己的Android 项目, 跳转到上面react 的activity ,也可以是fragment的。
如果出现错误,继续百度谷歌解决。。。有坑是肯定的嘛。先记录这些