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 原生移动应用程序.由原生平台的呈现引擎呈现界面而不 ...
随机推荐
- 关于 prototype与__proto__ (用到的时候再看一次 加深理解)
链接顺序: 1. https://blog.csdn.net/ligang2585116/article/details/53522741 2.https://www.jianshu.com/p/80 ...
- Gitlab备份,Crontab定时备份
1:Gitlab备份非常简单,只需要一条命令就可以创建完整的备份 gitlab-rake gitlab:backup:create 使用以上命令,就相当于在/var/opt/gitlab/backup ...
- [題解]hdu_6412公共子序列
https://blog.csdn.net/nka_kun/article/details/81902421 #include<bits/stdc++.h> #define ll long ...
- tcp端口扫描(python多线程)
1 使用单线程扫描单台主机 首先实现的是对单台主机中0-1024端口的扫描,发现差不多每秒扫描一个端口,很慢. import socket def tcp_scanner(host,port): cl ...
- UVa12298(生成函数的简单应用+FFT)
I have a set of super poker cards, consisting of an infinite number of cards. For each positive compo ...
- IIS7开启目录浏览功能
IIS7开启目录浏览功能: 在右侧操作中点击启用,并在左侧面板中勾选显示字段.
- 关于childNodes和children
1.childNodes. 会把注释.空文本.非空文本.标签都当做节点. 2.children: 在IE8以后的版本只会找到标签元素.不包括文本.空文本.注释.在IE8以前的版本会找到标签元素和注释, ...
- Spark Mllib里如何将trainDara训练数据文件里提取第M到第N字段(图文详解)
不多说,直接上干货! 具体,见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的第13章 使用决策树二元分类算法来预测分类StumbleUpon数据集
- 【详解】JS中的作用域、闭包和回收机制
在讲解主要内容之前,我们先来看看JS的解析顺序,我们惯性地觉得JS是从上往下执行的,所以我们要用一个变量来首先声明它,来看下面这段代码: alert(a); var a = 1; 大家觉得这段代码有什 ...
- idea 设置加载多个资源文件,显示本地图片
idea 经常只会设置一个资源路径,这个路径就是项目的路径.但是当要加载的文件处于其他位置时,则需要增加虚拟路径的配置. 如图:第一个是项目路径 第二个是图片路径