前言
昨天下午自己动手将Android的原生app中嵌入ReactNative,集成中遇到各种坑,现在写一下集成步骤和坑的解决方法。
集成步骤
1、创建一个Android Studio的项目(已有项目跳过), 本文我创建的项目名为RnProject;
2、打开命令行终端,进入RnProject目录,如下:
3:执行相关的终端命令;
1、npm init
终端会出现输入,一步步输入就行了。entry_point即为我们加载Rn的入口JS文件,执行这步命令会生成一个package.json 文件,也可以直接回车,然后打开这个文件,进行编辑,相信怎么编辑就不用我细说了吧,大家网上搜索一个copy一下就ok啦!
注意事项:这个name不能大写哦
2、npm install --save react react-native
该命令是生成react和react-native的包,执行会下载最新的react-native 版本,执行成功的话,会在package.json 文件中会看到下图所示,当然不可能那么一帆风顺滴。。。
执行这个命令会有坑:
报错如下图:
即提示你需要安装react@16.0.0-alpha.6,那解决办法就是安装这个版本的react就是咯,在终端上执行如下命令:
npm i -S react@16.0.0-alpha.6,如下图:
执行完后,我们可以去package.json文件中去查看下是否安装成功,如看到上面的dependencies图则表示成功或者如下图也表示成功,我们可以接着进行下面的步骤啦!
3、在package.json文件中的scripts字段中添加:"start": "node node_modules/react-native/local-cli/cli.jsstart"
4、执行命令:curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig,该命令是在项目根目录下生成.flowconfig文件,该命令不是必须的!
5、接着就是编辑我们的Rn文件啦,在项目根目录下新建一个index.android.js的文件,文件内容如下:
'use strict';
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}>Hello World</Text>
</View>
)
}}
var styles = StyleSheet.create(
{ container: {
flex: 1, justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
AppRegistry.registerComponent('HelloWorld', () => HelloWorld);
4、Android项目中配置React-Native
1、在你的app中的build.gradle 文件中添加react native的依赖:
dependencies{
...
compile"com.facebook.react:react-native:+"// From node_modules.
}
注意事项:若指定特定的版本,必须和package.json文件中的react-native的版本号一致!
2、在项目的build.gradle文件中添加maven的入口,如下:
allprojects {
repositories {
...
maven {//AllofReact Native (JS, Android binaries)isinstalledfromnpm
url"$rootDir/.node_modules/react-native/android"
}
}
...
}
坑:同步gradle,添加完后会报一个如下图的错误:
解决方法:在项目的app根目录中build.gradle中的
android{
....
configurations.all {
resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.2'
}
}
3、修改MainActivity
下面是按照官网的例子来修改,有两种方法,这里就说明一种方法了!
public class MainActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler{
privateReactRootView mReactRootView;
privateReactInstanceManager mReactInstanceManager;
@Override
protectedvoidonCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mReactRootView =newReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModuleName("index.android")
.addPackage(newMainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
// 注意这里的HelloWorld必须对应“index.android.js”中的“AppRegistry.registerComponent()”的第一个参数一致 mReactRootView.startReactApplication(mReactInstanceManager,"HelloWorld",null); setContentView(mReactRootView);
}@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);
}
}@Override public void invokeDefaultOnBackPressed(){
super.onBackPressed();
}@Override public void onBackPressed(){
if(mReactInstanceManager !=null) {
mReactInstanceManager.onBackPressed();
}else{
super.onBackPressed();
}
}@Override public boolean onKeyUp(intkeyCode, KeyEvent event){
if(keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager !=null) {
mReactInstanceManager.
showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}}
4、配置Android的 AndroidManifest.xml 清单文件的权限:
<user-permission android:name="android.permission.INTERNET"/>
设置react的开发模式,便于测试
<activity android:name="com.facebook.react.devsupport.DevSettingActivity"/>
5、部署完成了,接下来就是执行了!在终端上执行命令:
npm start
执行该命令时报错,如下图:
从报错原因可知,package.json文件出错了,打开文件一看,test前面缺少一个逗号;
修改后再次执行该命令又报错了!坑哇。。。。如下图:
一看报错信息,原来是刚才运行命令的时候 已经暂用了8081这个端口号了,再次运行就报这错了,很久,那我就把占用这个端口号的进程给干掉就是了!先用 lsof -i :8081 查看哪些进程占用了端口号,接着用kill -9 进程id 命令杀掉进程,全部杀完后接着 执行npm start
这下ok了,启动成功啦,终于松了一口气!
6、在studio 上run app
毫无疑问不可能一下成功的啦,你懂滴!error了,查看错误日志如下图:
是libgnustl_shared.so文件原因,原来32位和64位的兼容问题,如果直接init的project的话,也不能在64位Android手机上运行,会提示"/data/data/com.hfox.lovesquare/lib-main/libgnustl_shared.so" is 32-bit instead of 64-bit 这个错误,既然是兼容问题,那我们就取消掉所以的64位.so文件就行啦,只加载32的就可以了,具体解决如下:
1.在项目的根目录的gradle.properties里面添加一行代码android.useDeprecatedNdk=true.、
2.在app 的build.gradle文件里添加以下代码:
android {
...
defaultConfig {
...
ndk {
abiFilters"armeabi-v7a","x86"
}
packagingOptions {
exclude"lib/arm64-v8a/libgnustl_shared.so"
}
}
}
接着运行,又报错,oh my god!真想。。。错误日志如下:
Error calling AppResitry.runApplication
Cased by Could not get BatchedBridge, make sure your bundle is packaged correctly
不能运行,原因黄色箭头很明确说明了!bundle不对,解决方法就是
先在src/main目录下新建一个assets目录,如果已存在,则跳过
然后执行命令:
react-native bundle –platform android –dev false –entry-file index.android.js –bundle-output src/main/assets/index.android.bundle –assets-dest src/main/res/
执行完图如下:成功!
在assets目录下会生成两个文件:index.android.bundle,index.android.bundle.meta(可忽略删除),再run app !成功啦 ,终于看到hello world了!不容易哇!希望对大家有所帮助。。。