你不可不知的 React Native 混合用法(Android 篇)
2017-05-08 00:00
447 查看
前言
当前 React Native 虽说版本更新比较快,各种组件也提供的很全面了,但是在某些情况下,混合开发的方式才会快速缩短开发周期,原因无非就是原生平台的“底蕴”无疑更深,拥有众多且类型丰富的第三方支持库。很多情况下,运用这些库可以避免苦逼的重复劳动。接下来我们以 jpush-react-native 插件为例来看看在 React Native 中如何使用原生的第三方库。开始
在开始之前,你必须安装以下软件:npm 命令行工具,react-native 命令行工具, Android Studio。jpush-react-native 是极光推送提供的 React Native 版本插件,可以让我们快速集成推送功能。实际上这个插件就是一个混合应用,使用他们自己的原生 SDK,并且封装了一些接口,让开发者可以在 JS 和原生平台之间互相调用。接下来我们只需要三个步骤就可以完成绝大多数原生库在 React Native 中的应用。先明确两个概念,在 Android Studio 中一个项目往往会包含很多模块(Module),项目中的 build.gradle 配置一般对所有 module 生效。而 Module 中的 build.gradle 则配置了该 Module 所需的依赖或者任务等等。
第一步——安装
在命令行中进入 React Native 项目,然后使用如下两个命令即可完成 jpush-react-native 插件的安装:npm install jpush-react-native --save rnpm link jpush-react-native
jpush-react-native 发布到 npm 了,所以使用命令行可以轻松安装。
然而有很多第三方库可能需要原生的安装方式。比如提供 jar 包或者 aar 包的方式在 Android 中很常见,也有可能以 maven 依赖的方式安装。如果是以上方式安装需要做一些调整:
jar 包或者 aar 包的方式:
i. 将依赖包复制到 module 的 libs 文件夹下(如果没有则需要手动创建)
ii. 在 build.gradle 中添加:
android { ... sourceSets { main { jniLibs.srcDirs = ['libs'] } } ... } ... dependencies { compile fileTree(dir: "libs", include: ["*.jar"]) }
以 maven 依赖的方式:
i. 在项目的 build.gradle 中增加:
allprojects { repositories { ... mavenCentral() maven { url "https://oss.sonatype.org/content/repositories/snapshots/" } } }
ii. 在 module 的 build.gradle 中添加:
dependencies { ... compile 'xxx-SNAPSHOT' }
其中的 xxx 指代 groupId、artifactId 以及版本号(以 : 分隔),一般都会由提供方给出。比如 ActiveAndroid:
compile 'com.michaelpardo:activeandroid:3.1.0-SNAPSHOT'
第二步——适配(配置)
这一步因第三方库而异,其实大多都是大同小异,有的库甚至不需要配置直接可以“搭建桥梁”使用。jpush-react-native 还是要配置一下的首先在命令行中运行脚本:
// 将 AppKey 和 Module Na 7fe0 me 替换成自己的 npm run configureJPush [AppKey] [Module Name]
配置 AndroidManifest
<meta-data android:name="JPUSH_CHANNEL" android:value="${APP_CHANNEL}"/> <meta-data android:name="JPUSH_APPKEY" android:value="${JPUSH_APPKEY}"/>
将以上代码复制到你 Module 的 AndroidManifest 下即可。
配置 build.gradle
打开与 AndroidManifest 同级的 build.gradle 文件,做以下改动:
android { ... defaultConfig { // 换成自己的包名 applicationId "com.xxx" ... manifestPlaceholders = [ JPUSH_APPKEY: "xxx", //在此替换你的AppKey,极光官网注册应用获得 APP_CHANNEL: "developer-default" //应用渠道号 ] } }
到此配置完成。
第三步 搭建桥梁
这一步是最后也是最核心的一步。“搭建桥梁”主要是在 Native 侧提供一些 @ReactMethod 标签的方法,或者在 Native 中处理后回调到 JS,说白了就是要使得 JS 和 Native 可以相互调用。这也是混合开发的优势所在,原生平台提供的库,我们只需要搭建一下桥梁,就可以拿来使用。只要稍微写一点原生的代码,可以省去我们绝大部分工作。许多刚接触 React Native 的人不知道如何在 Native 中打开 JS 的界面(众所周知,JS 的界面由一个个 Component 组成,有自己的路由系统)后面我会写一个简单例子,用 Native 的方式声明注册界面(在 Android 中即为 Activity),然后用 JS 渲染界面,这个问题就迎刃而解了。接下来还是先看看 jpush-react-native 的例子。首先在你的 Module 下创建一个 ManiActivity 以及 MainApplication 类。RN 0.29 后,需要在 MainApplication 中添加原生模块。
MainActivity.java
public class MainActivity extends ReactActivity implements DefaultHardwareBackBtnHandler { @Override protected String getMainComponentName() { // 这里返回的名字要与 JS 侧注册的 Component 名字一致 return "PushDemoApp"; } @Override protected void onPause() { super.onPause(); JPushInterface.onPause(this); } @Override protected void onResume() { super.onResume(); JPushInterface.onResume(this); } }
接下来需要在 MainApplication 中增加原生模块
MainApplication.java
public class MainApplication extends Application implements ReactApplication { private boolean SHUTDOWN_TOAST = false; private boolean SHUTDOWN_LOG = false; private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { @Override protected boolean getUseDeveloperSupport() { return BuildConfig.DEBUG; } @Override protected List<ReactPackage> getPackages() { return Arrays.<ReactPackage>asList( new MainReactPackage(), new JPushPackage(SHUTDOWN_TOAST, SHUTDOWN_LOG) ); } }; @Override public ReactNativeHost getReactNativeHost() { return mReactNativeHost; } }
这样就完成了。在 Android Studio 中 sync 一下,可以看到 jpush-react-native 作为 Library Module 导进来了。打开 JPushModule 类,看到其中的 onReceive 方法,通知的处理都在这一块。在极光推送后台发送通知(也可以使用 服务端 sdk)后,客户端 sdk 收到通知后会回调到 onReceive 方法,在 onReceive 中可以做一些定制化的操作。比如收到通知后,点击通知打开特定的界面:
public static class JPushReceiver extends BroadcastReceiver { public JPushReceiver() { HeadlessJsTaskService.acquireWakeLockNow(mRAC); } @Override public void onReceive(Context context, Intent data) { ... } else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(data.getAction())) { Logger.d(TAG, "用户点击打开了通知"); Intent intent = new Intent(); intent.setClassName(context.getPackageName(), context.getPackageName() + ".MainActivity"); intent.putExtras(bundle); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP); // 如果需要跳转到指定的界面,那么需要同时启动 MainActivity 及指定界面(SecondActivity): // If you need to open appointed Activity, you need to start MainActivity and // appointed Activity at the same time. Intent detailIntent = new Intent(); detailIntent.setClassName(context.getPackageName(), context.getPackageName() + ".SecondActivity"); detailIntent.putExtras(bundle); Intent[] intents = {intent, detailIntent}; // 同时启动 MainActivity 以及 SecondActivity context.startActivities(intents); // 或者回调 JS 的某个方法 } } ... @ReactMethod public void finishActivity() { Activity activity = getCurrentActivity(); if (activity != null) { activity.finish(); } }
上面的例子中,我们在收到点击通知的事件时,打开一个特定的界面。这个界面在 Native 中创建(这样做的好处在于还可以实现一些特定的需求,比如收到通知后,如果存在 SecondActivity,则让位于 SecondActivity 之上的界面全部弹出,如果不存在,则创建等等之类的需求),但是还是用 JS 的代码来渲染界面,这对于熟悉 JS 的同学来说,再好不过。要做到这一点,首先我们创建一个 SecondActivity (与 MainActivity 同级)类:
SecondActivity.java
public class SecondActivity extends ReactActivity { @Override protected String getMainComponentName() { // 注意这个名字与 JS 对应的 Component 中 // AppRegistry.registerComponent 方法的第一个参数相同 return "SecondActivity"; } }
然后在 AndroidManifest 注册 SecondActivity:
AndroidManifest
<activity android:name=".SecondActivity" />
在 React Native 项目下新建一个文件夹 react-native-android,专门用来存放 js 相关的文件。新建 second.js 文件:
second.js
'use strict'; import React from 'react'; import ReactNative from 'react-native'; const { AppRegistry, View, Text, TouchableHighlight, StyleSheet, NativeModules, } = ReactNative; var JPushModule = NativeModules.JPushModule; export default class second extends React.Component { constructor(props) { super(props); } onBackPress = () => { let navigator = this.props.navigator; if (navigator != undefined) { this.props.navigator.pop(); } else { console.log("finishing second activity"); JPushModule.finishActivity(); } } onButtonPress = () => { console.log("will jump to setting page"); let navigator = this.props.navigator; if (navigator != undefined) { this.props.navigator.push({ name: "setActivity" }); } else { } } render() { return ( <View> <TouchableHighlight style={styles.backBtn} underlayColor = '#e4083f' activeOpacity = {0.5} onPress = {this.onBackPress}> <Text> Back </Text> </TouchableHighlight> <Text style={styles.welcome}> Welcome ! </Text> <TouchableHighlight underlayColor = '#e4083f' activeOpacity = {0.5} style = {styles.btnStyle} onPress = {this.onButtonPress}> <Text style={styles.btnTextStyle}> Jump To Setting page! </Text> </TouchableHighlight> </View> ); } } var styles = StyleSheet.create({ backBtn: { padding: 10, marginTop: 10, marginLeft: 10, borderWidth: 1, borderColor: '#3e83d7', backgroundColor: '#3e83d7', borderRadius: 8, alignSelf: 'flex-start' }, welcome: { textAlign: 'center', margin: 10, }, btnStyle: { marginTop: 10, borderWidth: 1, borderColor: '#3e83d7', borderRadius: 8, backgroundColor: '#3e83d7', alignSelf: 'center', justifyContent: 'center' }, btnTextStyle: { textAlign: 'center', fontSize: 25, color: '#ffffff' }, }); AppRegistry.registerComponent('SecondActivity', () => second);
就这样,大功告成!接下来可以在 index.android.js 中注册路由,使得在 JS 中也可以跳转到这个界面。源码请戳这里
总结
以上就是在 React Native 中以混合的方式开发应用的大概过程。用这种方式可以马上使用丰富的原生平台第三方库,只是在 Native 部分需要写些代码,但是花费的代价远远小于自己用 JS 的方式再实现一遍。作者:KenChoi - 极光
原文:你不可不知的 React Native 混合用法(Android 篇)
知乎专栏:极光日报
相关文章推荐
- 你不可不知的 React Native 混合用法(Android 篇)
- 你不可不知的 React Native 混合用法(Android 篇)
- 《React Native 精解与实战》书籍连载「Android 平台与 React Native 混合开发」
- react-native + androidstudio 混合开发 - 1(基础配置)
- Mac android原生工程中潜入react-native混合开发项目搭建
- react native与Android混合开发
- (React-Native 学习之八) Rn混合开发之--Android原生代码 和 ReactNative 通信
- react native 中DataPickerAndroid的用法和一些注意注意点
- android ReactNative混合开发之最新教程
- android开发新手不可不知的10大严重错误
- Eclipse不可不知的用法之四:配置服务器与项目的新建运行
- react-native试玩(34)-配置Android开发环境
- Start React Native In Android
- ReactNative Android 研究
- react-native —— 在Windows下搭建React Native Android开发环境
- XX程序媛学习笔记--Cordova(PhoneGap)Android Native混合开发值传递
- [图解教程]Eclipse不可不知的用法之一:自动生成Getter、Setter和构造方法
- [图解教程]Eclipse不可不知的用法之一:自动生成Getter、Setter和构造方法