ReactNative植入原生应用(windows)

ReactNative植入原生应用(windows)

当我们在开发android应用的时候,我们可能只是希望对现有应用中的某些部分用ReactNative进行替换,那么我们就需要在我们的项目中植入ReactNative.

首先我们需要满足如下两个条件:
1.一个已有的,基于gradle构建的Android应用。
2.Node.js。

添加ReactNative依赖

首先在我们的app的build.gradle文件中,添加ReactNative依赖:

    compile 'com.facebook.react:react-native:0.20.+'

或者通过如下步骤添加:

AndroidStudio中:File—>Project Structure->app->选择Dependencies->点击+号->选择Library dependency->搜索react-native->选择facebook的react-native的依赖包->点击确定按钮->完成

添加完成后需要在AndroidManifest.xml里增加Internet访问权限:

    <uses-permission android:name="android.permission.INTERNET" />

这个仅仅在调试模式从开发服务器加载JavaScript代码的时候用到,因此可以在构建发行包的时候将该权限去掉。

添加原生代码

添加完依赖之后,我们需要添加一些原生代码来启动ReactNative运行库以及让他渲染出东西。首先我们创建一个Activity和一个ReactRootView,然后在里面启动一个React应用并把它设置为Activity的主要内容视图。完整代码如下所示:

package com.hfga.zhangyi.myreact;

import android.app.Activity;
import android.os.Bundle;
import android.view.KeyEvent;

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;

/**
 * Created by ZhangYi on 2016/4/8.
 */
public class MyReactActivity extends Activity 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, "MyAwesomeApp", 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);
    }

}

添加JS代码到原生应用

在工程根目录下,运行如下代码:

    npm init

该命令会在根目录下创建一个package.json,运行之后会提示输入name,version等信息,如无特殊要求,可直接enter使用默认的即可。

注意:name只能是小写,不能包含大写。

接下来运行如下命令:

    npm install --save react-native

该命令会下载react-native所需要的文件,代码等。下载过程中需要梯子,但是在使用梯子下载发现也很容易出错,且速度较慢,我们可以直接下载完整的绿色纯净项目包并拷贝其中的node_modules文件夹到我们的项目根目录中。

注意:因为node_modules文件中层级过多,且有些js文件名字较长,在我们拷贝的过程中有可能出现有些文件不能拷贝,因此在建项目的时候项目所在路径最好不要太长。

拷贝完成后执行如下命令:

curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

但是在windows下提示没有curl这个命令,curl是利用URL语法在命令行方式下工作的开源文件传输工具。也就是是说该命令只是下载一个文件,因此我们可以在根目录下新建一个.flowconfig文件,并打开对应的地址:https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig,拷贝其中的所有内容到我们新建的.flowconfig文件中即可。

然后打开之前创建的package.json文件然后在scriptes自断下添加如下内容:

    "start": "node node_modules/react-native/local-cli/cli.js start"

注意:其中的test行很有可能在我们运行的时候导致错误,因此可以进行删除。

然后在根目录下新建一个index.android.js文件,并拷贝如下内容,或者可以在该文件中编写自己的页面:

'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('MyAwesomeApp', () => MyAwesomeApp);

该页面只是输出了一个hello world的TextView。

运行android应用

为了运行我们的应用,首先需要启动开发服务器,只需要在工程目录下运行如下代码:

    npm start

或者运行

    react-native start

但是在运行的时候有可能提示如下错误:

> myreact@1.0.0 start F:\MyReact
> node node_modules/react-native/local-cli/cli.js start

module.js:327
    throw err;
    ^

Error: Cannot find module 'number-is-nan'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (F:\MyReact\node_modules\react-native\node_modules\babel-preset-react-native\node_modules\babel-plugin-transform-es2015-modules-commonjs\node_modules\babel-types\node_modules\babel-traverse\node_modules\repeating\node_modules\is-finite\index.js:2:19)
    at Module._compile (module.js:409:26)
    at Module._extensions..js (module.js:416:10)
    at Object.require.extensions.(anonymous function) [as .js] (F:\MyReact\node_modules\react-native\node_modules\babel-register\lib\node.js:138:7)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)

这是因为module.js需要的的模块number—is-nan没有找到,我们需要安装对应的模块即可。使用如下命令进行安装:

    npm install --save number-is-nan

安装完成后再次运行react-native start命令,如果还有上述错误,按照提示的模块名称进行安装即可。

直到出现如下我们熟悉的界面:

┌────────────────────────────────────────────────────────── ──────────────────┐
 │  Running packager on port 8081.                                            │
 │                                                                            │
 │  Keep this packager running while developing on any JS projects. Feel      │
 │  free to close this tab and run your own packager instance if you          │
 │  prefer.                                                                   │
 │                                                                            │
 │  https://github.com/facebook/react-native                                  │
 │                                                                            │
 └────────────────────────────────────────────────────────── ──────────────────┘
Looking for JS files in
   F:\MyReact

[22:04:06] <START> Building Dependency Graph
[22:04:06] <START> Crawling File System
[Hot Module Replacement] Server listening on /hot

React packager ready.

[22:06:00] <END>   Crawling File System (114099ms)
[22:06:00] <START> Building in-memory fs for JavaScript
[22:06:07] <END>   Building in-memory fs for JavaScript (7531ms)
[22:06:07] <START> Building in-memory fs for Assets
[22:06:14] <END>   Building in-memory fs for Assets (7067ms)
[22:06:14] <START> Building Haste Map
[22:06:17] <START> Building (deprecated) Asset Map
[22:06:18] <END>   Building (deprecated) Asset Map (1114ms)
[22:06:19] <END>   Building Haste Map (4642ms)
[22:06:19] <END>   Building Dependency Graph (133363ms)

然后运行我们的Android应用,但是在运行之后跳转到我们的React页面,发现应用闪退,AndroidStudio提示如下错误:

java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.()' is inaccessible to class 'com.facebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in /data/app/package.name-2/base.apk)
    at com.facebook.react.modules.netinfo.NetInfoModule.(NetInfoModule.java:55)
    at com.facebook.react.shell.MainReactPackage.createNativeModules(MainReactPackage.java:62)
    at com.facebook.react.ReactInstanceManagerImpl.processPackage(ReactInstanceManagerImpl.java:751)
    at com.facebook.react.ReactInstanceManagerImpl.createReactContext(ReactInstanceManagerImpl.java:688)
    at com.facebook.react.ReactInstanceManagerImpl.access$600(ReactInstanceManagerImpl.java:84)

如果遇到该错误,需要检查build.gradle文件,将其中的

    com.android.support:appcompat-v7:23.2.1 

修改为:

    com.android.support:appcompat-v7:23.0.1

其他版本的appcompat-v7同理。

最终植入成功,界面显示hello world。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值