欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android 集成React Native 到现有的项目踩坑记录

程序员文章站 2022-03-16 17:09:46
...

集成步骤

官方文档: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’ 这个错误,所以建议还是版本低一点,这里使用稳定版
Android 集成React Native 到现有的项目踩坑记录

切换步骤:
(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 集成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的。
如果出现错误,继续百度谷歌解决。。。有坑是肯定的嘛。先记录这些