博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用Leancloud实现React Native App的消息推送(Push Notification)- Android篇
阅读量:5904 次
发布时间:2019-06-19

本文共 14274 字,大约阅读时间需要 47 分钟。

前言

在 中我们详细讲解了用Leancloud实现iOS消息推送的流程,今天本文将继续讲解实现Android的消息推送。

接入Leancloud

在接入Leancloud之前,还是推荐先阅读Leancloud官方的 。

安装Leancloud SDK

SDK有多种安装方式,详情请参考。我选择用Gradle安装,先在根目录下的build.gradle中添加Leancloud的maven仓库地址:

buildscript {    repositories {        jcenter()        maven {            url 'https://maven.google.com/'            name 'Google'        }        maven {            url "http://mvn.leancloud.cn/nexus/content/repositories/public"        }    }    dependencies {        classpath 'com.android.tools.build:gradle:2.3.3'    }}allprojects {    repositories {        mavenLocal()        jcenter()        maven {            url "$rootDir/../node_modules/react-native/android"        }        maven {            url 'https://maven.google.com/'            name 'Google'        }        maven {            url "http://mvn.leancloud.cn/nexus/content/repositories/public"        }    }}

然后打开 app 目录下的 build.gradle 进行如下配置:

android {    //为了解决部分第三方库重复打包了META-INF的问题    packagingOptions{        exclude 'META-INF/LICENSE.txt'        exclude 'META-INF/NOTICE.txt'    }    lintOptions {        abortOnError false    }    ...}...dependencies {    ...        // LeanCloud 基础包    compile ('cn.leancloud.android:avoscloud-sdk:v4.6.4')    // 推送与实时聊天需要的包    compile ('cn.leancloud.android:avoscloud-push:v4.6.4@aar'){transitive = true}}

初始化Leancloud

我们需要在App创建后用Leancloud的AppId,AppKey进行初始化,修改MainApplication如下:

@Override  public void onCreate() {    super.onCreate();    ...    //初始化leancloud    AVOSCloud.initialize(this,"ppdriT1clcnRoda0okCPaB48-gzGzoHsz","Qzarq5cMdWzAMjwDW4umWpBL");  }

接下来,在AndroidManifest.xml中配置Leancloud SDK所需的权限以及消息推送所需的service和receiver:

...
...

到此,Leancloud SDK的接入完成,我们需要测试一下SDK能不能正常使用。我们在MainActivity.javaonCreate方法中添加代码看能不能保存数据到Leancloud数据库:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    ...    // 测试 SDK 是否正常工作的代码    AVObject testObject = new AVObject("TestObject");    testObject.put("words","Hello World!");    testObject.saveInBackground(new SaveCallback() {        @Override        public void done(AVException e) {            if(e == null){                Log.d("saved","success!");            }        }    });    ...}

启动App,前往Leancloud控制台,查看数据库中是否多了一条TestObject的记录,如果有说明Leancloud SDK接入成功:

image

保存Installation

和iOS一样,Android也需要保存installation才能让Leancloud确定推送到哪些设备。但是比较坑的是:Leancloud官方提供的 只能正确保存iOS设备的installation。 因此我们只能使用Android的SDK保存installation,而且我们最好把这个方法封装成一个native模块暴露给js调用,以方便在保存成功或失败后执行相应操作。

com.leancloudpushdemo文件夹中创建PushModule.javaPushDemo继承于ReactContextBaseJavaModule并实现ActivityEventListener接口,添加如下代码:

package com.leancloudpushdemo;import android.app.Activity;import android.content.Intent;import com.avos.avoscloud.AVException;import com.avos.avoscloud.AVInstallation;import com.avos.avoscloud.SaveCallback;import com.facebook.react.bridge.ActivityEventListener;import com.facebook.react.bridge.Callback;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.bridge.ReactContextBaseJavaModule;import com.facebook.react.bridge.ReactMethod;public class PushModule extends ReactContextBaseJavaModule implements ActivityEventListener {    public PushModule(ReactApplicationContext reactContext) {        super(reactContext);    }        @Override    public String getName() {        return "androidPushModule";    }        @Override    public void onNewIntent(Intent intent) {}    @Override    public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {}    /**     * 保存installation     */    @ReactMethod    public void saveInstaillation(final Callback resultCallback) {        AVInstallation.getCurrentInstallation().saveInBackground(new SaveCallback() {            public void done(AVException e) {                if (e == null) {                    // 保存成功                    String installationId = AVInstallation.getCurrentInstallation().getInstallationId();                    resultCallback.invoke(installationId);                } else {                    resultCallback.invoke();                }            }        });    }}

接着在同一目录下面添加PushPackage.java用于注册PushModule模块,代码如下:

package com.leancloudpushdemo;import com.facebook.react.ReactPackage;import com.facebook.react.bridge.NativeModule;import com.facebook.react.bridge.ReactApplicationContext;import com.facebook.react.uimanager.ViewManager;import java.util.ArrayList;import java.util.Collections;import java.util.List;public class PushPackage implements ReactPackage {    @Override    public List
createNativeModules(ReactApplicationContext reactContext) { List
modules = new ArrayList<>(); modules.add(new PushModule(reactContext)); return modules; } @Override public List
createViewManagers(ReactApplicationContext reactContext) { return Collections.emptyList(); }}

然后,在MainApplication.java中的getPackages方法中增加PushPackage

@Overrideprotected List
getPackages() { return Arrays.
asList( ... new PushPackage() );}

接着,在我们的PushService.js中引入PushModule并保存installation:

...import { NativeModules } from 'react-native';const AndroidPush = NativeModules.androidPushModule;...class PushService {        ...    //Android    _an_initPush = () => {        this._an_saveInstallation();    }    _an_saveInstallation = () => {        AndroidPush.saveInstaillation((installationId) => {            if (installationId) {                console.log('Android installation 保存成功!');            }        })    }    ...}

最后,在App.js中执行Android的初始化:

componentDidMount() {    if (Platform.OS === 'ios') {        PushService._iOS_initPush();    } else {        PushService._an_initPush();    }    MessageBarManager.registerMessageBar(this.refs.alert);}

重启App,前往Leancloud控制台中查看数据库中是否多了一条installation记录,如果有说明保存成功:

image

如果确认代码没问题,但是还是保存不成功,我建议:

  1. 重启Android Studio
  2. 重启React Native Packager
  3. 重启电脑、手机。。
  4. 如果还有问题,欢迎咨询我

实现系统推送

启动推送服务

首先调用Leancloud SDK启动推送服务:

PushService.setDefaultPushCallback(getReactApplicationContext(), PushHandlerActivity.class);

PushHandlerActivity为收到通知默认打开的activity,我们接下来实现。

PushHandlerActivity实现

该activity的定位为接收并初步解析通知数据。我们在com.leancloudpushdemo文件夹下添加PushHandlerActivity.java,内容如下:

package com.leancloudpushdemo;import android.app.Activity;import android.content.Intent;import android.content.pm.PackageManager;import android.os.Bundle;import java.util.HashMap;import java.util.Map;public class PushHandlerActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        processPush();        finish();        if (!PushModule.isActive()) {  //todo:判断PushModule是否实例化            relaunchActivity();        }    }    private void processPush() {        try {            Intent intent = getIntent();            String action = intent.getAction();            String channel = intent.getExtras().getString("com.avos.avoscloud.Channel");            String data = intent.getExtras().getString("com.avos.avoscloud.Data");            Map
map = new HashMap
(); map.put("action", action); map.put("channel", channel); map.put("data", data); PushModule.onReceive(map); //todo:处理通知 } catch (Exception e) { PushModule.onError(e); // todo:处理错误 } } private void relaunchActivity() { PackageManager pm = getPackageManager(); Intent launchIntent = pm.getLaunchIntentForPackage(getApplicationContext().getPackageName()); startActivity(launchIntent); }}

别忘了在AndroidManifest.xml中加上该activity:

主要处理逻辑实现

PushHandlerActivity代码中有三处todo是我们接下来要在PushModule中实现的逻辑。关于接收到通知后如何处理,我的思路是当native module收到通知时,通过RCTDeviceEventEmitter触发相应的Event,在js中监听这些Event并响应,修改PushModule如下:

public class PushModule extends ReactContextBaseJavaModule implements ActivityEventListener {    private static PushModule singleton;    private static String ON_RECEIVE = "leancloudPushOnReceive";    private static String ON_ERROR = "leancloudPushOnError";        public PushModule(ReactApplicationContext reactContext) {        super(reactContext);        singleton = this;    }        ...        protected static boolean isActive() {        return singleton != null;    }        private static WritableMap getWritableMap(Map
map) { WritableMap writableMap = Arguments.createMap(); writableMap.putString("action", map.get("action")); writableMap.putString("channel", map.get("channel")); writableMap.putString("data", map.get("data")); return writableMap; } protected static void onReceive(Map
map) { if (singleton != null) { WritableMap pushNotification = getWritableMap(map); DeviceEventManagerModule.RCTDeviceEventEmitter emitter = singleton.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); emitter.emit(ON_RECEIVE, pushNotification); } } protected static void onError(Exception e) { if (singleton != null) { WritableMap error = Arguments.createMap(); error.putString("message", e.getLocalizedMessage()); DeviceEventManagerModule.RCTDeviceEventEmitter emitter = singleton.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); emitter.emit(ON_ERROR, error); } } @Override public Map
getConstants() { final Map
constants = new HashMap<>(); constants.put("ON_RECEIVE", ON_RECEIVE); constants.put("ON_ERROR", ON_ERROR); return constants; } ...

最后,我们在PushService.js增加对消息通知相关事件的监听和处理的逻辑,我选择在保存installation成功后增加监听:

...import { DeviceEventEmitter } from 'react-native';...class PushService {    ...        _an_saveInstallation = () => {        AndroidPush.saveInstaillation((installationId, error) => {            if (installationId) {                DeviceEventEmitter.addListener(AndroidPush.ON_RECEIVE, (notification) => {                    console.log('receive android notification');                    this._an_onNotificationTapped(notification);                });                DeviceEventEmitter.addListener(AndroidPush.ON_ERROR, (res) => {                    console.log('android notification error');                    console.log(res);                });            } else {                console.log(error);            }        })    }    _an_onNotificationTapped = (notification) => {        Alert.alert('Android Notification Tapped');    }}...

现在我们在Leancloud控制台发送一条通知,手机应该能收到消息:

image

当点击通知的时候,App打开并执行我们自定义的逻辑:

image

实现App打开状态下的推送

到目前为止,我们已经实现了系统级的推送,和iOS一样,我们希望Android App打开状态下也能弹出通知提醒。Leancloud提供了这样的可能,我们可以通过 来实现。

自定义Receiver

我们在com.leancloudpushdemo路径下添加CustomPushReceiver.java,代码如下:

package com.leancloudpushdemo;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import com.alibaba.fastjson.JSON;import com.alibaba.fastjson.JSONException;import com.alibaba.fastjson.JSONObject;import java.util.HashMap;import java.util.Map;public class CustomPushReceiver extends BroadcastReceiver {    private static final String TAG = "CustomPushReceiver";    private HandleMessage handleMessage;    @Override    public void onReceive(Context context, Intent intent) {        try {            String action = intent.getAction();            String channel = intent.getExtras().getString("com.avos.avoscloud.Channel");            //获取消息内容            String data = intent.getExtras().getString("com.avos.avoscloud.Data");            JSONObject jsonObject = JSON.parseObject(data);            if (jsonObject != null) {                Map
map = new HashMap
(); map.put("action", action); map.put("channel", channel); map.put("data", data); PushModule.onCustomReceive(map); //todo: 处理通知 if (handleMessage!=null){ handleMessage.receiveMessage(jsonObject); } } } catch (JSONException e) { PushModule.onError(e); } } interface HandleMessage{ public void receiveMessage(JSONObject jsonObject); } public void setHandleMessage(HandleMessage handleMessage) { this.handleMessage = handleMessage; }}

todo的方法待会儿在PushModule中实现。接着,在AndroidManifest.xml中添加custom receiver:

通知处理

然后修改PushModule如下:

public class PushModule extends ReactContextBaseJavaModule implements ActivityEventListener {    ...    private static String ON_CUSTOM_RECEIVE = "leancloudPushOnCustomReceive";        ...        protected static void onCustomReceive(Map
map) { if (singleton != null) { WritableMap pushNotification = getWritableMap(map); DeviceEventManagerModule.RCTDeviceEventEmitter emitter = singleton.getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class); emitter.emit(ON_CUSTOM_RECEIVE, pushNotification); } } ... @Override public Map
getConstants() { final Map
constants = new HashMap<>(); constants.put("ON_RECEIVE", ON_RECEIVE); constants.put("ON_CUSTOM_RECEIVE", ON_CUSTOM_RECEIVE); constants.put("ON_ERROR", ON_ERROR); return constants; }}

最后,修改PushService.js,增加对ON_CUSTOM_RECEIVE事件的监听:

..._an_saveInstallation = () => {    AndroidPush.saveInstaillation((installationId, error) => {        if (installationId) {            ...            DeviceEventEmitter.addListener(AndroidPush.ON_CUSTOM_RECEIVE, (notification) => {                console.log('receive custom android notification');                this._showAlert(JSON.parse(notification.data).alert);            });            ...        } else {            ...        }    })}...

同时通知的消息提也需要做相应修改,才能让custom receiver接收到,我们可以用Postman来发送消息:

image

消息发出后,App中成功弹出消息提醒,完美。

image

结语

经过不懈的努力,我们已经成功使用Leancloud实现了iOS和Android上的消息通知,第一次写这么长的文章还是有点累的。。如果对你有帮助欢迎点赞!还有虽然功能都实现了,但是我想可能还会有更好的实现方式,欢迎找到的同学分享,谢谢!

相关链接

iOS篇地址:

本文Demo Github地址:)

转载地址:http://ruupx.baihongyu.com/

你可能感兴趣的文章
Centos7安装rabbitmq server 3.6.0
查看>>
iostat命令学习
查看>>
SQL 三种分页方式
查看>>
查看linux是ubuntu还是centos
查看>>
html video的url更新,自动清缓存
查看>>
IOS Xib使用——为控制器添加Xib文件
查看>>
CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙步骤
查看>>
【11】ajax请求后台接口数据与返回值处理js写法
查看>>
Python菜鸟之路:Jquery Ajax的使用
查看>>
LeetCode算法题-Maximum Depth of Binary Tree
查看>>
Cox 教学视频5
查看>>
Jenkins持续集成学习-搭建jenkins问题汇总
查看>>
使用ffmpeg实现对h264视频解码 -- (实现了一个易于使用的c++封装库)
查看>>
flink watermark介绍
查看>>
[Flink原理介绍第四篇】:Flink的Checkpoint和Savepoint介绍
查看>>
Android Xutils 框架
查看>>
C#基础知识整理 基础知识(21) 委托(二)
查看>>
Sysbench 0.5版安装配置
查看>>
书摘—你不可不知的心理策略
查看>>
【博客话题】毕业——开始人生的艰苦历程
查看>>