这里主要是记录下自己在原有Android工程的情况下接入RN的一些经验。首先是感谢网上大牛的分享,我也是查阅了很多资料,阅读了很多的网站,才最终解决。当解决的那一刻,就暗自下决心要把自己走过的坑分享出来,让后面的少走弯路。
首先是电脑最基本的RN环境是搭建好的。你初始化一个Rn项目后,然后用AS引入Rn项目中android文件夹的工程可正常运行,如果这步还未完成,可以去https://reactnative.cn React Native 中文网去搭建环境。
下面就开始讲重点。
React Native 中文网 也提到了将Android已有工程集成到RN项目中,但是这种方法有弊端。官网的做法是将已有项目cory到RN项目中。这样做的缺点是Android代码 和 Rn代码如何管理。我们理想的状态是Android是一个git仓库,IOS也是一个Git仓库,RN代码也是额外的一个仓库。代码互相隔离开来。
1. 初始化一个RN项目
react-native init AwesomeProject ,当然你也可以指定RN的版本。react-native init AwesomeProject --version 0.59.9。在这里希望是指定版本,不指定版本默认情况下使用最新的版本,如果你是简单的练习一下可以用最新版本。但是如果是进行产品开发,最好是比新版本低几个版本,因为新版本一般的问题会很多很多。
2. copy package.json 文件到Android项目的根目录下。
这是正在开发中的一个package.json 文件,里面有版本信息和各种引用的库。如果是新初始化的项目,就没有这么依赖信息。
放置package.json 的地方如下。然后在AS 的termianl 中输入命令行:npm install
命令执行后,你可能会在最后看到 npm audit fix 这句话。如果你是想指定版本的RN,无需管它。这句话的意思是会自动将一些低版本的升级到新版本。这里必须要注意RN项目中package.json 中的版本号,也必须与Android项目中的一致。如何查看呢,你会在Android项目根目录下找到ode_modules ,然后继续寻找react-native/android。看到版本是一致的,说明这步完成。
3.Android项目Rn的引入。
3.1整个工程目录下的build.gradle 添加
allprojects {
repositories {
maven {url "$rootDir/node_modules/react-native/android"}
google()
jcenter()
}
}
这里主要是留意引入路径,你会发现网上也有人说$rootDir/../node_modules 大可不必疑惑,这种写法是因为androd项目是在RN项目里的。你可以查看官网初始化生成的RN项目,看看里面android的引用路径。大家在搭建的时候,多看一下自己初始化RN项目里的android代码。这样对你是有一些参考意义,可以明显的告知你该如何写。
3.2app里的build.gradle 添加,注意版本号要一致。
dependencies {
.....
implementation 'com.facebook.react:react-native:0.59.9'
....
}
3.3 application 要
public class AppApplication extends Application implements ReactApplication {
private static AppApplication instance;
@Override
public void onCreate() {
super.onCreate();
instance = this;
SoLoader.init(this, false);
}
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
public List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage()
);
}
};
/**
* 获取Application实例
*/
public static AppApplication getInstance() {
return instance;
}
@Override
public ReactNativeHost getReactNativeHost() {
return mReactNativeHost;
}
}
3.4 新增一个页面去承载Rn页面
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private final int OVERLAY_PERMISSION_REQ_CODE = 1; // 任写一个值
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setCurrentActivity(this)
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
.addPackages(getPackages())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意这里的MyReactNativeApp必须对应“index.js”中的
// “AppRegistry.registerComponent()”的第一个参数
mReactRootView.startReactApplication(mReactInstanceManager, "flapp", null);
setContentView(mReactRootView);
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);
}
}
}
public List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNGestureHandlerPackage()
);
}
@Override
public void invokeDefaultOnBackPressed() {
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();
}
}
@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 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
}
}
}
mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data );
}
}
上面的代码有这个类,可以先删除 RNGestureHandlerPackage。这两个代码可能因为有其他代码的引用,会报错,可以从其他地方去查看。
3.5 manifest.xml 文件的配置。
4. Rn中接入了react-native-gesture-handler,项目的配置
4.1 settings.gradle 中添加
include ':react-native-gesture-handler'
project(':react-native-gesture-handler').projectDir = new File(rootProject.projectDir, 'node_modules/react-native-gesture-handler/android')
4.2 app module 中添加
implementation project(':react-native-gesture-handler')
4.3 Application 中添加
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}
@Override
public List<ReactPackage> getPackages() {
return Arrays.<ReactPackage>asList(
new MainReactPackage(),
new RNGestureHandlerPackage()
);
}
};
4. Activity页面添加
public class MyReactActivity2 extends ReactActivity {
@Override
protected String getMainComponentName() {
return "flapp";
}
@Override
protected ReactActivityDelegate createReactActivityDelegate() {
return new ReactActivityDelegate(this, getMainComponentName()) {
@Override
protected ReactRootView createRootView() {
return new RNGestureHandlerEnabledRootView(MyReactActivity2.this);
}
};
}
}