React-Native移植-Android

簡介

參考鏈接:
Integrating with Existing Apps

由於公司業務需要,部分模塊需要將native代碼轉移到react-native,並且由於是已有項目,所以我這裏單獨把react-native移植到項目來,移植的過程中遇到了一些問題,這裏也記錄了下。

網上的一些教程資料都不是很全,而且一些關鍵的步驟說的都不是很詳細,這裏我們從零開始。

還有就是環境配置這裏不講了,都是很基礎的東西!

新建一個Android項目

這裏我們新建一個ReactNativeProject,初始化目錄結構如下:

引入React-Native

在你的app目錄下的build.gradle加入react-native依賴,我加入的是最新版本的0.20.1

compile 'com.facebook.react:react-native:0.20.1'

然後在AndroidManifest.xml加入訪問網絡權限,當然一般已經項目都有這個權限,如果有這一步可以忽略

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

爲了讓項目支持調試RN,需要在AndroidManifest.xml裏面加入RN的DevSettingsActivity,如下:

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

這樣真機晃動手機或者點擊Menu菜單就會打開相關的調試頁面,如圖下所示:

這裏部署完後,還有一個坑,就是React-Native對編譯版本和最小編譯版本都有要求,它需要app的build.gradle文件的compileSdkVersion爲23,minSdkVersion爲16,因爲我們項目要求最低版本爲15甚至更低,這裏需要在app的AndroidManifest.xml加入

<uses-sdk tools:overrideLibrary="com.facebook.react" />

加入基礎的Android原生代碼和JS代碼

我們新建一個MyReactActivity,完整代碼貼下

public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_my_react);

        mReactRootView = (ReactRootView) findViewById(R.id.react_root);

        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, "ReactNativeProject", null);

    }

    @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);
    }


}

因爲ReactRootView本身就是一個FrameLayout,我沒有按官網來直接new一個,而是直接把它放到佈局activity_my_react.xml裏面了,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.hhl.reactnativeproject.MyReactActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:gravity="center"
        android:text="我是本地控件TextView"
        android:textSize="20sp" />

    <com.facebook.react.ReactRootView
        android:id="@+id/react_root"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

這裏需要強調一下下,Activity裏面有兩個方法,setBundleAssetNamesetJSMainModuleName,其中setBundleAssetName間接調用了setJSBundleFile,而setJSBundleFile就是我們以後要講的熱修復的關鍵;而setJSMainModuleName設置的就是index.android.js的名字,這個可以更改目錄位置。

Android代碼加完了,開始加入JS代碼,這裏我們在項目根目錄下,也就是我們的ReactNativeProject目錄下加入index.android.js文件和package.json文件,index.android.js文件簡單代碼如下:

'use strict';

import React, {
  Text,
  View
} from 'react-native';

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

React.AppRegistry.registerComponent('ReactNativeProject', () => ReactNativeProject);

package.json代碼如下:

{
  "name": "ReactNativeProject",
  "version": "1.0.0",
  "description": "demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "hanhailong",
  "license": "ISC",
  "dependencies": {
    "react": "^0.14.8",
    "react-native": "^0.24.1"
  }
}

項目配置運行調試

ReactNativeProject目錄下執行如下命令

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

npm init命令可以不用執行,它如要用來生成package.json文件,前面我們已經創建過了,npm install –save react-native執行後會在目錄下面生成node_modules文件夾並添加react-native的npm依賴

首先啓動RN的npm本地服務:

$ npm start

啓動後如下:

npm啓動

在MainActivity裏面我們加入跳轉到MyReactActivity的代碼,

Intent intent = new Intent(MainActivity.this, MyReactActivity.class);
startActivity(intent);

項目結構圖

項目運行效果

最後我們運行項目,運行效果圖如下:

編譯可能遇到的問題

Caused by: java.lang.IllegalAccessError: tried to access method android.support.v4.net.ConnectivityManagerCompat.:(Lcom/facebook/react/bridge/ReactApplicationContext;)V from class com.facebook.react.modules.netinfo.NetInfoModule

我的項目的appcompat的版本是23.2.1,改成23.0.1就好了

compile 'com.android.support:appcompat-v7:23.0.1'

Demo下載

ReactNativeProject

下一節講解RN熱更新

下一節我們將講解RN的熱更新,敬請期待!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章