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运行完我这提示aaa@qq.com requires a peer of aaa@qq.com but none was installed,打开package.json看看,里面react版本不是16这个,这时候是react-native和react版本不一致问题,一定要解决,否则packager服务起不来,解决办法是输入命令npm i -S aaa@qq.com。再看看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文件夹为啥不一起移过去,那样据说会很卡...
推荐阅读
-
android使用webwiew载入页面使用示例(Hybrid App开发)
-
Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图
-
reactnative利用webvView嵌入h5页面以及RN与webView的通信教程
-
Android跳转到应用商店的APP详情页面实现方案
-
Android原生App跳转到React Native App实现方法
-
webview中调用Android如何关闭app页面
-
h5页面唤起app如果没安装就跳转下载(iOS和Android)
-
Android NFC 写入包名,NDEF数据,唤醒 指定 APP 跳转 指定 页面Activity,读取数据处理
-
Flutter 嵌入到Android原生项目中的几种实现方式
-
Android实现原生锁屏页面音乐控制