React-Native集成到现有的安卓项目中(坑死了)

React-Native集成到现有的安卓项目中

RN集成到ios的参见上一篇:https://github.com/ZhangMingZhao1/MingZhao-s-blog/issues/1

毕竟要做跨端,ios调研完了安卓还要再去跑通一下,弄下来感觉安卓比ios更坑一点。RN现在对版本的依赖太固定了,网上问题的教程也太少,版本不一样就不适用了。

1.

按照官网配置相关环境,后面的项目教程就不要跟着官网了,对新手不友好,适合会点原生的开发者,https://reactnative.cn/docs/getting-started/,
安装Android Studio,第一次打开会下载相关的SDK,按照官网教程来,还有JDK,配置环境变量。

用AS创建一个empty activity的项目,

2.

在Android工程中 打开Terminal窗口,npm init,npm install –save react react-native,这样默认下载的最新版,如果出现rn需要哪个版本react支持就install @xx.xx版本的。

就在版本这里卡了很久,我这里之前安装的ios的版本

  "dependencies": {
    "react": "16.0.0",
    "react-native": "0.51.0"
  }

到后面在安卓里增加activity的时候发现和教程的不一样了,AS提示我要重写函数,这个后面说。
所以我现在成功的版本是:

"react": "^16.6.3",
"react-native": "^0.57.7"

3.

在项目的根目录创建.flowconfig文件,该文件的内容可以从Facebook 的GitHub上下载, 查看这里, 将其内容copy进去即可;

4.

接下来在我们项目的根目录下的package.json文件中的scripts节点下添加改句:
"start": "node node_modules/react-native/local-cli/cli.js start"

在我们的项目根目录下添加index.js文件(老rn版本叫index.android.js),该文件即是我们的RN界面,然后在该文件中添加我们React Native界面的代码,例如简单的HelloWorld:
代码如下:

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

export default class App extends Component {
  render() {    return ( <Text>Hello world!</Text>);
  }}
AppRegistry.registerComponent('application', () => App);

5.

在android两个build.gradle里添加

dependencies {
    implementation 'com.android.support:appcompat-v7:26.1.0'(每个人的版本这里可能不一样)
    implementation 'com.facebook.react:react-native:+'
}
allprojects {
    repositories {
        google()
        jcenter()
        maven {
            url "$rootDir/node_modules/react-native/android"
        }
    }
}

6.

添加NDK支持,如果不添加这句话的话,可能会造成关于32位和64位SO库混合引入Crash:
i).在App 的build.gradle中的defaultConfig节点下添加如下语句:

ndk {
   abiFilters "armeabi-v7a", "x86"
}
即:
defaultConfig {
        applicationId "com.example.lance.myapplication"
        minSdkVersion 23
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        ndk {
            abiFilters "armeabi-v7a", "x86"
        }
    }

ii).然后在我们project下的gradle.properties文件中的末尾添加如下语句:
android.useDeprecatedNdk=true

iii).在App的build.gradle文件的android节点下添加:
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:1.3.9'
}

7.

完成以上步骤后,React Native就算集成到我们现有的Android项目中,接下来我们用Activity来展示我们的RN:

新版本中的ReactNative只需要自定义一个Activity,并将其集成ReactActivity,实现getMainComponentName()方法,在该方法中返回一开始我们注册的ReactNative的名称即可(即跟我们的index.js中的AppRegistry中的第一个参数相同),在ReactActivity中,已经帮我们实现了ReactRoot与ReactInstanceManager的配置,在之前的版本中,ReactRoot与ReactInstanceManager需要我们自己去写:
完成上面后,我们在android里main里新增一个activity:

package com.example.zhangmingzhao.rnandroid;

import javax.annotation.Nullable;

import com.facebook.react.ReactActivity;

public class MyReactActivity extends ReactActivity {
    @Nullable
    @Override
    protected String getMainComponentName() {        return "application";   //application即注册ReactNative时的名称;
    }
}

这里就是我上面说的遇到的版本的坑,我之前装的ios的版本的rn的时候,重写getMainComponentName后AS还报错提示我要重写一些其他方法,可能就是版本的问题。

8.

接下来创建一个MyApplication,并初始化一个ReactNativeHost,该MyApplication继承Application并实现ReactApplication,在源码loadApp方法时,会将当前的Activity的Application强制转换成ReactApplication:


package com.example.zhangmingzhao.rnandroid;

import android.app.Application;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;
import com.facebook.soloader.SoLoader;

import java.util.Arrays;
import java.util.List;

public class MyApplication extends Application implements ReactApplication {

    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
        public ReactNativeHost getReactNativeHost() {
            return reactNativeHost;
        }
        @Override
        public void onCreate() {
            super.onCreate();
            SoLoader.init(this,false);
        }
}

注意有的包option + 回车会提示多个,注意引对。
(这里写的getUseDeveloperSupport好像就是我上部低版本rn下要提示额外重写的方法?)

9.

在原生中加一个按钮,在 MainActivity 添加一个按钮跳转到 MyReactActivity,首先在 app/src/main/res/layout 下的 activity_main.xml 添加一个按钮元素

<Button
	android:id="@+id/btn"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="点击跳转到RN界面"/>

在 MainActivity 里添加点击跳转事件

package com.example.zhangmingzhao.rnandroid;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 点击按钮跳转到 react-native 页面
        findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this,MyReactActivity.class));
            }
        });
    }
}

10.

最后在 app/src/main/AndroidManifest.xml 文件中,添加一些权限,以及声明MainApplication 跟 MyReactActivity

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.zhangmingzhao.rnandroid">

    <uses-permission android:name="android.permission.INTERNET"/>   <!-- 网络权限 -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <!-- 弹框权限 -->
    <uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/> <!-- 窗体覆盖权限 -->
    <!-- 声明MainApplication -->
    <application
        android:name=".MyApplication"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 声明MyReactActivity -->
        <activity
            android:name=".MyReactActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme">
        </activity>
        <!-- 声明可以通过晃动手机或者点击Menu菜单打开相关的调试页面 -->
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
    </application>
</manifest>

这种方法下的必须要打包:
我们手动的在app/src/main/目录中添加一个assets目录, 并在该目录下添加一个index.android.bundle文件, 然后手动在该bundle文件中添加内容, 执行以下命令:

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --assets-dest app/src/main/res/

声明:

  1. --platform : 平台(android/ios)
  2. --dev : 开发模式
  3. --entry-file : 条目文件
  4. --bundle-output : bundle文件生成的目录
  5. --assets-dest : 资源文件生成的目录

ios的npm start启动,安卓模拟器也没识别到,如果是dev模式的话还要另需配置,待我补充,所以总体安卓比ios还是坑多了。

12.

打包后就可以在AS中运行了。注意每次改动AS的配置,都要重新点下Sync
在这里插入图片描述

第一次创建,clone安卓项目也要Sync,还要下载一些东西,用公司内网是真的慢,我自己开的热点。。

13

demo链接:
https://github.com/ZhangMingZhao1/react-native-pratice/tree/master/RNAndroid

总体安卓还是比IOS坑一些,安卓集成RN这个待补充吧。

posted @ 2018-11-30 16:11  Lawliet__zmz  阅读(693)  评论(0编辑  收藏  举报