android 原生app嵌入reactnative页面

来源:互联网 发布:套淘宝保证金如何秒回 编辑:程序博客网 时间:2024/05/17 15:59

话说原生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文件夹为啥不一起移过去,那样据说会很卡...

阅读全文
0 0
原创粉丝点击