1. 程式人生 > >react-native爬坑(1)————給現有的Android專案整合

react-native爬坑(1)————給現有的Android專案整合

公司專案需要頻繁更新,因此考慮使用react-native給現有的Android專案進行功能補充。研究了2天,官網的資料坑太多,網上的部落格也不適用最新的版本,跑不起來,網上翻了n多篇資料,終於能夠執行起來,開心。現在將react-native整合的詳細跳坑步驟寫一下;

(1)前提:需要按照官網的步驟,搭建環境先,還沒搭建好的可以參考中文官網的,這個沒坑:https://reactnative.cn/docs/getting-started/ 

(2)使用的react-native版本:0.57.5

 

下面開始給我們的現有Android專案整合react-native

1、用Androidstudio開啟我們的Android專案,開啟下方的  Terminal  命令視窗,預設是我們的工程根目錄;使用yarn init命令建立package.json檔案,需要填寫響應的資訊,這裡我填了name後全部回車跳過,最後生成。

2、接下來需要安裝依賴和 node_modules,還是在根目錄下,輸入yarn add react-native,安裝 React 和 React Native 模組。等待幾分鐘後,可以看到完成的資訊。

往上滾動,看上面的資訊,會有warning提示的一句話:

意思就是react-native0.57.5版本需要依賴react的版本是16.6.1,官網說要保持一致性,既然警告了,就安裝對應的版本唄,接下來執行yarn add

[email protected],這次安裝的很快,提示完成的如下

要注意:我現在安裝的版本是0.57.5,如果以後更新了這個版本,對應的react版本應該也會更改,所以要記得要去看warning資訊,檢視對應的react版本。

看一下我們的package.json檔案,出現了剛才我們安裝的版本,如果版本號前有^符號,把它去掉,固定一下版本;

3、在build.gradle新增倉庫:這裡記得不要按官網新增的路徑,有坑。直接複製下面的就行了

allprojects {
    repositories {
        maven { url "https://maven.google.com" }
        jcenter()
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/node_modules/react-native/android"
        }
    }
}
    dependencies {
        compile 'com.facebook.react:react-native:+'
    }

4、建立js檔案,我直接用了官網的例子,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}>HelloWorld,終於爬出坑了!</Text>
      </View>
    );
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: "center"
  },
  hello: {
    fontSize: 20,
    textAlign: "center",
    margin: 10
  }
});

AppRegistry.registerComponent("MyReactNativeApp", () => HelloWorld);

5、建立MyReactActivity

public class MyReactActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler {
    private final int OVERLAY_PERMISSION_REQ_CODE = 1;  // 任寫一個值
    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

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

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")//繫結的是app/src/main/assets中的bundle檔案
                .setJSMainModulePath("index")//js檔名
                .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
    public boolean onKeyUp(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
            mReactInstanceManager.showDevOptionsDialog();
            return true;
        }
        return super.onKeyUp(keyCode, event);
    }


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

    @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
                }
            }
        }
    }
}
 <!-- 聯網許可權 -->
    <uses-permission android:name="android.permission.INTERNET" />
    <activity
            android:name=".MyReactActivity"
            android:label="@string/app_name"
            android:theme="@style/Theme.AppCompat.Light.NoActionBar">
        </activity>

如果需要訪問 DevSettingsActivity 介面(即開發者選單),則還需要在 AndroidManifest.xml 中宣告:

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

這樣就差不多了,在執行Android專案前,我們需要生成bundle檔案,也就是編譯js程式碼。

5、構建bundle檔案;這裡是我爬了最久的坑,官網和網上的資料都說要執行yarn start命令,但是我一直會卡在

就不動了。於是找了很久的資料,才發現其實不需要執行這個start命令,而是在package.json檔案中新增另外一句bundle-android命令;

"scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "bundle-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/"
  }

該命令有2個資料夾路徑,其實就是我們的assets資料夾(要保證專案的assets路徑和命令中的資料夾路徑一致,不然會報找no such file or directory),bundle檔案會在這個命令之後在assets檔案下生成,我們在app/src/main下建立assets資料夾,然後直接在Terminal視窗執行這個命令:yarn bundle-android

 

6、執行我們的Android專案到真機或模擬器。需要許可權,這裡點選允許。

點選跳轉到MyReactActivity頁面,發現報錯了。

是以為我們沒有新增ndk的支援,在build.gradle檔案中新增

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

然後編譯,重新執行到真機,成功了!

 

總結:雖然過程比較艱辛,但是現在總結看來其實也不難弄,要注意的是,如果修改了js檔案,要重新執行yarn bundle-android命令新的js程式碼才能生效。寫的感覺比較詳細了,接下來繼續踩其他坑。