Android原生APP中集成React Native (各种坑!!!)

前言

昨天下午自己动手将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了!不容易哇!希望对大家有所帮助。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容