项目连接: RNHelloWorld
ReactNative使用手册
重要说明:
本文和ReactNative从零到完整项目-嵌入到安卓原生应用(方式一)步骤上从第八步开始不一样其它都一样,之所以分开成两篇,一是我自己本来就是两个项目按两种方式完成的,二是为了看起来更清晰,如果看过上一篇,那么这一篇可以直接跳到第八步开始看,文章结尾给出参考博客链接
把React Native组件植入到Android应用
第一步:引入react-native
在androidstudio的Terminal窗口中输入 npm init
,接着会提示你输入一些东西(除了项目名字其他都可直接回车使用默认值)
当我们输完的时候将工程切换到project模式下,可以看到工程多了一个package.json的文件
{
"name": "rnhello",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "赖天兵",
"license": "ISC"
}
看到这个文件有一种很熟悉但又陌生的感觉,但是它的作用都应该猜到了,这个和我们build.gradle中的配置是一样的作用,其实就是配置工程的一些属性
第二步:添加react和react_native模块
在Terminal窗口中输入:npm install --save react react-native
并执行,然后就是静静的等待,如果有报错,自己手动敲"--"这个符号,因为在不同的系统下“--”可能是不一样的,完成后就可以看到工程多了一个node_modules模块
第三步:在命令行中运行curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig
(这步对Windows来说真的坑)
直接运行会提示你:'curl' 不是内部或外部命令,也不是可运行的程序
所以看来我的首先处理Windows运行curl命令的问题了
curl是利用URL语法在命令行方式下工作的开源文件传输工具。它被广泛应用在Unix、多种Linux发行版中,并且有DOS和Win32、Win64下的移植版本。
所以首先要解决Windows下支持curl
命令的问题Windows下安装使用curl命令
提示有可能你找不到| curl-7.33.0-win64-ssl-sspi.zip
再提示一下当你按照上面Windows下安装使用curl命令走到了下图步骤时
这时候应该在命令窗口中输入curl -v -X OPTIONS https://www.baidu.com/
,这是文档没有说的,而是直接输入到命令行里了,第一次看如果不知道这个,那会很懵逼的
不过遗憾的是我按照上门的连接文档一步步走下来还是无法在任何地方使用curl命令(我的电脑win10 64位)
所以我用了最简单的方法,直接复制我们下载的curl.exe
到工程根目录,这样在本工程的根目录就能运行curl命令了
但是:真想爆粗口,还是生成不了.flowconfig
文件,
所以真正最直接的解决方式来了:自己在项目的根目录下创建.flowconfig
文本文件,然后打开.flowconfig连接复制文本到刚刚创建的文件中即可
走到这里突然想感叹一句,我饶了一大圈到底是为了啥
第三步:在package.json文件中的scripts
里面配置启动脚本"start": "node node_modules/react-native/local-cli/cli.js start",
{
"name": "rnhello",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node node_modules/react-native/local-cli/cli.js start",
"bundle-android": "react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false"
},
"author": "赖天兵",
"license": "ISC",
"dependencies": {
"react": "^16.2.0",
"react-native": "^0.53.3"
}
}
其实在官方文档中第三步已经完了,但是毕竟我是踏过了很多巨坑的,看了很多篇博客的我告诉你这步还没完,照常理这里还应该配置打包用index.android.js生成index.andriod.bundle的配置(你也可以尝试不做,绝对会出现一些经典的bug,这里就不提了,我会有一篇专门的文章记录这些bug)
配置生成发布、打包时所需要bundle文件的配置
在很多博客中会这样解决这个问题,像上面完整package.json中的scripts
代码一样添加
, "bundle-android": "react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false"
这一句在官方文档中没有说明,但是最好加上(虽然我加上后,至少我这里没有卵用,据说是新版本的RN不支持自动生成打包所需的bundle文件了),但是这里需要修改一下,很多博客都直接是
"bundle-android": "react-native bundle –platform android –dev false –entry-file index.android.js –bundle-output android/app/src/main/assets/index.android.bundle –sourcemap-output android/app/src/main/assets/index.android.map –assets-dest android/app/src/main/res/"
但是这是错的,打包的时候我们都要根据自己项目目录的结果做一些调整,不过在上面package.json中我已经做过调整了,但是还是无法自动完成打包bundle
解决:我们先在main下面创建asserts文件夹,然后进入工程根目录打开cmd输入
react-native bundle --platform android --entry-file index.android.js --bundle-output app/src/main/assets/index.android.bundle --dev false
(注意-output后面的参数根据自己的项目目录结构来写)
成功后的项目
你或许看过很多在安卓原始项目中嵌套RN,并按照他们步骤一步步完成了,但是最后就是看不到效果,这里就是其中一个重要的原因
如果这步完成了,那么恭喜你,你基本上能看到效果了,后面可能还要出bug,但是都是些容易解决的固定的了
第四步:在项目根目录中创建index.android.js
文件
在index.android.js中编写我们的代码
import React from 'react';
import {
AppRegistry,
StyleSheet,
Text,
View
} from 'react-native';
class HelloWorldApp extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.hello}>Hello world! I am from ReactNattive!!</Text>
</View>
)
}
}
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
});
//这里的第一个参熟名字要和我们创建的这个工程项目名一样
AppRegistry.registerComponent('RNHelloWorld', () => HelloWorldApp);
提示:在本系列RN博客的第二篇创建HelloWorld的时候说过,registerComponent()注册时名字必须和项目名字保持一致
第五步:添加ReactNative依赖
首先在APP的build.gradle
中添加
dependencies { ... compile "com.facebook.react:react-native:+" // From node_modules. }
其次在工程的build.gradle
中添加进入本地ReactNative仓库的路径,但是官方源文档写的路径是
$rootDir/../node_modules/react-native/android
如果你直接复制使用,恭喜你你又入坑了
因为我们通过之前第二步添加的添加react和react_native模块,默认是项目的根目录下,而官方文档给出的路径其实是多了“../”所以这就是一个坑(说到这里提一句,网上很多文章都是直接用的官方路径,但是项目结构又和我的一样,我真怀疑他们写那个文章的时候只是copy别人文章,自己根本没有成功,这也是很多人按照别人文章一步步到最后还是报错的又一个原因),这里路径应该对应自己工程中module的路径
我的工程目录
所以我的路径应该是
allprojects {
repositories {
...
maven {
// All of React Native (JS, Android binaries) is installed from npm
url "$rootDir/node_modules/react-native/android"
}
}
...
}
添加完成后记得同步以下哦,不过等待的时间过于漫长(最好开VPN,我是开了VPN才同步完成的),可以先往后继续看文章
第六步:在清单文件中添加网络请求权限,必须添加的
官方原话Next, make sure you have the Internet permission in your AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
以及调试需要用到的权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.SYSTEM_OVERLAY_WINDOW"/>
第七步:在清单文件中注册DevSettingsActivity
,此步骤可以省略,功能就是重载JavaScript
如果您需要访问DevSettingsActivity添加到您的AndroidManifest.xml:
<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />
这只在开发服务器重新加载JavaScript时才真正用于开发模式,因此,如果需要,可以在发布版本中将其剥离。
第八步:新建一个 ReactNativeActivity ,并在清单文件中设置成启动页面,用来展示 React Native 的页面:
public class ReactNativeActivity extends ReactActivity {
@Override
protected String getMainComponentName() {
return "RNHelloWorld";
}
}
看过上一篇的人,再回头看看上一篇,应该觉得很吃惊,原来可以这么简洁,而且成功的避开了RN版本不同可能找不到.setJSMainModuleName("index.android")
这个方法的坑。
接下来(这个步骤是可以跳过的),我们需要将一些活动生命周期回调传递给ReactInstanceManager:
@Override
protected void onPause() {
super.onPause();
if (mReactInstanceManager != null) {
mReactInstanceManager.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (mReactInstanceManager != null) {
mReactInstanceManager.onResume(this, this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mReactInstanceManager != null) {
mReactInstanceManager.onDestroy();
}
}
注意:如果你直接copy官网中代码的话,是会出错的,因为ReactNative版本更新了,方法名字更改和安卓更加同步了
(也是可跳过的)我们还需要将按钮事件传递给React Native:
@Override
public void onBackPressed() {
if (mReactInstanceManager != null) {
mReactInstanceManager.onBackPressed();
} else {
super.onBackPressed();
}
}
作用:这允许JavaScript控制用户按下硬件后退按钮时发生的情况(例如,实现导航)。当JavaScript不处理背按时,您的invokeDefaultOnBackPressed方法将被调用。默认情况下,这只是完成你的Activity。
最后(这个步骤也是可以跳过的),我们需要连接开发菜单。默认情况下,这是通过(愤怒)激发设备来激活的,但这在模拟器中并不是很有用。所以我们在按下硬件菜单按钮时显示它(Ctrl + M如果您使用的是Android Studio模拟器,请使用它):
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) {
mReactInstanceManager.showDevOptionsDialog();
return true;
}
return super.onKeyUp(keyCode, event);
}
第九步(此步骤可以跳过):配置权限以便开发中的红屏错误能正确显示
如果您的应用定位到Android API level 23
或更高版本,请确保您已overlay
为开发版本启用权限。你可以检查它Settings.canDrawOverlays(this);
。这在开发版本中是必需的,因为必须在所有其他窗口之上显示原始开发错误。由于在API级别23中引入了新的权限系统,用户需要批准它。这可以通过将以下代码添加到onCreate()方法中的Activity文件中来实现。OVERLAY_PERMISSION_REQ_CODE是将负责将结果传递回活动的类的字段。
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);
}
}
最后,onActivityResult()
必须重写该方法(如下面的代码所示)以处理一致UX的权限Accepted或Denied。
@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...
}
}
}
}
最后在明确下index.android.js和mReactRootView.startReactApplication(mReactInstanceManager, "HelloRN", null)
和package.json及项目名字,到底那几个保持一致(我也是集成了5次以上,总结出来的,如果有不对请留言指出)
必须一样的:工程名字(RNHelloWorld)和AppRegistry.registerComponent('RNHelloWorld', () => HelloWorldApp);
以及protected String getMainComponentName()返回的名字
三者必须一样。
当你出现以下错误,基本就是这个原因了
运行应用
- 首先运行服务
在项目的根文件夹下,命令行运行如下命令,启动测试服务器(可以直接在Androidstudio的Termin中输入,但是注意当前所在位置)。
npm start
或者:
react-native start
- 接下来像开发安卓项目一样直接运行项目
效果(这里使用的上一篇的效果图和真实的只是title不一样)
有了上一篇的经验,这次我一次就完成了将RN嵌入原生项目,真顺畅
如果报错
或是
解决:在app的build.gradle 中添加
|
|
ndk {
abiFilters "armeabi-v7a", "x86"
}
}```
参考链接:
其实我已经在坑了爬了三天了,看了几十篇博客,以及一些问题解决的网页,下面就指出我觉得最有用的,和影响最深刻的
官方文档嵌入到现有原生应用
Android项目中集成React Native
React Native 学习笔记十二(嵌入原生应用 甚是坑啊)
印象最深刻就是:现有Android项目引入ReactNative--九步大法,因为是鸿洋大神推荐的所以也是我首选看的资料,我还结合了官网资料一起看,没想到就入坑了,作者文章的工程目录结构和我一样,但是在在填写本地仓库的路径却和官网一样(猜想:如果作者的项目能运行,再看看作者的目录图片应该是苹果,我用的Windows,可能系统不一样所以路径可能存在一点差异)
maven {
// All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
url "$rootDir/../node_modules/react-native/android"
}
这也就是我入坑的第一步了,原因我在文章第五步已经说明,以至于"一入坑难起来啊",当然说这个不是为了针对作者,只是给更多的人提个醒,以免再次入坑
喜欢请点赞,或是关注,后续将完善发布更多的文章,你的鼓励就是我的动力(程序员最大的动力莫过于同行的鼓励)