React Native 十三:植入原生应用

前端之家收集整理的这篇文章主要介绍了React Native 十三:植入原生应用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
由于React并没有假设你其余部分的技术栈—它通常只作为MVC模型中的V存在—它也很容易嵌入到一个并非由React Native开发的应用中。
一、需求
1.一个已有的、基于gradle构建的Android应用;
2.Node.js;
二、准备你的App
1.使用Android Studio创建一个项目,在你的App里的build.gradle文件中,添加React Native依赖:
compile 'com.facebook.react:react-native:0.20.+'
2.在你的AndroidManifest.xml里,增加Internet访问权限;
这个仅仅在调试模式从服务器加载JavaScript代码的时候用到,你可以在构建发行包的时候把这条去掉;
<uses-permission android:name="android.permission.INTERNET" />
三、添加原生代码
MainActivity.java文件
package com.example.pengcx.reactnativetest;

import android.support.v7.app.AppCompatActivity;
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;

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

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        //创建一个ReactRootView,把它设置成Activity的主视图
        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();
    }

    //传递一些Activity的生命周期事件到ReactInstanceManager,这是的JavaScript代码可以控制当前用户按下返回按钮的时候作何处理(譬如控制导航切换等等)。如果JavaScript端不处理相应的事件,你的invokeDefaultOnBackPressed方法会被调用。默认情况,这会直接结束你的Activity。
    @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();
        }
    }

    //我们需要改动一下开发者菜单。默认情况下,任何开发者菜单都可以通过摇晃或者设备类触发,不过这对模拟器不是很有用。所以我们让它在按下Menu键的时候可以显示
    @Override
    public boolean onKeyUp(int keyCode,KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode,event);
    }
}
到此为止,你的Activity已经可以启动运行一些JavaScrip代码
四、把JS代码添加到你的应用
在你的工程根目录,运行以下代码
pengcx@pengcx-Ubuntu:~/AndroidStudioProjects/ReactNativeTest$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items,and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (ReactNativeTest) node_modules
Sorry,node_modules is a blacklisted name.
name: (ReactNativeTest) react_native
version: (1.0.0)
description: reactnative.cn
entry point: (index.js)
test command: make test
git repository:
keywords:
author:
license: (ISC)
About to write to /home/pengcx/AndroidStudioProjects/ReactNativeTest/package.json:

{
  "name": "react_native","version": "1.0.0","description": "reactnative.cn","main": "index.js","scripts": {
    "test": "make test"
  },"author": "","license": "ISC"
}

Is this ok? (yes) yes

pengcx@pengcx-Ubuntu:~/AndroidStudioProjects/ReactNativeTest$ npm install --save react-native
npm WARN package.json react_native@1.0.0 No repository field.
npm WARN package.json react_native@1.0.0 No README data
npm WARN peerDependencies The peer dependency react@^0.14.5 included from react-native will no
npm WARN peerDependencies longer be automatically installed to fulfill the peerDependency
npm WARN peerDependencies in npm 3+. Your application will need to depend on it explicitly.

> bufferutil@1.2.1 install /home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/bufferutil
> node-gyp rebuild

make:进入目录'/home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/bufferutil/build'
  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
  SOLINK_MODULE(target) Release/obj.target/bufferutil.node
  COPY Release/bufferutil.node
make:离开目录“/home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/bufferutil/build”
npm WARN optional dep Failed,continuing fsevents@1.0.12

> utf-8-validate@1.2.1 install /home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/utf-8-validate
> node-gyp rebuild

make:进入目录'/home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/utf-8-validate/build'
  CXX(target) Release/obj.target/validation/src/validation.o
  SOLINK_MODULE(target) Release/obj.target/validation.node
  COPY Release/validation.node
make:离开目录“/home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/ws/node_modules/utf-8-validate/build”

> spawn-sync@1.0.15 postinstall /home/pengcx/AndroidStudioProjects/ReactNativeTest/node_modules/react-native/node_modules/yeoman-generator/node_modules/cross-spawn/node_modules/spawn-sync
> node postinstall

react@0.14.8 node_modules/react
├── fbjs@0.6.1 (whatwg-fetch@0.9.0,ua-parser-js@0.7.10,loose-envify@1.1.0,promise@7.1.1,core-js@1.2.6)
└── envify@3.4.0 (through@2.3.8,jstransform@10.1.0)

react-native@0.25.1 node_modules/react-native
├── regenerator-runtime@0.9.5
├── react-clone-referenced-element@1.0.1
├── absolute-path@0.0.0
├── progress@1.1.8
├── stacktrace-parser@0.1.3
├── base64-js@0.0.8
├── graceful-fs@4.1.4
├── event-target-shim@1.1.1
├── wordwrap@1.0.0
├── react-timer-mixin@0.13.3
├── immutable@3.7.6
├── semver@5.1.0
├── image-size@0.3.5
├── opn@3.0.3 (object-assign@4.1.0)
├── bser@1.0.2 (node-int64@0.4.0)
├── json-stable-stringify@1.0.1 (jsonify@0.0.0)
├── debug@2.2.0 (ms@0.7.1)
├── temp@0.8.3 (os-tmpdir@1.0.1,rimraf@2.2.8)
├── chalk@1.1.3 (escape-string-regexp@1.0.5,supports-color@2.0.0,ansi-styles@2.2.1,strip-ansi@3.0.1,has-ansi@2.0.0)
├── source-map@0.4.4 (amdefine@1.0.0)
├── mkdirp@0.5.1 (minimist@0.0.8)
├── rebound@0.0.13
├── optimist@0.6.1 (wordwrap@0.0.3,minimist@0.0.10)
├── worker-farm@1.3.1 (xtend@4.0.1,errno@0.1.4)
├── promise@7.1.1 (asap@2.0.3)
├── node-haste@2.9.6 (throat@2.0.2,denodeify@1.2.1)
├── sane@1.3.4 (fb-watchman@1.9.0,watch@0.10.0,minimist@1.2.0,exec-sh@0.2.0,minimatch@0.2.14,walker@1.0.7)
├── yargs@3.32.0 (y18n@3.2.1,camelcase@2.1.1,decamelize@1.2.0,window-size@0.1.4,cliui@3.2.0,string-width@1.0.1,os-locale@1.4.0)
├── node-fetch@1.5.2 (is-stream@1.1.0,encoding@0.1.12)
├── art@0.10.1
├── json5@0.4.0
├── uglify-js@2.6.2 (async@0.2.10,uglify-to-browserify@1.0.2,source-map@0.5.6,yargs@3.10.0)
├── connect@2.30.2 (cookie@0.1.3,utils-merge@1.0.0,cookie-signature@1.0.6,pause@0.1.0,on-headers@1.0.1,fresh@0.3.0,parseurl@1.3.1,response-time@2.3.1,vhost@3.0.2,basic-auth-connect@1.0.0,bytes@2.1.0,cookie-parser@1.3.5,content-type@1.0.2,depd@1.0.1,qs@4.0.0,method-override@2.3.5,connect-timeout@1.6.2,serve-favicon@2.3.0,http-errors@1.3.1,morgan@1.6.1,express-session@1.11.3,type-is@1.6.12,finalhandler@0.4.0,multiparty@3.3.2,serve-static@1.10.2,csurf@1.8.3,errorhandler@1.4.3,compression@1.5.2,body-parser@1.13.3,serve-index@1.7.3)
├── jstransform@11.0.3 (object-assign@2.1.1,base62@1.1.1,esprima-fb@15001.1.0-dev-harmony-fb,commoner@0.10.4)
├── module-deps@3.9.1 (browser-resolve@1.11.1,through2@1.1.1,inherits@2.0.1,defined@1.0.0,xtend@4.0.1,duplexer2@0.0.2,parents@1.0.1,concat-stream@1.4.10,readable-stream@1.1.14,subarg@1.0.0,JSONStream@1.1.1,stream-combiner2@1.0.2,resolve@1.1.7,detective@4.3.1)
├── babel-plugin-external-helpers@6.8.0 (babel-runtime@6.6.1)
├── babel-register@6.8.0 (path-exists@1.0.0,home-or-tmp@1.0.0,source-map-support@0.2.10,babel-runtime@6.6.1)
├── babel-polyfill@6.8.0 (babel-regenerator-runtime@6.5.0,babel-runtime@6.6.1)
├── babel-types@6.8.1 (to-fast-properties@1.0.2,esutils@2.0.2,babel-traverse@6.8.0,babel-runtime@6.6.1)
├── babel-core@6.8.0 (slash@1.0.0,path-exists@1.0.0,shebang-regex@1.0.0,babel-template@6.8.0,path-is-absolute@1.0.0,babel-messages@6.8.0,babel-helpers@6.8.0,private@0.1.6,convert-source-map@1.2.0,babel-code-frame@6.8.0,minimatch@2.0.10,babel-generator@6.8.0,babel-runtime@6.6.1)
├── babylon@6.8.0 (babel-runtime@6.6.1)
├── lodash@3.10.1
├── joi@6.10.1 (topo@1.1.0,isemail@1.2.0,hoek@2.16.3,moment@2.13.0)
├── fbjs@0.7.2 (ua-parser-js@0.7.10,isomorphic-fetch@2.2.1,core-js@1.2.6)
├── babel-preset-react-native@1.7.0 (babel-plugin-transform-es2015-template-literals@6.8.0,babel-plugin-transform-flow-strip-types@6.8.0,babel-plugin-transform-es2015-for-of@6.8.0,babel-plugin-check-es2015-constants@6.8.0,babel-plugin-transform-es2015-destructuring@6.8.0,babel-plugin-transform-class-properties@6.8.0,babel-plugin-transform-es2015-arrow-functions@6.8.0,babel-plugin-Syntax-jsx@6.8.0,babel-plugin-Syntax-flow@6.8.0,babel-plugin-transform-es2015-spread@6.8.0,babel-plugin-Syntax-class-properties@6.8.0,babel-plugin-Syntax-async-functions@6.8.0,babel-plugin-transform-react-display-name@6.8.0,babel-plugin-transform-es2015-shorthand-properties@6.8.0,babel-plugin-transform-object-assign@6.8.0,babel-plugin-transform-es2015-function-name@6.8.0,babel-plugin-transform-object-rest-spread@6.8.0,babel-plugin-transform-es2015-modules-commonjs@6.8.0,babel-plugin-transform-es2015-computed-properties@6.8.0,babel-plugin-transform-react-jsx@6.8.0,babel-plugin-transform-es2015-block-scoping@6.8.0,babel-plugin-transform-es2015-parameters@6.8.0,babel-plugin-transform-es2015-classes@6.8.0,babel-plugin-Syntax-trailing-function-commas@6.8.0,babel-plugin-transform-regenerator@6.8.0,babel-plugin-react-transform@2.0.2)
├── react-transform-hmr@1.0.4 (global@4.3.0,react-proxy@1.1.8)
├── yeoman-environment@1.6.1 (escape-string-regexp@1.0.5,log-symbols@1.0.2,text-table@0.2.0,untildify@2.1.0,diff@2.2.2,globby@4.0.0,mem-fs@1.1.3,inquirer@1.0.2,grouped-queue@0.3.2,lodash@4.12.0)
├── core-js@2.4.0
├── fbjs-scripts@0.4.0 (object-assign@4.1.0,through2@2.0.1,gulp-util@3.0.7,core-js@1.2.6,babel@5.8.38)
├── ws@0.8.1 (options@0.0.6,ultron@1.0.2,bufferutil@1.2.1,utf-8-validate@1.2.1)
└── yeoman-generator@0.20.3 (detect-conflict@1.0.0,read-chunk@1.0.1,yeoman-welcome@1.0.1,async@1.5.2,mime@1.3.4,user-home@2.0.0,xdg-basedir@2.0.0,class-extend@0.1.2,dargs@4.1.0,istextorbinary@1.0.2,nopt@3.0.6,run-async@0.1.0,shelljs@0.5.3,yeoman-assert@2.2.1,cli-table@0.3.1,glob@5.0.15,findup-sync@0.2.1,rimraf@2.5.2,mem-fs-editor@2.2.0,underscore.string@3.3.4,sinon@1.17.4,dateformat@1.0.12,pretty-bytes@2.0.1,github-username@2.1.0,html-wiring@1.2.0,download@4.4.3,inquirer@0.8.5,gruntfile-editor@1.2.0,cross-spawn@2.2.3)

pengcx@pengcx-Ubuntu:~/AndroidStudioProjects/ReactNativeTest$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2654  100  2654    0     0   1522      0  0:00:01  0:00:01 --:--:--  1521
上面的代码会创建一个node模块,然后react-native作为npm依赖添加。现在打开新创建的package.json文件然后在scripts字段添加如下内容
"start": "node node_modules/react-native/local-cli/cli.js start"
复制并粘贴下面这段代码到你的工程根目录下面的index.android.js—这是一个简单的React Native应用:
android.android.js文件
'use strict';
var React = require('react');
var ReactNative = require('react-native');
var {
  Text,View,StyleSheet,AppRegistry
} = ReactNative;

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

AppRegistry.registerComponent('MyAwesomeApp',() => MyAwesomeApp);
五、运行你的应用
为了运行你的应用,首先要启动开发服务器。只需要在你的工程目录运行这段代码
pengcx@pengcx-Ubuntu:~/AndroidStudioProjects/ReactNativeTest$ npm 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
   /home/pengcx/AndroidStudioProjects/ReactNativeTest

[02:17:41] <START> Building Dependency Graph
[02:17:57] <START> Crawling File System
[Hot Module Replacement] Server listening on /hot

React packager ready.
六、应用程序运行如下:
现在来构建和运行你的Android应用(譬如./gradlew installDebug)。一旦启动了React Native制作的Activity,它应该会从开发服务器加载代码显示

提示1:在完成上面的操作步骤之后,启动程序获取JS代码的时候,程序会崩溃,报错如下:
05-12 02:52:21.440 3992-4020/com.example.pengcx.reactnativetest E/libEGL: cache file Failed CRC check
05-12 02:52:21.502 3992-4019/com.example.pengcx.reactnativetest E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
Process: com.example.pengcx.reactnativetest,PID: 3992
java.lang.RuntimeException: An error occured while executing doInBackground()
at android.os.AsyncTask$3.done(AsyncTask.java:300)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
at java.util.concurrent.FutureTask.run(FutureTask.java:242)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)
Caused by: java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.<init>()' is inaccessible to class 'com.facebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in /data/app/com.example.pengcx.reactnativetest-1/base.apk)
at com.facebook.react.modules.netinfo.NetInfoModule.<init>(NetInfoModule.java:55)
at com.facebook.react.shell.MainReactPackage.createNativeModules(MainReactPackage.java:67)
at com.facebook.react.ReactInstanceManagerImpl.processPackage(ReactInstanceManagerImpl.java:793)
at com.facebook.react.ReactInstanceManagerImpl.createReactContext(ReactInstanceManagerImpl.java:730)
at com.facebook.react.ReactInstanceManagerImpl.access$600(ReactInstanceManagerImpl.java:91)
at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:184)
at com.facebook.react.ReactInstanceManagerImpl$ReactContextInitAsyncTask.doInBackground(ReactInstanceManagerImpl.java:169)
at android.os.AsyncTask$2.call(AsyncTask.java:288)
at java.util.concurrent.FutureTask.run(FutureTask.java:237)
处理:该问题应该是引用的react的版本问题,而且目前Maven库中没有最新版本的React Native版本,引用项目根目录下的最新版本:
修改app下的build.gradle文件
compile 'com.android.support:appcompat-v7:23.0.1'
compile 'com.facebook.react:react-native:+'

修改项目根目录下的build.gradle文件
allprojects {
repositories {
mavenLocal()
jcenter()
maven {
// All of React Native (JS,Obj-C sources,Android binaries) is installed from npm
url "$projectDir/node_modules/react-native/android"
}
}
}

猜你在找的React相关文章