android 原生app嵌入reactnative页面

话说原生Android app嵌入reactnative页面的网上资料也不少了,而且也不错,但是自己照着做的时候还是问题多多,难道真的是坑太多吗?摸索着最终还是实现了,唉,眼泪哗哗的,先记录一下吧。

第一步让我晕的就是目录结构,看了官方文档一直说项目根目录,结果百度了一下根目录,一哥们说是src的上级目录就是app所在的目录,感觉也是,结果就做下去了,结果就悲催了,折腾了一下午也没搞定,然后看了江清清的文章,这把知道目录了,要在项目的同级目录里面,也就是app的上级目录,src的上上级目录做。这把做下去历经不知道多少劫难,成功啦,开心!但是。。。为毛项目名称一定要是Android啊,这不坑吗,难道我以后的项目名字都有叫这个啊,这显然不行,结果我新建了一个项目,名字随便起的叫ReactNativeOne,结果就报错了:Android project not found. Maybe run react-native android first?,这时候看了网上一哥们的解答,试了一下,确实可以,就是先用android stdio先运行app,首先我们的app是一个原生的,as启动自然没问题。点击绿色小三角运行app启动了,然后运行命令react-native start或者npm start,就可以了,然后跳转RN页面,设置ip和端口,重新加载一下就ok了。下面是demo的主要实现不步骤,和网上有很多雷同,就不一一给出链接了。

1、E:盘下新建目录ReactNativeProject目录,as新建工程ReactNativeOne,一个原生android就出来了,目录如下:


然后cmd进入到ReactNativeProject目录下面,执行npm init命令,提示输入name的时候就输入reactnativeproject,要小写。其他的一路enter键下去就好了。然后再执行命令npm install --save react react-native,等待一会执行成功,目录结构如下:


npm install --save react react-native运行完我这提示react-native@0.44.0 requires a peer of react@16.0.0-alpha.6 but none was installed,打开package.json看看,里面react版本不是16这个,这时候是react-native和react版本不一致问题,一定要解决,否则packager服务起不来,解决办法是输入命令npm i -S react@16.0.0-alpha.6。再看看package里面react版本就变了。接下来修改package.json文件,package.json里面scripts替换"start": "node node_modules/react-native/local-cli/cli.js start"。然后上图目录里面加入index.android.js文件,代码如下:

import React, { Component } from 'react';
import { AppRegistry,StyleSheet, Text, View } from 'react-native';

class Blink extends Component {
  constructor(props) {
    super(props);
    this.state = { showText: true };

    // 每50毫秒对showText状态做一次取反操作
    setInterval(() => {
      this.setState({ showText: !this.state.showText });
    }, 50);
  }

  render() {
    // 根据当前showText的值决定是否显示text内容
    let display = this.state.showText ? this.props.text : ' ';
    return (
      <Text style={styles.bigblue,styles.red}>{display}</Text>
    );
  }
}

class BlinkApp extends Component {
  render() {
    return (
      <View>
        <Blink text='I love to blink' />
        <Blink text='Yes blinking is so great' />
        <Blink text='Why did they ever take this out of HTML' />
        <Blink text='Look at me look at me look at me' />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  bigblue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

AppRegistry.registerComponent('ReactNativeProject', () => BlinkApp);

目录如下:


接下来修改as工程,打开MainActivity页面,加入一个按钮,然后新建一个ReactNativeActivity页面,按钮跳转到该页面。然后再建立工程,app里面的build.gradle里面导入compile "com.facebook.react:react-native:+" ,这个要在npm install --save react react-native命令后执行,如果顺序反了就在as里面无法正确导入react-native包,可能导入的是老版本的而不是你本地安装的,这个地方要注意一下,否则as就报错了。

gradle里面最低sdk版本要改为至少16,即minSdkVersion16,否则报错。

然后还是在app里面的build.gradle里面的build.gradle里面android{}加入如下代码:

 configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
    }
我这最终代码如下:

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.2"
    defaultConfig {
        applicationId "com.example.user.reactnativeone"
        minSdkVersion 16
        targetSdkVersion 25
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    configurations.all {
        resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.0'
    }
}
不然会报如下错误:
Conflict with dependency 'com.google.code.findbugs:jsr305'. 
Resolved versions for app (3.0.0) and test app (2.0.1) differ. 
See http://g.co/androidstudio/app-test-app-conflict for details.

接下来AndroidManifest里面加入权限:

<uses-permissionandroid:name="android.permission.INTERNET"/>

<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
和DevSettingsActivity声明,不然到时候点击Dev Setting就崩啦

<activityandroid:name="com.facebook.react.devsupport.DevSettingsActivity"/>

最后就是修改DevSettingsActivity里面的代码了:

public class ReactNativeActivity extends Activity implements DefaultHardwareBackBtnHandler {

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;
    public static int OVERLAY_PERMISSION_REQ_CODE = 1234;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        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();
        mReactRootView.startReactApplication(mReactInstanceManager, "ReactNativeProject", null);
        setContentView(mReactRootView);

        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);
            }
        }
    }

    @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...
                }
            }
        }
    }

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

    @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
    public void onBackPressed() {
        if (mReactInstanceManager != null) {
            mReactInstanceManager.onBackPressed();
        } else {
            super.onBackPressed();
        }
    }
}
好了,这下基本上工作完事,准备跑起来吧。

但是...记得开篇说的注意事项了吗,先跑as,模拟器运行处app后,然后在命令行下执行react-native start或者npm start命令。


模拟器跑出来app后进入android原生页面


点击按钮进入react-native页面,ctrl+M调出菜单,点击Dev Setting设置ip和端口


最后as重新运行app就好了,这之前可能要重新运行nmp start命令,最终RN页面如下,是一个带有闪啊闪啊字的页面,截图个静态的页面:


结束啦。。。并没有。。。

参考网上一个哥们文章,说的有道理,我们为啥要把js和json文件放在工程外面呢,这不合理啊,他们属于工程内部文件啊,那咱把他们移到工程里面,目录如下:


然后开启packager服务的命令要修改成如下样子了:


其他的都一样了,至于node_modules文件夹为啥不一起移过去,那样据说会很卡...

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值