react-native移植到android项目中详细步骤

开篇胡扯:

刚刚过完年假回来上班,公司并没有特别的任务安排。闲来无事,就莫名的开始了人生第一篇的博客之旅吐舌头。本来不想特意将自己get到的东西写到博客上。

一是担心自己的经验不够,写了害怕误人子弟;

二是自己可以随便在云笔记上写自己懂的东西,不必花费很多时间在斟酌字句上,担心有什么疏漏。

好了,既然决定写了就认真的分享下(免得真的误人),自己也再次巩固所学到的,还可以无意之中的帮助别人,何乐不为!


回归正题,对于react-native,去年就开始稍微了解过,尝试写过些小demo,但由于自己的懒惰就没有去尝试性的往下面继续研究了,主要是公司还没用到,自己就想偷个懒。恰巧昨天看到鸿神推送的关于react-native的文章,于是就下定决心开始重拾起来。下面就开始说说个人昨天一天对于rn集成到android项目中实践心得吧,希望各位给出意见!

前提rn的环境配置完毕(以下说的拷贝是react-native init之后的工程里的文件)

第一步:

进入android工程根目录使用npm init命令创建package.json文件(或者将生成好的rn项目拷贝过去)千万要记住,这个里面的react-native版本一定要和android工程里gradle配置的版本一样,不然就出现了那个“Module  0”的版本不一致的错误了。

第二步:

在android工程的根目录使用npm install -save react react-native下载源文件,最后会生成一个node_modules文件夹(当然也可以拷贝原来的)

第三步:

拷贝或者下载.flowconfig文件(下载链接https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig),主要是给folw用的,用来做静态代码检查,下载完后放在android的根目录下即可。

第四步:

配置Android项目react-native依赖库,版本号一定要和本地rn的版本一致


第五步:

配置react-native本地代码路径,本步骤是制定Android-studio编译react-native时用制定路径下的代码,大致这个意思。这里添加是在根目录下的build.gradle中修改,放在在allprojects节点下。截图如下:


同步工程在External Libraries看到这个匹配的版本的依赖包就说明成功了。

第六步:

修改package.json文件,修改信息如下:

{
"name": "myapplication",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"bundle-android":"react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output MyApplication/app/src/main/assets/index.android.bundle --sourcemap-output MyApplication/app/src/main/assets/index.android.map --assets-dest MyApplication/app/src/main/res/"
},
"author": "0",
"license": "ISC",
"dependencies": {
"react": "^15.3.1",
"react-native": "^0.33.0"
}
}

name是工程名字字母都小写,scripts一定要根据自己的实际配置不然会报错,dependencies按照自己的版本来修改(最好参照原生的react-native的package.json)

第七步:

创建原生安卓类,作为加载rn容器,再将index.android.js(rn的核心代码文件)文件直接放在android项目根目录就行或者自己创建添加如下代码:

import React,{Component} 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}>这是React-Native组件</Text>
      </View>
    )
  }
}
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    backgroundColor:'#ccc',
  },
  hello: {
    fontSize: 20,
    color: '#fff',
    textAlign: 'center',
    margin: 10,
  },
});
//注意这里的reactdemo哦
AppRegistry.registerComponent('reactdemo', () => HelloWorld);

再创建一个ReactActivity

public class ReactActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    private LinearLayout ll;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.myreactdemo);
        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();
        //reactdemo这个名字要与package.json、以及react-native中index.android.js中的项目名要一致,否则会出错。
        mReactRootView.startReactApplication(mReactInstanceManager, "reactdemo", null);
        ll= (LinearLayout) findViewById(R.id.ll);
        ll.addView(mReactRootView);

    }
    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostPause(MyReactActivity.this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onHostDestroy(MyReactActivity.this);
        }
    }

    @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);
    }
}
再在MainActivity里添加点击事件跳入ReactActivity
 findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (Build.VERSION.SDK_INT>=23){
                    if (!Settings.canDrawOverlays(MainActivity.this)){
                        startActivity(new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION));
                        return;
                    }else{

                    }
                }else{
                    //绘UI代码,这里android6.0以下的系统可以直接绘出即可
                }
                startActivity(new Intent(MainActivity.this,ReactActivity.class));
            }
        });

第八步:

修改AndroidManifest.xml配置文件如下:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
<activity android:name=".MyReactActivity"/>
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>

第九步:

打开cmd进入到android的目录下,运行react-native start ,启动服务,再运行android项目,就可以看见一部分是android原生控件,一部分是rn控件


常见错误

java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.()' is inaccessible to class 'com.f
acebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in 
/data/app/package.name-2/base.apk)

 
 

解决办法:(老外也遇到了这样的问题https://github.com/facebook/react-native/issues/6152#issuecomment-200759453)在项目下修改以下的文件内容:
.gitignore(在该文件里添加排除项,node_modules/  npm-debug.log
app/build.gradle (将 'com.android.support:appcompat-v7:24.2.1' 改为 'com.android.support:appcompat-v7:23.0.1')
gradle.properties (在文件末尾添加,android.useDeprecatedNdk=true)

红屏问题"Could not get BatchedBridge, make sure your bundle is packaged correctly"

解决方法: 主要就只遇到这一个问题, 更改ip和port没有解决了, 后来在package.json中的"scripts"中添加"bundle-android":"react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output 工程名/app/src/main/assets/index.android.bundle --sourcemap-output 工程名/app/src/main/assets/index.android.map --assets-dest 工程名/app/src/main/res/",如果没有assets目录,手动添加下,不过运行时没有效果, 在cmd中手动执行下(去掉命令的工程名如果在根路径下执行命令), assets目录中会多出几个文件, 即可解决这个问题


参考资料:

如何把React Native嵌入到原生android应用中

React Native 集成到已有项目








评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值