Android 项目必备(三十八)-->APP 消息推送

在这里插入图片描述

文章目录

    • 前言
    • 推送的实现方式
      • 1. C2DM
      • 2. 轮询
      • 3. SMS信令推送
      • 4. MQTT协议
      • 5. XMPP协议
      • 6. 使用第三方平台
    • Android 中 MQTT 的使用
      • 1. 集成
      • 2. 具体代码
      • 3. 项目地址

前言

今天来讲讲推送这件小事,事虽小,要做好却不容易。

推送难,难于上青天。

我们在讨论 Android 手机上的推送时,大多数情况是在说集成第三方推送,因为即使是像微信这样的大厂,也需要厂商加到启动白名单里才能保持在线。

iOS 手机使用 APNs(Apple Push Notification service)进行推送,而 Android 手机,也是有 GCM(Google Cloud Messaging)作为 Google 官方的推送支持的,但是在国内需要翻墙才能使用,并且需要手机安装了 Google Service ,条件比较苛刻。

GCM 最新版本叫 FCM(Firebase Cloud Messaging

推送的实现方式

1. C2DM

Cloud to Device Messaging,云端推送,是Android系统级别的消息推送服务(Google出品)

  • 原理
    基于Push方式
  • 具体描述
    C2DM服务负责处理诸如消息排队等事务,并向运行于目标设备上的应用程序分发这些消息。如下图:
    在这里插入图片描述
  • C2DM原理
    • 优点
      C2DM提供了一个简单的、轻量级的机制,允许服务器可以通知移动应用程序直接与服务器进行通信,以便于从服务器获取应用程序更新和用户数据。

    • 缺点
      1.依赖于Google官方提供的C2DM服务器,但在国内使用Google服务需要翻墙,成本较大;
      2.需要用户手机安装Google服务。但由于Android机型、系统的碎片化 & 国内环境,国内的Android系统都自动去除Google服务,假如要使用C2DM服务,这意味着用户还得去安装Google服务,成本较大。

2. 轮询

  • 原理
    基于Pull方式

  • 具体描述
    应用程序隔固定时间主动与服务器进行连接并查询是否有新的消息

  • 优点
    实时性好

  • 缺点
    成本大,需要自己实现与服务器之间的通信,例如消息排队等;
    到达率不确定,考虑轮询的频率:太低可能导致消息的延迟;太高,更费客户端的资源(CPU资源、网络流量、系统电量)和服务器资源(网络带宽)

3. SMS信令推送

  • 原理
    基于Push方式
  • 具体描述
    服务器有新消息时,发送1条类似短信的信令给客户端,客户端通过拦截信令,解析消息内容 / 向服务器获取信息
  • 优点
    可实现完全的实时操作
  • 缺点
    成本高(主要是短信资费的支出)

4. MQTT协议

  • 定义
    轻量级的消息发布/订阅协议
  • 原理
    基于Push方式,wmqtt.jar 是IBM提供的MQTT协议的实现,原理如下图:
    在这里插入图片描述
  • 项目实例
    AndroidPushNotificationsDemo

5. XMPP协议

  • 定义
    Extensible Messageing and Presence Protocol,可扩展消息与存在协议,是基于可扩展标记语言(XML)的协议,是目前主流的四种IM协议之一

  • 原理流程
    在这里插入图片描述

  • 优点
    1.开源:可通过修改其源代码来适应我们的应用程序。
    2.简单:XML易于解析和阅读;将复杂性从客户端转移到了服务器端
    3.可拓展性强:继承了在XML环境中灵活的发展性,可进一步对协议进行扩展,实现更为完善的功能。

  • 缺点
    如果将消息从服务器上推送出去,则不管消息是否成功到达客户端手机上。

6. 使用第三方平台

现今主流的推送平台分为:

  • 手机厂商类:小米推送、华为推送。
  • 第三方平台类:友盟推送、极光推送、云巴(基于MQTT)
  • BAT大厂的平台推送:阿里云移动推送、腾讯信鸽推送、百度云推送

推荐阅读:Android消息推送:第三方消息推送平台详细解析

Android 中 MQTT 的使用

Android中使用MQTT需要使用到Paho Android Service库,Paho Android Service是一个用Java编写的MQTT客户端库。
GitHub地址:https://github.com/eclipse/paho.mqtt.android

1. 集成

  • 在 module 的 build.gradle 文件中添加依赖:
repositories {maven {url "https://repo.eclipse.org/content/repositories/paho-snapshots/"}
}
dependencies {compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
}
  • AndroidManifest.xml 添加限权
    <uses-permission android:name="android.permission.INTERNET" /><uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /><uses-permission android:name="android.permission.WAKE_LOCK" />
  • 在 AndroidManifest.xml 注册 Service
        <service android:name="org.eclipse.paho.android.service.MqttService" /> <!--MqttService--><service android:name="com.dongyk.service.MyMqttService"/> <!--MyMqttService-->

2. 具体代码

2.1 Android中使用MQTT最主要的就是以下几个方法:

  • connect:连接MQTT服务器,这里主要讲3个参数的方法,如下:
 @Overridepublic IMqttToken connect(MqttConnectOptions options, Object userContext,IMqttActionListener callback) throws MqttException {//...
}

参数options:用来携带连接服务器的一系列参数,例如用户名、密码等。
参数userContext:可选对象,用于向回调传递上下文。一般传null即可。
参数callback:用来监听MQTT是否连接成功的回调

  • publish:发布消息,这里使用四个参数的方法,如下:
 @Overridepublic IMqttDeliveryToken publish(String topic, byte[] payload, int qos,boolean retained) throws MqttException, MqttPersistenceException {//...}

参数topic:发布消息的主题
参数payload:消息的字节数组
参数qos:提供消息的服务质量,可传0、1或2
参数retained:是否在服务器保留断开连接后的最后一条消息

  • subscribe:订阅消息,这里主要讲2个参数的方法,如下:
 @Overridepublic IMqttToken subscribe(String topic, int qos) throws MqttException,MqttSecurityException {//...}

参数topic:订阅消息的主题
参数qos:订阅消息的服务质量,可传0、1或2

2.2 MQTT服务——MyMqttService

public class MyMqttService extends Service {public final String TAG = MyMqttService.class.getSimpleName();private static MqttAndroidClient  mqttAndroidClient;private        MqttConnectOptions mMqttConnectOptions;public        String HOST           = "tcp://192.168.0.102:61613";//服务器地址(协议+地址+端口号)public        String USERNAME       = "admin";//用户名public        String PASSWORD       = "password";//密码public static String PUBLISH_TOPIC  = "tourist_enter";//发布主题public static String RESPONSE_TOPIC = "message_arrived";//响应主题@RequiresApi(api = 26)public        String CLIENTID       = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O? Build.getSerial() : Build.SERIAL;//客户端ID,一般以客户端唯一标识符表示,这里用设备序列号表示@Overridepublic int onStartCommand(Intent intent, int flags, int startId) {init();return super.onStartCommand(intent, flags, startId);}@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}/*** 开启服务*/public static void startService(Context mContext) {mContext.startService(new Intent(mContext, MyMqttService.class));}/*** 发布 (模拟其他客户端发布消息)** @param message 消息*/public static void publish(String message) {String topic = PUBLISH_TOPIC;Integer qos = 2;Boolean retained = false;try {//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());} catch (MqttException e) {e.printStackTrace();}}/*** 响应 (收到其他客户端的消息后,响应给对方告知消息已到达或者消息有问题等)** @param message 消息*/public void response(String message) {String topic = RESPONSE_TOPIC;Integer qos = 2;Boolean retained = false;try {//参数分别为:主题、消息的字节数组、服务质量、是否在服务器保留断开连接后的最后一条消息mqttAndroidClient.publish(topic, message.getBytes(), qos.intValue(), retained.booleanValue());} catch (MqttException e) {e.printStackTrace();}}/*** 初始化*/private void init() {String serverURI = HOST; //服务器地址(协议+地址+端口号)mqttAndroidClient = new MqttAndroidClient(this, serverURI, CLIENTID);mqttAndroidClient.setCallback(mqttCallback); //设置监听订阅消息的回调mMqttConnectOptions = new MqttConnectOptions();mMqttConnectOptions.setCleanSession(true); //设置是否清除缓存mMqttConnectOptions.setConnectionTimeout(10); //设置超时时间,单位:秒mMqttConnectOptions.setKeepAliveInterval(20); //设置心跳包发送间隔,单位:秒mMqttConnectOptions.setUserName(USERNAME); //设置用户名mMqttConnectOptions.setPassword(PASSWORD.toCharArray()); //设置密码// last will messageboolean doConnect = true;String message = "{\"terminal_uid\":\"" + CLIENTID + "\"}";String topic = PUBLISH_TOPIC;Integer qos = 2;Boolean retained = false;if ((!message.equals("")) || (!topic.equals(""))) {// 最后的遗嘱try {mMqttConnectOptions.setWill(topic, message.getBytes(), qos.intValue(), retained.booleanValue());} catch (Exception e) {Log.i(TAG, "Exception Occured", e);doConnect = false;iMqttActionListener.onFailure(null, e);}}if (doConnect) {doClientConnection();}}/*** 连接MQTT服务器*/private void doClientConnection() {if (!mqttAndroidClient.isConnected() && isConnectIsNomarl()) {try {mqttAndroidClient.connect(mMqttConnectOptions, null, iMqttActionListener);} catch (MqttException e) {e.printStackTrace();}}}/*** 判断网络是否连接*/private boolean isConnectIsNomarl() {ConnectivityManager connectivityManager = (ConnectivityManager) this.getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);NetworkInfo info = connectivityManager.getActiveNetworkInfo();if (info != null && info.isAvailable()) {String name = info.getTypeName();Log.i(TAG, "当前网络名称:" + name);return true;} else {Log.i(TAG, "没有可用网络");/*没有可用网络的时候,延迟3秒再尝试重连*/new Handler().postDelayed(new Runnable() {@Overridepublic void run() {doClientConnection();}}, 3000);return false;}}//MQTT是否连接成功的监听private IMqttActionListener iMqttActionListener = new IMqttActionListener() {@Overridepublic void onSuccess(IMqttToken arg0) {Log.i(TAG, "连接成功 ");try {mqttAndroidClient.subscribe(PUBLISH_TOPIC, 2);//订阅主题,参数:主题、服务质量} catch (MqttException e) {e.printStackTrace();}}@Overridepublic void onFailure(IMqttToken arg0, Throwable arg1) {arg1.printStackTrace();Log.i(TAG, "连接失败 ");doClientConnection();//连接失败,重连(可关闭服务器进行模拟)}};//订阅主题的回调private MqttCallback mqttCallback = new MqttCallback() {@Overridepublic void messageArrived(String topic, MqttMessage message) throws Exception {Log.i(TAG, "收到消息: " + new String(message.getPayload()));//收到消息,这里弹出Toast表示。如果需要更新UI,可以使用广播或者EventBus进行发送Toast.makeText(getApplicationContext(), "messageArrived: " + new String(message.getPayload()), Toast.LENGTH_LONG).show();//收到其他客户端的消息后,响应给对方告知消息已到达或者消息有问题等response("message arrived");}@Overridepublic void deliveryComplete(IMqttDeliveryToken arg0) {}@Overridepublic void connectionLost(Throwable arg0) {Log.i(TAG, "连接断开 ");doClientConnection();//连接断开,重连}};@Overridepublic void onDestroy() {try {mqttAndroidClient.disconnect(); //断开连接} catch (MqttException e) {e.printStackTrace();}super.onDestroy();}
}

MyMqttService 类的大概逻辑就是开启服务后,调用init()方法初始化各个参数,包括服务器地址、用户名、密码等等,然后调用doClientConnection()方法连接MQTT服务器,iMqttActionListener用来监听MQTT是否连接成功,连接成功则订阅主题。mqttCallback为订阅主题的回调,收到消息后会执行该回调中的messageArrived()方法,拿到消息后进行UI更新,并调用response()方法响应给对方告知消息已到达或者消息有问题等。

2.3 开启服务
MainActivity中开启服务,这里为了方便不做UI更新,所以就一行开启服务的代码,如下:

public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyMqttService.startService(this); //开启服务}
}

3. 项目地址

MqttAndroidClient

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/1381943.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

APP消息推送(APP Push)解决方案-服务端工作逻辑和实现

一、APP 推送概述&#xff1a; App推送消息是我们常见的一种app消息提醒方式。 我们的实现需要第三方的支持&#xff0c;实现方式是后台通过接口将Push请求发送至第三方&#xff0c;第三方实现在App所在设备上的推送。 二、APP推送后台处理逻辑&#xff1a; 在与推送平台交互时…

app消息推送的详细实现教程

实现的主要思想 app实现消息推送&#xff0c;利用的是第三方的个推平台&#xff0c;后端将需要推送的内容通过第三方个推服务器传递给手机端。 具体前端打包配置 根据上图可知&#xff0c;采用的打包软件是Hbuilder X,在模块配置的时候&#xff0c;勾选push模块中的uniPush。…

App消息推送的原理

文章目录 1. 基本概念2. iOS和Android消息推送原理对比2.1 iOS2.1.1 基本原理2.1.2 优劣势 2.2 Android2.2.1 基本原理2.2.2 优劣势 3. Android消息推送原理3.1 操作系统有自身的消息推送功能&#xff08;系统级别&#xff09;3.2 三种基本的推送方式&#xff1a;Push、Pull 和…

php实现app消息推送

如何用php实现APP消息推送 现在有很多的消息推送厂商&#xff0c;比如阿里云的消息推送&#xff0c;极光推送&#xff0c;融云的消息推送。他们的原理都是把sdk内置在app里面&#xff0c;达到消息推送的目的&#xff0c;通过一张图来了解一下&#xff0c;看不懂不要紧&#xf…

Android,ios,安卓app推送消息通知,java后台向手机推送app的通知教程

文章目录 一、业务介绍1.1 产品简介1.2 名词解释1.3 消息推送流程 二、应用创建三、客户端 SDK 集成3.1 Android3.2 iOS 四、服务端推送4.1 服务端消息下发流程&#xff08;必读&#xff09;4.2 开发者中心后台4.3 推送代码 五、参数说明 一、业务介绍 1.1 产品简介 个推是商…

App消息推送概述

消息推送介绍 消息推送&#xff08;Push&#xff09;&#xff0c;是指从云端服务器到手机终端的消息推送通道&#xff0c;运营人员可以通过自己产品后台或者第三方推送通道对用户移动设备进行主动的消息推送。通过消息推送&#xff0c;目标用户可以在移动设备通知和状态栏看到…

PushDeer:一种无APP的通知推送解决方案

概述 去年六月&#xff0c;我曾写下一篇博客介绍如何 借助 ServerChan 实现个人微信通知推送&#xff0c;在那篇文章中介绍了 ServerChan 及其使用方法&#xff0c;总的来说&#xff0c;对于简单的通知需求&#xff0c;使用 ServerChan 是非常简单有效的。但是实际使用起来&…

一文让你知道关于App推送那些事

推送相关介绍 在用户未打开App时&#xff0c;服务端向用户推送服务器最新的消息数据&#xff0c;称为推送。消息推送在移动开发中用到的场景非常多&#xff0c;比如典电商类app的商品促销活动&#xff0c;资讯类的app的新闻推送等等。在实际开发中&#xff0c;我们常常会根据产…

关于ISO27701隐私信息安全管理体系介绍

01 什么是ISO27701 ISO27701是对ISO27001信息安全管理和ISO27002安全控制的隐私扩展&#xff0c;全称《安全技术—扩展ISO27001和ISO27002的隐私信息管理—要求与指南》&#xff0c;是ISO标准委员会以ISO 27001为基准&#xff0c;以ISO27552为蓝本&#xff0c;建立发布的隐私…

双向循环链表、dancing links

目录 双向循环链表 力扣 426. 将二叉搜索树转化为排序的双向链表 十字交叉双向循环链表&#xff08;dancing links&#xff09; 精确覆盖问题 dancing links X算法&#xff08;V1递归版&#xff09; POJ 3740 Easy Finding 数独 X算法优化 X算法&#xff08;V2非递归…

jpg照片太大怎么压缩变小?jpg如何缩小图片大小kb?

我们平时在接收过多的jpg格式图片的时候&#xff0c;越大的图片虽然越清晰&#xff0c;但是接收和储存起来就非常不方便&#xff0c;那么有没有什么办法可以将jpg图片压缩呢&#xff1f;其实现在可以通过在线图片处理工具来完成jpg压缩&#xff08;https://www.yasuotu.com/jpg…

html宽度一变小图形就上去,如何把图片大小变小?

我们在布局图片列表时&#xff0c;通常我们要控制图片的高度和宽度这样来达到图片统一。我们在HTML布局时候直接在图片img标签加宽度和高度属性即可控制图片高和宽。 一、html img图片标签高度宽度设置 我们可以直接在图片标签设置宽度width和高度height&#xff0c;这里需要注…

ChatGPT等人工智能编写文章的内容今后将成为常态

BuzzFeed股价上涨200%可能标志着“转向人工智能”媒体趋势的开始。 周四&#xff0c;一份内部备忘录被华尔街日报透露BuzzFeed正计划使用ChatGPT聊天机器人-风格文本合成技术来自OpenAI&#xff0c;用于创建个性化盘问和将来可能的其他内容。消息传出后&#xff0c;BuzzFeed的…

照片怎么转换大小?怎么把图片尺寸变小?

平时在使用QQ截图之后&#xff0c;发现图片尺寸过大不方便上传&#xff0c;该怎么解决图片大小转换问题呢&#xff1f;本文将介绍一款图片改大小&#xff08;https://www.yasuotu.com/size&#xff09;工具&#xff0c;可以在线处理图片尺寸&#xff0c;打开浏览器即可调整图片…

照片大小kb怎么调整变小?

伴随着工作和生活的需要&#xff0c;图片的应用遍及我们生活和工作的方方面面&#xff0c;随之我们的电子设备上面累积的图片文件也越来越多。因为图片使用的场景不同&#xff0c;所以对图片的大小也有不同的要求&#xff0c;那就要求我们学会调整照片大小的方法&#xff0c;会…

如何压缩照片大小-照片无损压缩办法

图片大家都不陌生&#xff0c;于生活于工作我们都能接触到&#xff0c;但并不是原图片什么样&#xff0c;我们都可以直接进行使用的。很多图片的质量虽然特别的高清&#xff0c;但是它的体积也像特别大&#xff0c;这时候无论我们是传输给他人&#xff0c;还是上传到各个社交媒…

C#,数值计算——抛物线插值与Brent方法(Parabolic Interpolation and Brent‘s Method)的计算方法与源程序

using System; namespace Legalsoft.Truffer { /// <summary> /// 抛物线插值与Brent方法 /// Parabolic Interpolation and Brents Method /// </summary> public class Brent : Bracketmethod { public double xmin { get; set…

【Linux操作系统】深入理解Linux系统编程中的open函数

在Linux系统编程中&#xff0c;open函数是一个非常重要的系统调用函数&#xff0c;它用于打开或创建一个文件&#xff0c;并返回一个文件描述符。本文将详细介绍open函数的用法&#xff0c;并给出具体的代码示例。 文章目录 1. 函数原型2. 函数参数2.1 flags参数2.2 mode参数 …

34. 应用监控【监控端点配置】

当一个 Spring Boot 项目运行时&#xff0c;开发者需要对 Spring Boot 项目进行实时监控来获取项目的运行情况&#xff0c;在项目出错时能够实现自动报警等。 Spring Boot 提供了actuator 来帮助开发者获取应用程序的实时运行数据。开发者可以选择使用 HTTP 端点或JMX来管理和监…

数据监控平台

数据监控平台 监控平台需要实时监控业务指标数据&#xff0c;系统特点&#xff1a;高并发&#xff0c;大数据&#xff0c;低延迟。主要使用的技术&#xff1a; HBase存储海量数据&#xff0c;ScriptEngine引擎&#xff0c;MySQL分表&#xff0c;Redis集群。 高并发&#xf…