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

作者: wfunny | 来源:发表于2017-06-03 13:05 被阅读111次

    前言

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

    相关文章

      网友评论

        本文标题:Android原生APP中集成React Native (各种坑

        本文链接:https://www.haomeiwen.com/subject/zobpfxtx.html