ReactNative与Android 集成踩坑

本文介绍了如何将ReactNative(RN)集成到Android项目中,包括设置项目目录结构,安装JavaScript依赖,配置Android Studio,处理API版本和库版本问题,编写ReactNative代码,申请权限,配置核心代码,启动服务,以及打包流程。在集成过程中,提到了一些常见的坑点,如最小API版本要求,权限申请等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值