React-Native移植-Android

简介

参考链接:
Integrating with Existing Apps

由于公司业务需要,部分模块需要将native代码转移到react-native,并且由于是已有项目,所以我这里单独把react-native移植到项目来,移植的过程中遇到了一些问题,这里也记录了下。

网上的一些教程资料都不是很全,而且一些关键的步骤说的都不是很详细,这里我们从零开始。

还有就是环境配置这里不讲了,都是很基础的东西!

新建一个Android项目

这里我们新建一个ReactNativeProject,初始化目录结构如下:

React-Native移植-Android_第1张图片

引入React-Native

在你的app目录下的build.gradle加入react-native依赖,我加入的是最新版本的0.20.1

compile 'com.facebook.react:react-native:0.20.1'

然后在AndroidManifest.xml加入访问网络权限,当然一般已经项目都有这个权限,如果有这一步可以忽略


为了让项目支持调试RN,需要在AndroidManifest.xml里面加入RN的DevSettingsActivity,如下:


这样真机晃动手机或者点击Menu菜单就会打开相关的调试页面,如图下所示:

React-Native移植-Android_第2张图片

这里部署完后,还有一个坑,就是React-Native对编译版本和最小编译版本都有要求,它需要app的build.gradle文件的compileSdkVersion为23,minSdkVersion为16,因为我们项目要求最低版本为15甚至更低,这里需要在app的AndroidManifest.xml加入


加入基础的Android原生代码和JS代码

我们新建一个MyReactActivity,完整代码贴下

public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_react);

        mReactRootView = (ReactRootView) findViewById(R.id.react_root);

        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, "ReactNativeProject", null);

    }

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

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

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

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

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

    @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);
    }


}

因为ReactRootView本身就是一个FrameLayout,我没有按官网来直接new一个,而是直接把它放到布局activity_my_react.xml里面了,代码如下:




    

    


这里需要强调一下下,Activity里面有两个方法,setBundleAssetNamesetJSMainModuleName,其中setBundleAssetName间接调用了setJSBundleFile,而setJSBundleFile就是我们以后要讲的热修复的关键;而setJSMainModuleName设置的就是index.android.js的名字,这个可以更改目录位置。

Android代码加完了,开始加入JS代码,这里我们在项目根目录下,也就是我们的ReactNativeProject目录下加入index.android.js文件和package.json文件,index.android.js文件简单代码如下:

'use strict';

import React, {
  Text,
  View
} from 'react-native';

class ReactNativeProject extends React.Component {
  render() {
    return (
      
        Hello, World
        测试ReactNative
      
    )
  }
}
var styles = React.StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

React.AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);

package.json代码如下:

{
  "name": "ReactNativeProject",
  "version": "1.0.0",
  "description": "demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "hanhailong",
  "license": "ISC",
  "dependencies": {
    "react": "^0.14.8",
    "react-native": "^0.24.1"
  }
}

项目配置运行调试

ReactNativeProject目录下执行如下命令

$ npm init
$ npm install --save react-native
$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

npm init命令可以不用执行,它如要用来生成package.json文件,前面我们已经创建过了,npm install –save react-native执行后会在目录下面生成node_modules文件夹并添加react-native的npm依赖

首先启动RN的npm本地服务:

$ npm start

启动后如下:

React-Native移植-Android_第3张图片

在MainActivity里面我们加入跳转到MyReactActivity的代码,

Intent intent = new Intent(MainActivity.this, MyReactActivity.class);
startActivity(intent);

项目结构图

React-Native移植-Android_第4张图片

项目运行效果

最后我们运行项目,运行效果图如下:

React-Native移植-Android_第5张图片

编译可能遇到的问题

Caused by: java.lang.IllegalAccessError: tried to access method android.support.v4.net.ConnectivityManagerCompat.:(Lcom/facebook/react/bridge/ReactApplicationContext;)V from class com.facebook.react.modules.netinfo.NetInfoModule

我的项目的appcompat的版本是23.2.1,改成23.0.1就好了

compile 'com.android.support:appcompat-v7:23.0.1'

Demo下载

ReactNativeProject

下一节讲解RN热更新

下一节我们将讲解RN的热更新,敬请期待!!!

你可能感兴趣的:(Android大神之路)