4、在已有的Android应用中使用React Native

这一篇记录的是如何在已有的Android应用中使用React Native,在官方的文档上也有介绍:http://reactnative.cn/docs/embedded-app-android.html#content,不过这里我还是想记录一下遇到的一些坑。一步一步来说吧:

创建Android应用

这里我直接用AndroidStudio在桌面上创建了一个应用,名称为ReactNativeApp

添加React Native支持

在创建好的Android应用的build.gradle中,加入React Native的库:compile 'com.facebook.react:react-native:0.17.+',如下图所示:
4、在已有的Android应用中使用React Native_第1张图片
在AndroidManifest.xml文件中,需要加入访问网络的权限,然后还要注册一个Activity,这个Activity是React Native用来调试应用内置的一个Activity(com.facebook.react.devsupport.DevSettingsActivity),如下图所示:

添加跟ReactNative相关的java代码,具体代码可以在上面的官方文档上找到,这里我直接把代码添加到MainActivity中了,如下代码所示:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.KeyEvent;
import android.widget.Toast;

import com.facebook.react.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;

public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    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, "helloworld", null);

        setContentView(mReactRootView);
    }

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

}
经过上面几个步骤,Android的代码基本上就配置好了,下面需要配置React Native相关的js代码。

添加node模块

在Windows的命令行下,进入我们第一步创建的android应用的根目录,然后依次执行下面几个命令:
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模块,这个命令执行的时间会比较长,需要耐心等待下;
第三个命令是用curl执行的,在Windows上需要先安装curl,下载地址见这里: http://pan.baidu.com/share/link?shareid=2123553377&uk=4278509670下载完成后直接解压到硬盘某个目录,然后在环境变量的path中加入curl文件的路径,就可以直接在命令行中用curl命令了,有个问题是,如果直接执行上面的curl命令,可能会报错,这里我在-o参数前面加了-k参数后才执行成功。

修改package.json文件并启动服务器

执行完上面的三个命令后,在android应用的根目录下打开package.json文件,即上面npm init生成的那个文件,然后修改成如下内容:
{
  "name": "helloworld",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node_modules/react-native/packager/packager.sh"
  },
  "dependencies": {
    "react-native": "^0.12.0"
  }
}
修改完毕后,需要在android应用的根目录下添加一个index.android.js文件,在Activity中就会加载这个js文件显示UI,在这里我们直接使用官方文档上提供的demo,内容如下:
'use strict';

var React = require('react-native');
var {
  Text,
  View
} = React;

class MyAwesomeApp extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.hello}>Hello, World</Text>
      </View>
    )
  }
}
var styles = React.StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

React.AppRegistry.registerComponent('helloworld', () => MyAwesomeApp);
这里需要注意一点,即上面代码的最后一行,React.AppRegistry.registerComponent('helloworld', () => MyAwesomeApp);这个函数的第一个参数应该跟我们java代码中的这一句:
mReactRootView.startReactApplication(mReactInstanceManager, "helloworld", null);
对应,如果不对应,加载就会出错。
到这里就可以启动服务器了,启动服务器的命令是:npm start,不过不知道为什么,我使用这个命令报错了,服务器并没有启动,所以我直接到node_modules/react-native/packager/目录下,执行了packager.sh命令,一样可以启动服务器,其实上面的package.json中配置的start,就是执行的packager.sh命令

打包运行Android应用

到这里,我们就可以编译apk文件了,用手机连接电脑,直接在AndroidStudio中运行即可。但是如果你的APP打开,可能会直接见到一片红,如下图所示:
4、在已有的Android应用中使用React Native_第2张图片
这时候需要配置下服务器的IP和端口,按手机的菜单键,然后选择Dev Settings选项,即出现开头我们在AndroidManifest.xml文件中配置的那个Activity,然后选择Debug sserver host & port for device那一项,在出来的对话框中,填写你的电脑的ip地址,默认端口是8081,注意:此时手机跟电脑应该在同一个局域网中。如下图所示:
4、在已有的Android应用中使用React Native_第3张图片
这些都配置好了,就可以按菜单键,然后选择Reload JS重新加载js文件了,如果没其他问题的话,应该是可以在Activity中看到效果的,下面是一张效果图:
4、在已有的Android应用中使用React Native_第4张图片
在使用小米手机的时候遇到一个坑:APP安装后,MIUI默认禁止了悬浮窗,导致我按菜单键时一直出不来React Native的调试对话框,这个对话框出不来就无法设置IP和端口,这里需要注意下,在应用权限管理中,应该允许我们的ReactNativeApp显示悬浮窗,如下图所示:
4、在已有的Android应用中使用React Native_第5张图片
到这里基本上就告一段落了,在已有的Android项目中使用React Native,虽然官方文档上有详细介绍,但这个过程中依然存在很多坑,今天记录下来,希望给看到这篇博文的朋友一些帮助。


你可能感兴趣的:(android,react,native,集成ReactNative)