原生代码中接入React Native

来源:互联网 发布:mac系统密码忘记 编辑:程序博客网 时间:2024/05/17 06:05

       查阅网上资源和博客,全部是在原生的基础上一点一点的加文件实现使原生项目变成React Native项目,步骤较多,比较复杂,容易出现各种问题,对于项目不是很大,文件目录不是过于复杂的原生项目尝试利用先新建React Native项目,然后将原生代码集成进去的办法(基于Android平台、IOS类似)。


一、打开现有项目

利用Android Studio打开现有原生项目,如下图所示。



二、初始化一个React Native项目

这里不再赘述,现在书籍或者网上相关文档很多,跑一遍测试能否正常运行。


三、更换包名及appid

如果新建完成后的React Native项目中android目录中的包名和appid不一致,可以将包名和appid修改,然后重新跑一遍工程检测是否能够运行。这样为了做到和之前原生代码一致,如果没有此方面需求或者新建完成后的项目包名和appid都一样则可以跳过此步骤。


四、将原生项目中指定目录copy到React Native项目中

主要涉及java目录、res目录、assets目录、jniLibs与lib目录、build.gradle与AndroidManifest配置文件,如下图所示,左侧为原生工程目录,右侧为React Native中的android目录。



最关键并且需要注意的是build.gradle与AndroidManifest两个配置文件,build.gradle文件中的依赖只移动红色区域部分依赖,蓝色部分为React Native项目初始化化时自动生成的,不用动,如下图所示。




AndroidManifest配置文件中需要移动<uses-permission android:name="android.permission.INTERNET" />类似各种权限的部分和注册的Activity部分,如果lib下的jar包不能识别,需要右键jar然后add as library。 复制完毕以上目录和文件再用Android Studio跑一遍,测试程序能否跑通。


五、编写代码

(1)  参见React Native与原生混编博客,可以实现从React Native到原生或者原生到React Native页面,这里不再赘述。


(2)  React Native中MainApplication与之前原生代码中XXXApplication的代码合并,这个是要注意的地方,没有冲突的情况下,建议直接将XXXApplication的代码粘贴到React Native自动生成的MainApplication中,如果有代码冲突,具体问题具体分析。


(3)  在原生代码MainActivity的恰当位置或者想用React Native去实现的页面编写跳转React Native的代码逻辑。

Intent intent = new Intent(MainActivity.this,ReactNativeActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);

(4)  在ReactNativeActivity中去实现DefaultHardwareBackBtnHandler类,并且去覆写指定方法。onCreate方法中编写加载bundle文件代码及赋值一些设置信息。完整代码如下图所示。

public class ReactNativeActivity  extends Activity implements DefaultHardwareBackBtnHandler {private ReactRootView mReactRootView;private ReactInstanceManager mReactInstanceManager;protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);mReactRootView = new ReactRootView(this);mReactInstanceManager = ReactInstanceManager.builder()                .setApplication(getApplication())                .setBundleAssetName("index.android.bundle")                .setJSMainModuleName("index.android")                .addPackage(new MainReactPackage())                .setUseDeveloperSupport(BuildConfig.DEBUG)                .setInitialLifecycleState(LifecycleState.RESUMED)                .build();mReactRootView.startReactApplication(mReactInstanceManager, "ReactNativeProjectName", null);setContentView(mReactRootView);}@Overridepublic void invokeDefaultOnBackPressed() {super.onBackPressed();}@Overrideprotected void onPause() {super.onPause();        if (mReactInstanceManager != null) {mReactInstanceManager.onHostPause();}    }@Overrideprotected void onResume() {super.onResume()        if (mReactInstanceManager != null) {mReactInstanceManager.onHostResume(this, this);}    }@Overrideprotected void onDestroy() {super.onDestroy();        if (mReactInstanceManager != null) {mReactInstanceManager.onHostDestroy();}    }@Overridepublic void onBackPressed() {if (mReactInstanceManager != null) {mReactInstanceManager.onBackPressed();} else {super.onBackPressed();}    }@Overridepublic boolean onKeyUp(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_MENU &&mReactInstanceManager != null) {mReactInstanceManager.showDevOptionsDialog();            return true;}return super.onKeyUp(keyCode, event);}}

注意setBundleAssetName中index.android.bundle的全称,这需要和android工程目录下assets一致;setJSMainModuleName中index.android要与React Native侧的首个启动js页名称一致;startReactApplication中的第二个参数要与React Native侧的注册组件名称一致。


(5)  原生代码唤起React Native侧代码程序入口完全在(4)中完成,这时建立新工程时自动生成的MainActivity如下图所示完全没有用了,可以考虑删除掉。


(6)  终端到项目根目录下,执行react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/。目的是在android的工程目录下assets中生成index.android.bundle文件和index.android.bundle.meta文件。也就是说所有编写的React Native代码会打包进index.android.bundle文件中,供原生代码调用。


(7)  利用Android Studio运行该程序,点击,即可完成从原生到React Native页面的跳转,原生代码中成功嵌入了React Native的代码。


六、遇到的问题及解决办法

(1)  终端出现如下日志,bundle文件才算正式生成成功。



(2)  修改package.json文件和终端执行生成bundle文件命令,二选一,不要二者都操作一遍。(本例是采用终端键入react-native bundle --platform android--dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/的方式)


(3)  ReactNative页面是基于原生的,原生调用的是assets目录下打包好的bundle文件,所以利用命令打包之前js文件最好是准确无误可以跑通的,因为js每调试一次就得利用命令生成一次,目前在网上还没有查到更好的方式(欢迎留言指导)。目前尝试出的一个比较好的方式是:在注册文件AndroidManifest中设置启动页为React Native自动生成的MainActivity,这样启动时就能调试js代码。



1 0
原创粉丝点击