RN与现有的原生app集成
https://facebook.github.io/react-native/docs/integration-with-existing-apps.html
RN可以很好地支持往一个原生的app上添加RN的组件。通过简单的步骤,我们可以添加RN基础的特征、组件等。后面以android为例。
关键思想(概要)
- 设置RN的依赖和结构目录
- 用JS开发RN组件
- 添加一个ReactRootView到android app上,这会作为RN组件的容器
- 开启RN服务器和运行原生app
- 检查RN组件是否正常工作
预备知识
按照官方指引,设置好RN开发环境。
- 设置目录结构。把android项目“内容”复制到RN项目根目录下的android文件夹中(初始化的RN项目中就已经有这样一个文件夹了,里面有初始的android项目内容)
- 安装JS依赖。在RN项目创建一个package.json,内容如下(初始的RN项目也有这些内容了)
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
}
}然后安装react和react-native依赖
npm install --save react@16.0.0-beta.5 react-native
把RN添加到app中
配置maven仓库
把RN依赖添加到android/app/build.gradle中(测试发现不能使用+,应该指定版本,将+替换为npm中对应的RN版本号,如package.json中 ^0.5,则将+替换为0.5):
dependencies {
...
compile "com.facebook.react:react-native:+" // From node_modules.
}
光光以上这么配置,gradle会找不到这个依赖,需要在android/build.gradle中配置一个仓库告诉gradle去哪里找依赖(确保添加到allproject这个块中,而且要在所有其他maven仓库之上。同时确保下面的url是正确的):
allprojects {
repositories {
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
...
}
...
}
配置权限
往AndroidManifest.xml清单文件中加上:
<uses-permission android:name="android.permission.INTERNET" />
如果需要在原生app中打开开发者菜单,也需要在清单文件中加上(如果要发布则把下面这行去掉):
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
代码集成
在项目的根目录创建一个index.js,这是RN程序的入口点,往index.js中添加如下内容
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('MyReactNativeApp', () => HelloWorld);
ReactRootView
现在需要写一些原生代码来启动RN runtime和渲染界面。在activity中创建ReactRootView,并作为主内容显示:
public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler {
private ReactRootView mReactRootView;
private ReactInstanceManager mReactInstanceManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mReactRootView = new ReactRootView(this);
mReactInstanceManager = ReactInstanceManager.builder()
.setApplication(getApplication())
.setBundleAssetName("index.android.bundle")
.setJSMainModulePath("index")
.addPackage(new MainReactPackage())
.setUseDeveloperSupport(BuildConfig.DEBUG)
.setInitialLifecycleState(LifecycleState.RESUMED)
.build();
mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null);
setContentView(mReactRootView);
}
@Override
public void invokeDefaultOnBackPressed() {
super.onBackPressed();
}
}
以上的ReactInstanceManager可以在多个activity和fragment之间共享。接着使RN与activity的生命周期同步(这是为了让JS代码能处理这些生命周期,如JS可以检测到用户按了后退):
@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 onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
如果API大于23,需要配置开发模式下错误信息的显示权限,因为错误信息必须要显示在所有窗口之上。在activity的onCreate中添加如下代码:
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);
}
}
接着需要重写activity的onActivityResult方法
@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 boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
最后,在清单文件中对这个activity进行声明
<activity
android:name=".MyReactActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
</activity>
运行
到根目录下执行npm start来打包生成js bundle。然后直接构建app(如使用android studio)启动app看效果。
实践
通过android studio创建一个项目,项目目录指定为root/android/。
项目地址:https://github.com/947133297/rn-ntegration-with-existing-apps
RN与现有的原生app集成的更多相关文章
- RN在Android打包发布App
参考资料:http://www.jianshu.com/p/b8811669bcb6 RN在Android打包发布App 1-:生成一个签名密钥你可以用keytool命令生成一个私有密钥.在Windo ...
- Vue+原生App混合开发手记#1
项目的大致需求就是做一个App,里面集成各种功能供用户使用,其中涉及到很多Vue的使用方法,单独总结太麻烦,所以通过这几篇笔记来梳理一下.原型图如下: 路由配置 主界面会用到一些原生App方法,比如验 ...
- H5、原生app、混合开发三者比较
一.概念 a) H5:即Html5,接触过互联网的都知道html,所以很明显h5是html的第5次重大修改的一项超文本标记语言的标准协议. b) 原生:使用原生制作APP(Native app),即在 ...
- 仿原生app,native特效
为解决手机端wap项目中页面跳转响应慢的问题,基于jquery开发了fr.routeApp.js,使得wap项目拥有原生app的流畅,跳转时亦有native的特效 html部分 <!--定义容器 ...
- 吓哭原生App的HTML5离线存储技术,却出乎意料的容易!【低调转载】
吓哭原生App的HTML5离线存储技术,却出乎意料的容易![WeX5低调转载] 2015-11-16 lakb248 起步软件 近几天,WeX5小编编跟部分移动应用从业人士聊了聊,很多已经准备好全面拥 ...
- 转发-UI基础教程 – 原生App切图的那些事儿
UI基础教程 – 原生App切图的那些事儿 转发:http://www.shejidaren.com/app-ui-cut-and-slice.html 移动APP切图是UI设计必须学会的一项技能,切 ...
- JavaScript开发原生App模式能否突出重围?
移动应用制作的第三方服务市场已经被瓜分得差不多了,对于刚起步的中小企业来说,这些公司的 IT 部门人员比较熟悉的是 Appcan ,但随着互联网公司对 App 开发的需求持续升温,也有不少后来的闯入者 ...
- Do带你解析:原生APP与web APP的区别
对于DeviceOne原生跨平台APP与WEB APP的区别,很多人还不是很清楚,下面就让小编来简单介绍DeviceOne原生APP的功能以及与WEB APP的区别. 定义,什么是原生APP和web ...
- NativeScript - JS 构建跨平台的原生 APP
使用 NativeScript,你可以用现有的 JavaScript 和 CSS 技术来编写 iOS.Android 和 Windows Phone 原生移动应用程序.由原生平台的呈现引擎呈现界面而不 ...
随机推荐
- 证书重复冲突问题:Command /usr/bin/codesign failed with exit code 1
打开钥匙串 查看是否有两个identifier为相同 的证书,显然导证书的时候不知道怎么把证书导进了系统帐号,并且还重复了.把重复的证书删除就行了.
- centos 7 安装pip和pip3
首先安装epel扩展源: yum -y install epel-release 更新完成之后,就可安装pip: yum -y install python-pip 安装完成之后清除cache: yu ...
- LCT 学习笔记
LCT学习笔记 前言 自己定的学习计划看起来完不成了(两天没学东西,全在补题),决定赶快学点东西 于是就学LCT了 简介 Link/Cut Tree是一种数据结构,我们用它解决动态树问题 但是LCT不 ...
- 牛客练习赛42D(性质、数学)
题目传送 就像题解所说的,写几个可以发现有分成四段的性质:第一段是从n开始往下贪,第二段是个数字,第三段……卧槽好吧真难描述. 然后发现这个数据量可达1e9,所以考虑“二分确定序列+数学计算”的方式解 ...
- Apache的多处理模块MPM
本博文主要参数 Apache 2.2文档以及Apache模块开发指南 Apache的整个运行可以分为两个阶段:启动阶段和运行阶段. 在启动阶段时,它以ROOT特权来启动,进行解析配置文件(一般就是ht ...
- C#oracle备份和还原
最近公司的oracle备份工具不好使了,原来是公司的人用VB写的,由于我是主攻C#的,所以想着自己来写一个C#版本的oracle备份和还原工具. 一开始,我按照原来的设计思路来进行编写,想在pluss ...
- vue2.0:(三)、项目开始,首页入门(main.js,App.vue,importfrom)
接下来,就需要对main.js App.vue 等进行操作了. 但是这就出现了一个问题:什么是main.js,他主要干什么用的?App.vue又是干什么用的?main.js 里面的import fro ...
- 1058 合唱队形 2004年NOIP全国联赛提高组
1058 合唱队形 2004年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Descripti ...
- 兼容IE的滚动条自定义样式
废话不多说,直接上: IE专属的滚动条样式定义,只能设置各种原始结构的颜色,宽高结构等其他样式无法修改: div{ scrollbar-arrow-color: red; /*三角箭头的颜色*/ sc ...
- LR中webservice服务测试的脚本
Action(){ /* 测试QQ是否在线的功能接口 输入参数:QQ号码 String,默认QQ号码:8698053. 返回数据:String,Y = 在线:N = 离线:E = QQ号码错误:A = ...