React Native客户端服务器分开集成方案

本文详细介绍如何将React Native项目与现有Android应用集成,并解决过程中遇到的各种问题,包括SDK兼容、依赖冲突及调试支持等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

刚刚接触React Native,发现网上在原有项目上集成RN时总是把Server和native代码混在一起,这样子很难维护,所以我们要想办法把server的代码和native的代码分开处理。

如何分开集成呢?

构建客户端

1.在我们Android项目中,可以新建一个RNLib的module,在其中的build.gradle中配置如下(这个是已经解决了后边碰到的问题的最终结果,大家如果在集成时遇到了问题可以参考下边这个文件):

apply plugin: 'com.android.library'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        minSdkVersion 15
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        ndk{
            abiFilters "armeabi-v7a", "x86"
        }

    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile ( "com.facebook.react:react-native:+",{
        exclude group: 'com.android.support',module:'recyclerview-v7'
        exclude group:'com.android.support',module:'support-v4'
    })

}

然后可以新建一个Activity,用于承载RN的页面:

package com.xx.xx;

import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;

import com.facebook.react.BuildConfig;
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 MainActivity extends Activity
        implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    private LifecycleState mLifecycleState
            = LifecycleState.BEFORE_RESUME;

    @Override
    protected void onCreate( Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            if (!Settings.canDrawOverlays(this)) {
                Intent serviceIntent = new Intent(
                        Settings.ACTION_MANAGE_OVERLAY_PERMISSION);
                startActivity(serviceIntent);
            }
        }
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(mLifecycleState)
                .build();
        mReactRootView.startReactApplication(mReactInstanceManager,
                "HelloWorld", null);

        setContentView(mReactRootView);
    }

    @Override
    protected void onPause() {
        super.onPause();

        mLifecycleState = LifecycleState.BEFORE_RESUME;

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

        mLifecycleState = LifecycleState.RESUMED;

        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        mReactRootView.unmountReactApplication();
        mReactRootView = null;

        if (mReactInstanceManager != null) {
            mReactInstanceManager.destroy();
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode,
                                 Intent data) {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onActivityResult(this,requestCode,
                    resultCode, data);
        }
    }

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        }
        else {
            super.onBackPressed();
        }
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }
}

别忘记在Manifest文件中声明该Activity。接下来我们只需要在我们的原生Android项目中对应需要跳转的位置加上Intent跳转即可。

这期间,你可能遇到的坑有:



 
1.最低版本sdk兼容问题
Error:Execution failed for task ':rnlib:processDebugAndroidTestManifest'.
> java.lang.RuntimeException: Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version 16 declared in library [com.facebook.react:react-native:0.37.0] D:\MyProject\rnlib\build\intermediates\exploded-aar\com.facebook.react\react-native\0.37.0\AndroidManifest.xml
Suggestion: use tools:overrideLibrary="com.facebook.react" to force usage
解决办法:可以提示在app中的Manifest文件中的use tools添加接下来我们只需要将原生项目拷贝到Android文件夹下即可。 use tools:overrideLibrary="com.facebook.react"。如果原来就已经有其他overrideLibrary的话,只需要在后边追加即可。


 
2.v7包和v4包和你项目中的引用重复了。

解决办法:


 compile ( "com.facebook.react:react-native:+",{
        exclude group: 'com.android.support',module:'recyclerview-v7'
        exclude group:'com.android.support',module:'support-v4'
    })
在集成react-native包时exclude重复的包,常见的是v7包。接下来我们只需要将原生项目拷贝到Android文件夹下即可。

 
3.Error:Execution failed for task ':58moneybox-app:transformClassesWithDexForDebug'.
> com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command 'C:\Program Files\Java\jdk1.8.0_91\bin\java.exe'' finished with non-zero exit value 2
这个问题大部分也是资源重复的问题,我当时时排除了v7包,但是v4包并没有报 duplicate的问题,而是报了这个,搜了好多资料。尝试排除v4就可以了。
如果还不可以那么进行如下操作:
1.查看是否有重复导入的jar包
2.修改builde.gradle buildToolsVersion "23.0.2" 改为 最新版
3.builder.gradle 下添加 defaultConfig {
       .....       
       multiDexEnabled true
        .....
    }

    dexOptions {
        incremental true
        javaMaxHeapSize "4g"
    }
另外如果使用了最新的build tools    compilesdk也要使用最新的 依赖的support也使用最新的  三者要保持一致



 
4.Error:(12, 0) Error: NDK integration is deprecated in the current plugin. Consider trying the new experimental plugin. For details, see http://tools.android.com/tech-docs/new-build-system/gradle-experimental. Set "android.useDeprecatedNdk=true" in gradle.properties to continue using the current NDK integration.
<a href="openFile:D:\58moneybox-react_native-2.2.0\rnlib\build.gradle">Open File</a>
这个提示也非常明显,在gradle.properties中添加android.useDeprecatedNdk=true.



5.如果这样做,总是提示RN中的类找不到,那么你看一下你引用的RN中的类是否真的不存在。
  

我当时碰到的情况是本地下载的react-native对应的aar总是0.20.0的包,而代码里用到的类却是0.37.0的包,后来想了半天,才想到是本地maven仓库的事儿,然后我将后边服务器端构建时生成的RNServer\node_modules\react-native\android\com\facebook\react\react-native\0.37.0这个目录复制到maven仓库,然后运行,发现真的可以了,会重新下载0.37.0对应的aar包。


6.当我们运行时,发现有些x86手机会找不到其他你用到的so,这是因为rn中有些只有x86和v7的so,而so的原理是一旦有对应的文件夹,就会去这个文件夹下找所有对应的so,当其他第三方的so不足时,我们就需要对rn做改造。将rn中相关的so拷贝到项目总,然后添加so过滤。
方法如下:

添加so过滤:
ndk {
abiFilters "armeabi"
}

sourceSets {
    main {
      jniLibs.srcDirs = ['libs']
    }
}


安装我们对应的包,等服务器端搭建好后,我们来测试结果。

构建服务器端:

如果您还没有RN环境,可以参考中文官网,先构建环境:http://reactnative.cn/docs/0.38/getting-started.html#content。

接下来就是在你要构建server的目录下运行

react-native init AwesomeProject
cd AwesomeProject
react-native run-android


运行npm start。

我们打开调用我们RNActivity的地方,发现报错了。



1.Java.lang.RuntimeException: Could not get BatchedBridge, make sure your bundle is packaged correctly
解决方案:运行

[java]  view plain  copy
  1. react-native bundle —platform android —dev false —entry-file index.android.js —bundle-output MyYhao/app/src/main/assets/index.android.bundle —sourcemap-output MyYhao/app/src/main/assets/index.android.map —assets-dest MyYhao/app/src/main/res/  
react-native bundle —platform android —dev false —entry-file index.android.js —bundle-output  MyProject/app/src/main/assets/index.android.bundle —sourcemap-output
MyProject/app/src/main/assets/index.android.map —assets-dest MyProject/app/src/main/res/

注意assets的目录,我是在里面直接新建了index.android.bundle和index.android.map两个空文件,然后运行的,会自动往里面写入代码,然后运行就可以了


2.我们摇一摇发现调不出调试页面,打开悬浮窗权限仍然是不可以。经过查看才发现我们的RNActivity中原本设置的setUseDeveloperSupport(DebugConfig.Debug),

DebugConfig.Debug返回的值为false,我们将setUseDeveloperSupport方法的参数传为true即可。


接下来运行,发现终于可以正常开发RN了,欢呼吧。在RN开发中会遇到各种坑,需要大家耐心下来一点点攻克。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值