-
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版本即可!