一步一步在 Windows下搭建 React Native Android 开发环境

本文详细介绍了如何在Windows操作系统下逐步搭建React Native Android开发环境,包括创建Android项目、引入React-Native、解决编译版本问题、配置运行调试以及应对各种编译运行中遇到的问题。通过跟随教程,开发者可以成功建立RN开发环境并进行真机测试。

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

一、前言

搭建RN 的环境过程中可能会遇到比较多的坑,要有一个心理准备。我昨天搭建环境的时候,遇到很多的问题,一个问题一个问题的google,到昨天晚上遇到的最后一个问题,始终解决不了,今天又折腾了一天,才弄好。

二、什么是 React Native?

官方解释:

React Native使你能够在Javascript和React的基础上获得完全一致的开发体验,构建世界一流的原生APP。

React Native着力于提高多平台开发的开发效率 —— 仅需学习一次,编写任何平台。(Learn once, write anywhere)

Facebook已经在多项产品中使用了React Native,并且将持续地投入建设React Native。

大白话:

就是,老板招聘一个会RN 的人,就可以抵得上分别招Android、IOS、前端各一个人,然后就没有然后呢。

作为一个技术人才,技术的知识广度和深度始终是不懈的追求。技术总是超前发展的,你不学习,你不进步,就会慢慢被社会淘汰。

三、开始搭建

1、新建一个 Android 项目

项目名称:RnTest

2、引入React-Native

在你的app目录下的build.gradle加入react-native依赖,我加入的是最新版本的:

compile "com.facebook.react:react-native:+"

然后在AndroidManifest.xml加入访问网络权限,当然一般已经项目都有这个权限,如果有这一步可以忽略:

<uses-permission android:name="android.permission.INTERNET" />

为了让项目支持调试RN,需要在AndroidManifest.xml里面加入RN的DevSettingsActivity,如下:

<activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

这样真机晃动手机或者点击Menu菜单就会打开相关的调试页面,如图下所示:

这里写图片描述

这里部署完后,还有一个坑,就是React-Native对编译版本和最小编译版本都有要求,它需要app的build.gradle文件的compileSdkVersion为23,minSdkVersion为16,因为我们项目要求最低版本为15甚至更低,这里需要在app的AndroidManifest.xml加入:

<uses-sdk tools:overrideLibrary="com.facebook.react" />

3、实现方式1:引用 ReactRootView

新建一个RnActivity.java:

import com.facebook.react.common.LifecycleState;
import com.facebook.react.ReactInstanceManager;
import com.facebook.react.ReactRootView;
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler;
import com.facebook.react.shell.MainReactPackage;

public class RnActivity extends AppCompatActivity implements DefaultHardwareBackBtnHandler{

    private ReactRootView mReactRootView;
    private ReactInstanceManager mReactInstanceManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_rn);

        mReactRootView = (ReactRootView)findViewById(R.id.react_rootview);

        findViewById(R.id.back_button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RnActivity.this.finish();
            }
        });

        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setBundleAssetName("index.android.bundle")
                .setJSMainModuleName("index.android")
                .addPackage(new MainReactPackage())
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED).build();

        mReactRootView.startReactApplication(mReactInstanceManager, "RnTest", null);
    }

    @Override
    public void invokeDefaultOnBackPressed() {
        super.onBackPressed();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if(mReactInstanceManager != null){
            //mReactInstanceManager.onPause();
            mReactInstanceManager.onHostPause(this);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        if(mReactInstanceManager != null){
            //mReactInstanceManager.onResume(this, this);
            mReactInstanceManager.onHostResume(this, this);
        }
    }

    @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);
    }
}

因为ReactRootView本身就是一个FrameLayout,我没有按官网来直接new一个,而是直接把它放到布局activity_my_react.xml里面了,布局文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:orientation="vertical"
    tools:context="com.troy.rntest.RnActivity">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="我是本地控件TextView"/>

    <Button
        android:id="@+id/back_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="返回"
        android:textColor="@android:color/white"
        android:background="@color/colorPrimaryDark"/>

    <com.facebook.react.ReactRootView
        android:id="@+id/react_rootview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="10dp">

    </com.facebook.react.ReactRootView>

</LinearLayout>

可以看到ReactRootView 实际是FrameLayout 的子类:

public class ReactRootView extends SizeMonitoringFrameLayout implements RootView {}

public class SizeMonitoringFrameLayout extends FrameLayout {}

4、JS代码如下

在项目目录下新建一个 index.android.js 文件:

import React from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  NativeModules,
  ToastAndroid
} from 'react-native';

class RnTest extends React.Component {
  render() {
    return (
      <View style={styles.container}>
        <Text> 测试ReactNative </Text>
      </View>
    )
  }
}

var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
  },
  hello: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
});

AppRegistry.registerComponent('RnTest', () => RnTest);

注意细节,部分版本在调用方法时需要加React.,比如

注册时:

React.AppRegistry.registerComponent('RnTest', () => RnTest);

引用样式时:

React.StyleSheet.create

5、添加 package.json

代码如下:

{
  "name": "RnTest",
  "version": "1.0.0",
  "description": "demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node node_modules/react-native/local-cli/cli.js start"
  },
  "author": "troy",
  "license": "ISC",
  "dependencies": {
    "react": "^15.4.2",
    "react-native": "^0.42.3"
  }
}

6、实现方式2:App 实现 ReactApplication接口

项目Application 实现ReactApplication 接口:

public class MyApp extends Application implements ReactApplication{

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
    }

    @Override
    public ReactNativeHost getReactNativeHost() {
        return new ReactNativeHost(this) {
            @Override
            public boolean getUseDeveloperSupport() {
                return true;//返回true
            }

            @Override
            protected List<ReactPackage> getPackages() {
                return Arrays.asList((ReactPackage)new MainReactPackage());//返回MainReactPackage;
            }
        };
    }
}

新建一个Activity:

public class SecondActivity extends ReactActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //注释原来的布局文件
//        setContentView(R.layout.activity_second);
    }

    @Override
    protected String getMainComponentName() {
    //直接加载 RN 组件RnTest:
        return "RnTest";
    }
 }

四、项目配置运行调试

4.1、在RnTest 项目目录下执行如下命令

$ npm init
$ npm install --save react-native
$ curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig

npm init命令可以不用执行,它如要用来生成package.json文件,前面我们已经创建过了,npm install –save react-native执行后会在目录下面生成node_modules文件夹并添加react-native的npm依赖。

首先启动RN的npm本地服务:

$ npm start

启动后如下:

这里写图片描述

在浏览器中打开:

http://localhost:8081/index.android.bundle?platform=android

出现前端代码:

(function(global) {

global.__DEV__ = true;

global.__BUNDLE_START_TIME__ = Date.now();
})(typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : this);
(function(global) {

'use strict';

global.require = _require;
global.__d = define;

表示启动成功。

4.2、真机测试

为了真机测试,需要设置adb 反转,执行命令如下:

/d/android-sdk-windows/platform-tools/adb.exe reverse tcp:8081 tcp:8081

结果,在真机上运行ok。Hello World 的截图就不放了。

4.3、设置maven 本地依赖

在项目的gradle 文件中加入:

allprojects {
    repositories {
        maven {
            // All of React Native (JS, Android binaries) is installed from npm
            url "$rootDir/node_modules/react-native/android"
        }
        jcenter()


    }
}

五、编译/运行遇到的各种问题及解决办法

5.1、appcompat-v7:23 版本问题

问题描述:


Caused by: java.lang.IllegalAccessError: tried to access method android.support.v4.net.ConnectivityManagerCompat.:(Lcom/facebook/react/bridge/ReactApplicationContext;)V from class com.facebook.react.modules.netinfo.NetInfoModule

我的项目的appcompat的版本是23.2.1,改成23.0.1就好了。

compile 'com.android.support:appcompat-v7:23.0.1'

5.2、添加NDK 支持

问题描述:

Caused by: java.lang.UnsatisfiedLinkError: could find DSO to load: libreactnativejni.so

解决办法:

在build.gradle增加对ndk 的支持:

defaultConfig {  
        applicationId "react.plus.com.android_react"  
        minSdkVersion 22  
        targetSdkVersion 23  
        versionCode 1  
        versionName "1.0"  
        ndk {  
            abiFilters "armeabi-v7a", "x86"  
        }  
    } 

同时在项目的 gradle.properties 文件中申明:

android.useDeprecatedNdk=true

5.3、sdk 版本问题

问题描述:

Caused by: java.lang.IllegalAccessError: Method 'void android.support.v4.net.ConnectivityManagerCompat.<init>()' is inaccessible to class 'com.facebook.react.modules.netinfo.NetInfoModule' (declaration of 'com.facebook.react.modules.netinfo.NetInfoModule' appears in /data/app/com.wuage.steel-1/base.apk:classes20.dex)

将sdk 版本改为24 之后便ok。

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.2"

    defaultConfig {
        applicationId "com.troy.rntest"
        minSdkVersion 14
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"

        ndk {
            abiFilters "armeabi","armeabi-v7a"

六、RN 集成用到的常见命令

  1. npm init // 编辑一个package.json 文件
  2. npm install –save react-native // 初始化一个 node_modules/
  3. curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig // 拉取配置文件
  4. npm ls // 查看安装的模块
  5. npm start // 启动模块
  6. npm start –reset-cache //重启
  7. npm stop // 停止模块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值