背景
我们可能需要将react-native集成到已有工程的某个module中,而不是从头创建一个新工程。下面记录了笔者一个demo的集成过程。
已有工程结构
下图中,app为application类型module,rntrial为library类型的module,就是我用来集成react-native的
准备工作
按照官方教程搭好新建rn工程的环境,传送门http://reactnative.cn/docs/0.51/getting-started.html#content
再看下“集成到现有原生应用”Android部分的内容,笔者也是参考这里的步骤进行的。
开始集成
1、移花接木
运行命令 :react-native init [工程名] 创建一个全新的rn工程,如下
(注意工程名在下图标识的三个文件中均有出现)
删掉这个新工程android目录下的内容,将原工程根目录的所有文件拷贝到这个android目录下
这样原工程就变成了一个标准的rn工程,在工程根目录下可以使用npm、react-native等命令来操作了
2、创建一个具有RN功能的Activity
rntrail目录中的build.gradle如下
apply plugin: 'com.android.library'
android {
compileSdkVersion 26
defaultConfig {
minSdkVersion 19
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
api 'com.facebook.react:react-native:0.51.0'
}
创建RntrialActivity作为rn的主界面,并实现DefaultHardwareBackBtnHandler,主要代码如下(请务必注意代码中的注释)
public class RntrailActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
private static final int OVERLAY_PERMISSION_REQ_CODE = 0x01;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//这里不加权限判断 6.0或以上机型会闪退
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())
//这是设置assets目录下的打包过的js文件名 这个文件可用命令生成 但调试期间我们使用npm server动态注入 发布时才将它打进assets
.setBundleAssetName("index.android.bundle")
//这里设置js入口文件 旧一点的api可能是setJSMainModuleName 但我的版本是0.51.0 取而代之的是setJSMainModulePath方法
.setJSMainModulePath("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意这里的“Rnfeel”必须
// 对应index.js”中的“AppRegistry.registerComponent()”的第一个参数值
// 对应“package.json”中的“name”属性值
// 最好也将“app.json”中的“name”和“displayName”改成它
mReactRootView.startReactApplication(mReactInstanceManager, "Rnfeel", null);
setContentView(mReactRootView);
}
...
@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...
}
}
}
}
}
3、检查相关文件内容
以下几个文件中的相关内容务必保证一致
app.json中的name和displayName属性值
{
"name": "Rnfeel",
"displayName": "Rnfeel"
}
index.js中registerComponent的第一个参数值
AppRegistry.registerComponent('Rnfeel', () => App);
package.json中的name属性值
"name": "Rnfeel",
4、在真机上运行和调试
首先连接usb,一台电脑只连一部手机(电脑上的模拟器也要关闭,不然有些操作会失败)
运行命令:react-native run-android 将应用安装到设备上
在编译的同时会弹出node server的界面,这个服务可以通过usb绑定设备实现js热更新
运行命令adb reverse tcp:8081 tcp:8081与设备建立连接
修改js内容,摇晃手机弹出rn设置菜单, 选择reload更新界面
rn设置菜单中选择 Debug JS Remotely开启远程调试
Chrome地址栏输入http://localhost:8081/debugger-ui/ ,打开开发者模式,设备连接好后即可调试