ReactNative集成到原生項目

1、準備

1.1 建立 /ios目錄,並拷貝iOS原生項目的全部工程文件到該目錄下;

1.2 建立/android目錄,並拷貝Android原生項目的全部工程文件到該目錄下;

1.3 在根目錄下建立package.json文件,並添加以下內容:

{
  "name": "MyReactNativeApp",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start"
  }
}
複製代碼

1.4 根目錄下執行

yarn add react-native 或者npm i --save react-nativejava

1.5 安裝與當前react-native版本配套的react

能夠根據步驟四中輸出的警告信息查看,具體版本如:warning "react-native@0.57.6" has unmet peer dependency "react@16.6.1". 或者直接查看react-native的package.json中依賴react的版本package.jsonnode

yarn add react@16.6.1npm i --save react@16.6.1react

1.6 目錄

image

2、iOS集成

注意:此處默認本機cocoapods已安裝完成,未安裝的可先google對應教程安裝。參考:CocoaPods安裝方法android

2.1 在\ios根目錄下,終端執行pod init,生成Podfile文件;

2.2 編輯Podfile文件,可參考以下配置:

# Uncomment the next line to define a global platform for your project
 platform :ios, '9.0'
target 'MyReactNativeApp' do
  # Uncomment the next line if you're using Swift or would like to use dynamic frameworks
  # use_frameworks!

  # Pods for MyReactNativeApp

  # 'node_modules'目錄通常位於根目錄中
  # 可是若是你的結構不一樣,那你就要根據實際路徑修改下面的`:path`
  pod 'React', :path => '../node_modules/react-native', :subspecs => [
    'Core',
    'CxxBridge', # 若是RN版本 >= 0.47則加入此行
    'DevSupport', # 若是RN版本 >= 0.43,則須要加入此行才能開啓開發者菜單
    'RCTText',
    'RCTNetwork',
    'RCTWebSocket', # 調試功能須要此模塊
    'RCTAnimation', # FlatList和原生動畫功能須要此模塊
    # 在這裏繼續添加你所須要的其餘RN模塊
    'RCTActionSheet',
    'RCTBlob',
    'RCTGeolocation',
    'RCTImage',
    'RCTSettings',
    'RCTVibration',
    'RCTLinkingIOS',

  ]
  # 若是你的RN版本 >= 0.42.0,則加入下面這行
  pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga'

  # 若是RN版本 >= 0.45則加入下面三個第三方編譯依賴
  pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec'
  pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec'
  pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec'


  target 'MyReactNativeAppTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'MyReactNativeAppUITests' do
    inherit! :search_paths
    # Pods for testing
  end

end
複製代碼

2.3 執行pod install

2.4 工程根目錄下,建立一個組件index.js

import React, {Component} from 'react';
import {
	AppRegistry,
	StyleSheet,
	View,
	Text,
} from 'react-native';
class index extends Component {
	render() {
		return (
			<View style={styles.container}> <Text style={{fontSize:20}}>我是ReactNative !</Text> </View>
		);
	}
}
const styles = StyleSheet.create({
	container:{
		flex:1,
		backgroundColor:'green',
		justifyContent:'center',
		alignItems:'center'
	}
});

AppRegistry.registerComponent("MyReactNativeApp", () => index);
複製代碼

2.5 在原生項目中測試:

在須要跳轉的頁面(ViewController):ios

#import <React/RCTRootView.h>
#import <React/RCTBundleURLProvider.h>


- (void)pushToReactNativeVc {
	NSURL *jsBundleLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsBundleLocation moduleName:@"MyReactNativeApp" initialProperties:nil launchOptions:nil];
    
    UIViewController *vc = [[UIViewController alloc] init];
    vc.view = rootView;
    [self.navigationController pushViewController:vc animated:YES];
}
複製代碼

Tips:若是遇到 以下錯誤c++

image

打開Build Phases→Link Binary With Libraries點擊 + ,而後添加以下的.a靜態庫git

image

3、Android集成

3.1 配置Gradle

3.1.1 在app 中 build.gradle 文件中添加 React Native 依賴

dependencies {
    implementation 'com.android.support:appcompat-v7:23.0.1'
    ...
    implementation "com.facebook.react:react-native:+" // From node_modules
}
複製代碼

若是想要指定特定的 React Native 版本,能夠用具體的版本號替換 +,固然前提是你從 npm 裏下載的是這個版本。github

3.1.2 在項目的 build.gradle 文件中爲 React Native 添加一個 maven 依賴的入口,必須寫在 "allprojects" 代碼塊中:

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

確保依賴路徑的正確!以避免在 Android Studio 運行 Gradle 同步構建時拋出 「Failed to resolve: com.facebook.react:react-native:0.x.x" 異常。objective-c

3.2 配置權限

3.2.1 在 AndroidManifest.xml 清單文件中聲明網絡權限:

<uses-permission android:name="android.permission.INTERNET" />
複製代碼

3.2.2 若是須要訪問 DevSettingsActivity 界面(即開發者菜單),則還須要在 AndroidManifest.xml 中聲明:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
複製代碼

修改abiFilters

ndk {
       abiFilters "armeabi-v7a", "x86"
    }
複製代碼

緣由:
react-native生成aar的源碼在npm install命令下載生成的 '$項目根目錄'\node_modules\react-native\ReactAndroid中,aar中關於對於CPU限制在 '$項目根目錄'\node_modules\react-native\ReactAndroid\src\main\jni\Application.mk , 在這個文件中,咱們能夠到:npm

APP_BUILD_SCRIPT := Android.mk

APP_ABI := armeabi-v7a x86
APP_PLATFORM := android-16

APP_MK_DIR := $(dir $(lastword $(MAKEFILE_LIST)))

NDK_MODULE_PATH := $(APP_MK_DIR)$(HOST_DIRSEP)$(THIRD_PARTY_NDK_DIR)$(HOST_DIRSEP)$(REACT_COMMON_DIR)$(HOST_DIRSEP)$(APP_MK_DIR)first-party

APP_STL := gnustl_shared

# Make sure every shared lib includes a .note.gnu.build-id header
APP_CFLAGS := -Wall -Werror
APP_CPPFLAGS := -std=c++1y
APP_LDFLAGS := -Wl,--build-id

NDK_TOOLCHAIN_VERSION := 4.9
複製代碼

說明了CPU的類型限定在了armeabi-v7ax86

3.3 加載ReactNative視圖

方式1、繼承ReactActivity

  • App內須要使用react-native的頁面繼承ReactActivity
import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {

    /** * Returns the name of the main component registered from JavaScript. * This is used to schedule rendering of the component. */
    @Override
    protected String getMainComponentName() {
        return "MyReactNativeApp";
    }
}
複製代碼
  • Application中實現ReactApplication的方法,以下:
@Override
    public ReactNativeHost getReactNativeHost() {
        return reactNativeHost;
    }

private final ReactNativeHost reactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
        return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
        return Arrays.<ReactPackage>asList(
                new MainReactPackage()
        );
    }
    @Override
    protected String getJSMainModuleName(){
        return "index";
    }
};
複製代碼

方式2、在佈局中加入ReactRootView,經過 ReactInstanceManager加載管理JS

  • 一、配置權限以便開發中的紅屏錯誤能正確顯示

    若是你的應用會運行在 Android 6.0(API level 23)或更高版本,請確保你在開發版本中有打開懸浮窗(overlay)權限。你能夠在代碼中使用Settings.canDrawOverlays(this);來檢查。之因此須要這一權限,是由於咱們會把開發中的報錯顯示在懸浮窗中(僅在開發階段須要)。在 Android 6.0(API level 23)中用戶須要手動贊成受權。具體請求受權的作法是在onCreate()中添加以下代碼。其中OVERLAY_PERMISSION_REQ_CODE是用於回傳受權結果的字段。

private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // 任寫一個值

...

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);
    }
}
複製代碼

重寫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
            }
        }
    }
}
複製代碼
  • 二、接下來添加一些原生代碼來啓動 React Native 的運行時環境並讓它開始渲染。首先須要在一個Activity中建立一個ReactRootView對象,而後在這個對象之中啓動 React Native 應用,並將它設爲界面的主視圖。

若是你想在安卓 5.0 如下的系統上運行,請用 com.android.support:appcompat 包中的 AppCompatActivity 代替 Activity

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();
        // 注意這裏的MyReactNativeApp必須對應「index.js」中的
        // 「AppRegistry.registerComponent()」的第一個參數
       mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
        setContentView(mReactRootView);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }
    
    
    @Override
	public void onBackPressed() {
	    if (mReactInstanceManager != null) {
	        mReactInstanceManager.onBackPressed();
	    } else {
	        super.onBackPressed();
	    }
	}
}
複製代碼
  • 三、生命週期方法
@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);
    }
    if (mReactRootView != null) {
        mReactRootView.unmountReactApplication();
    }
}
複製代碼
  • 四、彈出RN的開發者菜單
@Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }
複製代碼

3.4 Android相關報錯處理

  • 一、so庫衝突
    image

處理:在app下的build.gride中添加以下設置

packagingOptions {
        pickFirst 'lib/x86/libgnustl_shared.so'
        pickFirst 'lib/armeabi-v7a/libgnustl_shared.so'
    }

複製代碼
相關文章
相關標籤/搜索