美文网首页
Android项目集成ReactNative框架

Android项目集成ReactNative框架

作者: karlsu | 来源:发表于2016-07-19 17:15 被阅读1867次

    ReactNative推出也有一段日子了,相信很多开发者都想体验一下rn的强大功能,但是目前代码都是基于native代码的,如何加入ReactNative的代码呢?本文将从简单介绍下如何在已有工程的基础上,新增ReactNative模块。

    准备条件

    1.一个已有的、基于gradle构建的Android应用。
    2.Node.js,参见开始使用React Native来了解相关的设置操作。
    首先创建个Android工程,结构如下图所示:


    下面我们开始在这个原生android工程上进行改造,加入我们的ReactNative代码。

    在android/app/build.gradle文件中,添加React Native依赖:

    // From node_modules

    compile"com.facebook.react:react-native:+"
    

    然后在android/build.gradle文件中(注意跟上面的路径不同)加入本地React Native的maven目录(现在React Native的所有组件,无论JS还是Android的预编译包,都是通过npm分发的了):

    allprojects {
    repositories {
        ...
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/node_modules/react-native/android"
        }
    }
    ...
    }
    

    最后在你的AndroidManifest.xml里增加Internet访问权限:

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

    添加原生代码

    你需要添加一些原生代码来启动React Native运行库以及让它渲染出东西来。我们接下来创建一个Activity和一ReactRootView
    ,然后在里面启动一个React应用并把它设置为Activity的主要内容视图。

    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, "HelloRn", null);
        setContentView(mReactRootView);
    }}
    

    接下来,我们需要传递一些Activity的生命周期事件到ReactInstanceManager

    @Override
    protected void onPause() {
        super.onPause();
    
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause();
        }
    }
    
    @Override
    protected void onResume() {
        super.onResume();
    
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }
    

    我们还需要把Back按钮事件传递给React native:

    @Override
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }
    

    把JS代码添加到你的应用

    在你的工程根目录,运行以下代码:

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

    上面的代码会创建一个node模块,然后react-native作为npm依赖添加。现在打开新创建的package.json文件然后在scripts字段下添加如下内容:

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

    复制并粘贴下面的这段代码到你工程根目录下的index.android.js

     'use strict';
    import React, { Component } from 'react';
    import {
    AppRegistry,
    Text,
    StyleSheet,
    View,
    } from 'react-native';
    class HelloRn extends 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('HelloRn', () => HelloRn);
    

    运行应用

    为了运行应用,首先要启动开发服务器。只需要在你的工程目录下运行这段代码:
    $ npm start
    现在来构建和运行你的Android应用(譬如./gradlew installDebug
    )。一旦启动了React Native制作的Activity,它应该会从开发服务器加载代码并显示:

    661cbee9e9f91617aceab5e7a2fae49a.png

    可能遇到的问题:

    1. Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16 declared in library [com.facebook.react:react-native:0.29.2]


      在mainfest配置如下参数即可:


    2. java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so


      在两处添加配置:
      app#build.gradle

      defaultConfig {
       //...
       ndk {
           abiFilters "armeabi-v7a", "x86"
         }
       }
      

    gradle.properties
    android.useDeprecatedNdk=true

    3.报错信息如下:

    Loading dependency graph, done.
    error: bundling: UnableToResolveError: Unable to resolve module `react/lib/ReactDebugCurrentFrame` from `/Users/suwantao/AndroidStudioProjects/ReactNativeDemo/react_native/node_modules/react-native/Libraries/Renderer/src/renderers/shared/stack/reconciler/ReactCompositeComponent.js`: Module does not exist in the module map or in these directories:
      /Users/suwantao/AndroidStudioProjects/ReactNativeDemo/react_native/node_modules/react-native/node_modules/react/lib
    ,   /Users/suwantao/AndroidStudioProjects/ReactNativeDemo/react_native/node_modules/react/lib
    ,   /Users/suwantao/node_modules/react/lib
    
    This might be related to https://github.com/facebook/react-native/issues/4968
    To resolve try the following:
      1. Clear watchman watches: `watchman watch-del-all`.
      2. Delete the `node_modules` folder: `rm -rf node_modules && npm install`.
      3. Reset packager cache: `rm -fr $TMPDIR/react-*` or `npm start --reset-cache`.
        at UnableToResolveError (/Users/suwantao/AndroidStudioProjects/ReactNativeDemo/react_native/node_modules/react-native/packager/src/node-haste/DependencyGraph/ResolutionRequest.js:488:5)
        at p.catch.error (/Users/suwantao/AndroidStudioProjects/ReactNativeDemo/react_native/node_modules/react-native/packager/src/node-haste/DependencyGraph/ResolutionRequest.js:366:19)
        at process._tickCallback (internal/process/next_tick.js:103:7)
    Bundling `index.android.js`  84.3% (349/380), failed.
    
    Paste_Image.png

    解决方案:添加 react-native-material-design
    react-native-material-design依赖react-native-material-design-styles ,如果他的父类是个全局的模块,则不能被React Native's bundler打包。

    参考The development server returned response error code: 500 in react native

    执行npm install react-native-material-design 如果报错,

    Paste_Image.png

    根据提示,执行:npm install --save react@16.0.0-alpha.6
    安装成功之后再次执行npm install react-native-material-design即可。
    4.诡异的问题


    image.png

    解决方案:
    app/build.gradle (将 'com.android.support:appcompat-v7:xx.x.x' 改为 'com.android.support:appcompat-v7:23.0.1')

    5.undefined is not an object (evaluating ‘ReactInternals.ReactCurrentOwner’)

    IMG_1603.JPG

    解决方案:
    参考:https://github.com/facebook/react-native/issues/13874
    由于本地没安装yarm,无法直接调用 yarn add react@16.0.0-alpha.12在package.json手动填入"react": "16.0.0-alpha.12"也没解决问题。
    最后通过一个热心网友解决了该问题。方案如下:
    在项目根目录输入 npm install 然后 npm start ,问题完美解决。

    相关文章

      网友评论

          本文标题:Android项目集成ReactNative框架

          本文链接:https://www.haomeiwen.com/subject/oanmjttx.html