文档章节

你不可不知的 React Native 混合用法(Android 篇)

极光推送
 极光推送
发布于 2017/05/08 17:45
字数 1946
阅读 157
收藏 11
点赞 0
评论 0

前言

当前 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 Name 替换成自己的
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 篇)

知乎专栏:极光日报

© 著作权归作者所有

共有 人打赏支持
极光推送
粉丝 40
博文 115
码字总数 125095
作品 1
深圳
个人站长
React Native 调试问题

使用React Native Tool在VSCODE中进行断点调试时点击DEBUG Android,弹出 Could not debug. Unknown error: not all success patterns were matched. It means that "react-native run-andro......

bill1987610
05/31
0
0
React Native 调试问题

使用React Native Tool在VSCODE中进行断点调试时点击DEBUG Android,弹出 Could not debug. Unknown error: not all success patterns were matched. It means that "react-native run-andro......

bill1987610
05/31
0
0
React-Native 之 环境配置和简单使用

前言 学习本系列内容需要具备一定 HTML 开发基础,没有基础的朋友可以先转至 HTML快速入门(一) 学习 本人接触 React Native 时间并不是特别长,所以对其中的内容和性质了解可能会有所偏差,在...

postdep
05/01
0
0
JavaScript(React Native、Node.js等)移动、服务端通吃的全栈语言

作者:李宁老师 东北大学计算机专业硕士。曾任沈阳东软股份项目经理。51CTO学院签约讲师。从事软件研究和开发超过20年。长久以来一直从事Java、Android、iOS、C++、Swift、Objective-C以及跨...

androidguy
06/29
0
0
继 Airbnb 之后,Udacity 也宣布弃用 React Native!

Udacity 移动端团队最近删除了 App 中使用 React Native 语言开发的相关功能。 我们收到大量有关我们用法或 React Native 的问题以及为什么我们停止投入资源和精力在 RN 上。 在这篇文章中,...

亦枫
07/12
0
0
React Native 轻松集成统计功能(Android 篇)

关于推送的集成请参考这篇文章,本篇文章将引导你集成统计功能,只需要简单的三个步骤就可以集成统计功能。 第一步 安装 在你的项目路径下执行命令: 执行完上述命令后,使用 Android Studio...

极光推送
2017/11/06
0
0
如何解读 Airbnb 弃用 React Native

最近的技术圈尤为热闹,Google 发布了首个 Flutter 预览版、Vue.js 在 GitHub 上的 star 数量超过了 React.js,而如今全球著名的民宿预订平台 Airbnb 突然宣布要弃 React Native 坑而逃,回归...

程序师
06/30
0
0
从Android到React Native开发(四、打包流程解析和发布为Maven库)

1、从Android到React Native开发(一、入门) 2、从Android到React Native开发(二、通信与模块实现) 3、从Android到React Native开发(三、自定义原生控件支持)  作为失踪人口,本篇是对...

恋猫月亮
06/13
0
0
RN文件上传(仅ios),下载,创建,删除等文件操作(兼容IOS和Android)--react-native-fs

https://github.com/itinance/react-native-fs //GitHub地址 具体用法参照GitHub 一.下载依赖 npm install react-native-fs --save 二.链接原生库 链接后重新编译,如果android还是报错用AS打...

Chason-洪
2017/10/26
0
0
Dore 混合应用框架 —— 基于 React Native 的混合应用迁移方案

上个周末,在写我的年终总结,有了一点新灵感 —— 其实是 xxx 的原因。 在半年前的那篇《我们是如何将 Cordova 应用嵌入到 React Native 中》中,我介绍了如何将 Cordova 嵌入 React Native...

Phodal
2017/12/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

高效编写Dockerfile的几条准则

概述 Dockerfile 是专门用来进行自动化构建镜像的编排文件(就像Jenkins 2.0时代的Jenkinsfile是对Jenkins的Job和Stage的编排一样),我们可以通过 docker build 命令来自动化地从 Dockerfi...

小致dad
58分钟前
0
0
SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
9
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
7
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
198
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部