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

xiaoxiao2021-02-27  456

一、前言

搭建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 集成用到的常见命令

npm init // 编辑一个package.json 文件npm install –save react-native // 初始化一个 node_modules/curl -o .flowconfig https://raw.githubusercontent.com/facebook/react-native/master/.flowconfig // 拉取配置文件npm ls // 查看安装的模块 npm start // 启动模块 npm start –reset-cache //重启npm stop // 停止模块
转载请注明原文地址: https://www.6miu.com/read-607.html

最新回复(0)