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/
声明:
- --platform : 平台(android/ios)
- --dev : 开发模式
- --entry-file : 条目文件
- --bundle-output : bundle文件生成的目录
- --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这个待补充吧。