- 1. 设置项目目录结构
- 首先创建一个空目录用于存放React Native项目 , 然后在其中创建一个android子目录 , 把你现有的Android项目拷贝到android子目录中 ;
- 2. 安装JavaScript依赖包
- 在项目根目录下创建一个名为package.json的空文本文件,然后填入以下内容:
{
"name": "MyReactNativeApp",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start"
},
"dependencies": {
"react": "16.0.0-alpha.6",
"react-native": "0.44.3"
}
}
- name 随意
- version字段没有太大意义(除非你要把你的项目发布到npm仓库)
- scripts中是用于启动packager服务的命令
- dependencies中的react和react-native的版本取决于你的具体需求(一般来说照着复制就行 )
- 然后在项目目录(根目录)中 命令行 (npm install) 安装React和ReactNative模块...等吧 需要点儿时间
- 3. 配置AndroidStudio 将ReactNative添加到Android项目中
- 坑① : 最小支持版本为 API 16
- 坑② : com.android.support:appcompat-v7 的版本为 23
- 配置Maven
// 打个注释吧 这个是在app中的build.gradle文件中的
dependencies {
...
// 此处用native:+ 就没问题,有强迫症的可以改成自己电脑上的版本
compile "com.facebook.react:react-native:+" // From node_modules.
}
// 这个是在project中的build.gradle文件中的
allprojects {
repositories {
...
maven {
// All of React Native (JS, Android binaries) is installed from npm
// 只要npm install执行完成了 下面这个目录是真实存在的 不存在的话Gradle构建会失败
url "$rootDir/../node_modules/react-native/android"
}
}
...
}
- 权限申请 :
<!--React-Native 需要网络权限-->
<
uses-permission
android
:name=
"android.permission.INTERNET"
/>
<!--悬浮窗权限-->
<
uses-permission
android
:name=
"android.permission.SYSTEM_ALERT_WINDOW"
/>
- 如果需要访问 DevSettingsActivity 界面(即开发者菜单),则还需要在 AndroidManifest.xml 中声明:(此处直接复制比较好,打DevSett联想不出来)
<!--React-Native 开发者菜单-->
<
activity
android
:name=
"com.facebook.react.devsupport.DevSettingsActivity"
/>
- 开发者菜单一般仅用于在开发时从Packager服务器刷新JavaScript代码,所以在正式发布时你可以去掉这一权限。
- 4. 编写ReactNative代码
- 根目录下新建index.js (index.js是React Native应用在Android上的入口文件 而且它是不可或缺的)
- 首先是 index.js 代码
// 引入React库
import React from 'react';
// 引入文件NewClass
import NewClass from './NewClass';
// 引入AppRegistry
import {
AppRegistry
} from 'react-native';
// 设置首页是哪一个类
AppRegistry.registerComponent('MyReactNativeApp', () => NewClass);
- 然后是NewClass代码(中文网中的Text输入Demo)
import React, { Component } from 'react';
import {Text,TextInput,View} from 'react-native';
class TextInputDemo extends Component{
constructor(props){
super(props);
// 在这里声明State
this.state = {text : "",stateTest:""};
}
render(){
return(
<View style={{padding:10}}>
<TextInput style={{height:40}} placeholder="Please Input XXXX" onChangeText={(text)=>this.setState({text})}/>
<Text style={{padding :10,fontSize:42}}>
{this.state.text}
</Text>
</View>
);
}
}
export default class NewClass extends Component<Props> {
render() {
return (
<TextInputDemo/>
);
}
}
- 5. 6.0权限申请
- 某个Activity中动态申请悬浮窗权限 申请代码如下(中文网示例)
private static final int OVERLAY_PERMISSION_REQ_CODE = 10001;
/**
* 请求弹窗权限
*/
private void
initPermission() {
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
)) {
//
TODO
}
}
}
}
- 6. 核心代码 ReactRootView ReactInstanceManager
/**
*
@作者
RedWolfChao
*
@时间
2018/2/22 16:38
*
@描述
代码没有很好的弄6.0权限处理 所以在没有授权的情况下, APP会崩溃
*/
public class
MainActivity
extends
AppCompatActivity
implements
DefaultHardwareBackBtnHandler {
private static final int
OVERLAY_PERMISSION_REQ_CODE
=
10001
;
// ReactNative核心类
private
ReactRootView
mReactRootView
;
// ...
private
ReactInstanceManager
mReactInstanceManager
;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
initPermission();
initReactNative();
}
/**
* 初始化ReactNative
*/
private void
initReactNative() {
mReactRootView
=
new
ReactRootView(
this
);
mReactInstanceManager
= ReactInstanceManager.
builder
()
.setApplication(getApplication())
// 此处中文网中有点不一样 中文网中的文档感觉有点儿过时
.setBundleAssetName(
"index.bundle"
)
.setJSMainModuleName(
"index"
)
.addPackage(
new
MainReactPackage())
.setUseDeveloperSupport(BuildConfig.
DEBUG
)
.setInitialLifecycleState(LifecycleState.
RESUMED
)
.build();
// 注意这里的MyReactNativeApp 必须对应 "index.js"中的"AppRegistry.registerComponent()"的第一个参数
mReactRootView
.startReactApplication(
mReactInstanceManager
,
"MyReactNativeApp"
,
null
);
setContentView(
mReactRootView
);
}
@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
)) {
//
TODO
}
}
}
}
/**
* 请求弹窗权限
*/
private void
initPermission() {
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
public void
invokeDefaultOnBackPressed() {
super
.onBackPressed();
}
@Override
public void
onBackPressed() {
if
(
mReactInstanceManager
!=
null
) {
mReactInstanceManager
.onBackPressed();
}
else
{
super
.onBackPressed();
}
}
@Override
public boolean
onKeyUp(
int
keyCode, KeyEvent event) {
if
(keyCode == KeyEvent.
KEYCODE_MENU
&&
mReactInstanceManager
!=
null
) {
mReactInstanceManager
.showDevOptionsDialog();
return true
;
}
return super
.onKeyUp(keyCode, event);
}
@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
);
}
}
}
- 配置Manifest.xml
<
activity
android
:name=
".MainActivity"
>
<
intent-filter
>
<
action
android
:name=
"android.intent.action.MAIN"
/>
<
category
android
:name=
"android.intent.category.LAUNCHER"
/>
</
intent-filter
>
</
activity
>
- 7. 起 ReactNative 服务 在根目录命令行
npm start
- 8. 运行即可 , 可以直接run app(AS的三角符号运行) , 也可以用gradlew installDebug命令行 (中文网说是直接运行会崩溃..我没遇见过)
- 9. 打包 (未测试)
- 你也可以使用Android Studio来打release包!其步骤基本和原生应用一样,只是在每次编译打包之前需要先执行js文件的打包(即生成离线的jsbundle文件)。具体的js打包命令如下:
$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/
- 注意把上述命令中的路径替换为你实际项目的路径。如果assets目录不存在,则需要提前自己创建一个。
- 然后在Android Studio中正常生成release版本即可!