• RN与现有的原生app集成


    https://facebook.github.io/react-native/docs/integration-with-existing-apps.html

      RN可以很好地支持往一个原生的app上添加RN的组件。通过简单的步骤,我们可以添加RN基础的特征、组件等。后面以android为例。

    关键思想(概要)

    1. 设置RN的依赖和结构目录
    2. 用JS开发RN组件
    3. 添加一个ReactRootView到android app上,这会作为RN组件的容器
    4. 开启RN服务器和运行原生app
    5. 检查RN组件是否正常工作

    预备知识

      按照官方指引,设置好RN开发环境。

    1. 设置目录结构。把android项目“内容”复制到RN项目根目录下的android文件夹中(初始化的RN项目中就已经有这样一个文件夹了,里面有初始的android项目内容)
    2. 安装JS依赖。在RN项目创建一个package.json,内容如下(初始的RN项目也有这些内容了)
      {
        "name": "MyReactNativeApp",
        "version": "0.0.1",
        "private": true,
        "scripts": {
          "start": "node node_modules/react-native/local-cli/cli.js start"
        }
      }

      然后安装react和react-native依赖

      npm install --save react@16.0.0-beta.5 react-native

    把RN添加到app中

    配置maven仓库

      把RN依赖添加到android/app/build.gradle中(测试发现不能使用+,应该指定版本,将+替换为npm中对应的RN版本号,如package.json中 ^0.5,则将+替换为0.5):

    dependencies {
        ...
        compile "com.facebook.react:react-native:+" // From node_modules.
    }

      光光以上这么配置,gradle会找不到这个依赖,需要在android/build.gradle中配置一个仓库告诉gradle去哪里找依赖(确保添加到allproject这个块中,而且要在所有其他maven仓库之上。同时确保下面的url是正确的):

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

    配置权限

      往AndroidManifest.xml清单文件中加上:

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

      如果需要在原生app中打开开发者菜单,也需要在清单文件中加上(如果要发布则把下面这行去掉):

    <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

    代码集成

      在项目的根目录创建一个index.js,这是RN程序的入口点,往index.js中添加如下内容

    import React from 'react';
    import {AppRegistry, StyleSheet, Text, View} from 'react-native';
    
    class HelloWorld 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('MyReactNativeApp', () => HelloWorld);

    ReactRootView

      现在需要写一些原生代码来启动RN runtime和渲染界面。在activity中创建ReactRootView,并作为主内容显示:

    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")
                    .setJSMainModulePath("index")
                    .addPackage(new MainReactPackage())
                    .setUseDeveloperSupport(BuildConfig.DEBUG)
                    .setInitialLifecycleState(LifecycleState.RESUMED)
                    .build();
            mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
    
            setContentView(mReactRootView);
        }
    
        @Override
        public void invokeDefaultOnBackPressed() {
            super.onBackPressed();
        }
    }

      以上的ReactInstanceManager可以在多个activity和fragment之间共享。接着使RN与activity的生命周期同步(这是为了让JS代码能处理这些生命周期,如JS可以检测到用户按了后退):

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

      如果API大于23,需要配置开发模式下错误信息的显示权限,因为错误信息必须要显示在所有窗口之上。在activity的onCreate中添加如下代码:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (!Settings.canDrawOverlays(this)) {
            Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                                       Uri.parse("package:" + getPackageName()));
            startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE);
        }
    }

      接着需要重写activity的onActivityResult方法

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == OVERLAY_PERMISSION_REQ_CODE) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (!Settings.canDrawOverlays(this)) {
                    // SYSTEM_ALERT_WINDOW permission not granted...
                }
            }
        }
    }

      接着设置开发者菜单的弹出:  

    @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进行声明

    <activity
      android:name=".MyReactActivity"
      android:label="@string/app_name"
      android:theme="@style/Theme.AppCompat.Light.NoActionBar">
    </activity>

    运行

      到根目录下执行npm start来打包生成js bundle。然后直接构建app(如使用android studio)启动app看效果。

    实践

      通过android studio创建一个项目,项目目录指定为root/android/。

      项目地址:https://github.com/947133297/rn-ntegration-with-existing-apps

  • 相关阅读:
    进程上下文VS中断上下文
    字符串分割处理
    C++接收含有空格的字符串
    TLS分析
    位运算之bit_xor、bit_not、bit_and、bit_or
    GET和POST区别
    我的 HTTP/1.1 好慢啊!
    HTTP/2与HTTP/1的比较
    C++11新特性之一— auto 和 decltype 区别和联系
    C++ tuple元组的基本用法(总结)
  • 原文地址:https://www.cnblogs.com/hellohello/p/8310377.html
Copyright © 2020-2023  润新知