基于 Expo 的 React Native 消息推送
Expo 是 React Native 开发的一个神器,正如 Expo 官网上所说,Expo 之于 React Native 就像 Rails 之于 Ruby,它提供了很多超越原生 React Native API 的功能,包括二维码扫描、存储、内部浏览器等,甚至还可以使用 Expo 进行 APP 的打包,完全不需要使用 XCode 和 Android Studio。
而消息推送则是 APP 应用非常常见的一个功能,今天就来介绍一下基于 Expo 的 React Native 消息推送功能是如何开发的吧。
APP 的消息推送一般有两种形式,一种是本地消息,比如 APP 中有个定时执行的任务,完成后给用户发送一个”任务执行完成”的通知;另外一种是远程消息,比如说某个电商做活动,会向用户推送一些活动相关的消息。
本地和远程消息两者本质的区别就是:本地消息是由 APP 本身发送的,而远程消息是由 APP 的后端(服务端)发送的。
本地消息推送
本地消息不需要和服务端交互,相对比较简单,让我们先来看看 Expo 的本地消息是如何发送的。
消息对象
一般我们手机上收到的推送消息大概是下面这样子,有 APP 的 Icon、标题、摘要信息以及推送的时间。
所以我们需要先构造一个本地消息对象,它主要包含以下属性:
- title:字符串类型,必填属性,消息的标题,会显示在手机的通知栏上面
- body:字符串类型,必填属性,消息的摘要信息,会显示在手机的通知栏上面
- data:对象类型,可选属性,附加在消息上的一个数据对象,不会显示在通知栏上,但可在 APP 内部使用该对象。
1 | const localNotification = { |
消息发送
创建好了消息对象后,我们就可以来尝试将它发送,Expo 提供了两种发送方式:立即发送和定时发送。
立即发送
1 | import { Notifications } from 'expo'; |
调用这个方法后 APP 会马上发送一条消息,然后在手机通知栏上就可以看到。
定时发送
定时发送除了要求消息对象外,还需要时间调度的对象。
1 | import { Notifications } from 'expo'; |
上面的示例中会在 1 秒后发送消息,schedulingOptions
的有如下属性:
- time:可以是 Date 对象,也可以是时间毫秒数,表示什么时候开始发送消息
- repeat:字符串,可以填的值有
'minute'、'hour'、'day'、'week'、'month'、'year'
,表示是否重复发送消息
远程消息推送
远程消息的发送稍微复杂一些,需要搭建自己的后台服务,流程图如下:
- 手机通过后台服务提供的 API 进行设备登记
- 后台服务调用 Expo 后台服务的 API
- Expo 后台服务往所有登记过的设备上推送消息
下面我们来详细看下每一步的具体操作。
后台服务
我们需要搭建自己的后台服务来提供 API,API 要做的事情就是接收请求中的设备号并保存起来,下面我们用Node.js
来写个简单的 API 示例:
1 | // 使用 Set 来保存手机设备号,这样保证每个设备号只有一个 |
例子非常简单,这里提供了一个方法为POST
,url 为/users/push-token
的 API,请求中必须带有 token 参数。
登记设备
准备好了 API 之后,我们就可以在设备上调用 API 进行设备登记了。
Expo 在Notifications
模块中提供了相应的方法来让获取设备号,我们来看一下示例代码:
1 | import { Permissions, Notifications } from 'expo'; |
拿到设备号后,我们就可以将设备号发送到我们的后台服务了。
1 | const PUSH_ENDPOINT = 'https://your-server.com/users/push-token'; |
发送消息
最后一步是让 Expo 的后台服务将消息推送给登记过的所有设备,那我们要怎么发送请求给 Expo 的后台服务呢?
其实 Expo 提供了 sdk 包来让我们的后台服务可以与 Expo 的服务器进行通信,sdk 包支持多种语言,方便与各种 Web 服务集成,支持的语言包括Node.js
、Python
、Ruby
、PHP
、Golang
等,我们以Node.js
为例介绍一下我们的后台服务是如何与 Expo 后台服务进行通信的:
- 首先是要添加 Expo 的 sdk 包
1 | yarn add expo-server-sdk |
- 接着调用 Expo 的 API 进行消息推送,下面是示例代码,可以看注释理解相应的代码:
1 | import Expo from 'expo-server-sdk'; |
这样就完成了一次远程消息的推送。
消息接收
当消息发送到手机上的时候,APP 要如何进行消息接收呢?Expo 提供了一个消息监听器,不管是本地的还是远程的消息都可以监听到,我们来看一段简单的代码示例。
1 | import React from 'react'; |
notification 对象
在handleNotification
方法中我们会对接收消息进行处理,notification
就是接收的消息对象,它有如下属性:
- remote:
true
表示这个消息是远程消息,false
则是本地消息 - origin:这个属性有 2 个值——
selected
和received
。selected
表示是用户从通知栏上点击消息而接收到的,而received
则表示是 APP 在打开状态时接收到的。 - data:附加在消息上的 data 对象
EventSubscription 对象
调用Notifications.addListener
后返回的notificationSubscription
是一个EventSubscription
对象,它有以下属性和方法:
- remove():该方法可以用来取消已有的监听器
- origin:同
notification
对象的origin
属性 - remote:同
notification
对象的remote
属性 - data:同
notification
对象的data
属性
总结
消息推送是 APP 的常见需求,市面上也有不少解决方案,但 Expo 相对其他解决方案来说最大的优势就是无需与原生的模块打交道,比如其他消息推送方案可能需要对 android 的源文件进行修改,然后再对 ios 的源文件进行修改,而 Expo 则不需要关心这些,只要在 React Native 中写好代码就可以了。唯一的不足就是需要搭建自己的后台服务,但如果你的 APP 本身就带有后台服务的话,则 Expo 的消息推送方案是你的首要选择。