来聊一聊那个很牛逼的极光推送
之前写了一篇 websocket 的:web管理后台与微信公众号的消息会话,那么今天我们来聊聊另外一个长连接的技术–极光推送,已经项目实战,直接复制即可使用。
一、技术产生背景
1、在平时开发中,可能需要服务端对客户端实时的推送一些消息,例如在世界杯期间,一些球星的新闻以及最新的赛场状态,都是需要很快并且精准的推送到用户的手机
2、我们平时做的一般都是由客户端调取服务端的接口来进行一些数据交互,然而服务端却无法主动像客户端发送数据,这个时候推送就应运而生了
二、引入
1、在 pom 引入对应的极光包以及依赖包,这里直接拿官网的 pom 文件:
官网 java sdk 地址
<dependency><groupId>cn.jpush.api</groupId><artifactId>jiguang-common</artifactId><version>1.1.4</version></dependency><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.6.Final</version><scope>compile</scope></dependency><dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.3</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-api</artifactId><version>1.7.7</version></dependency><!-- For log4j --><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-log4j12</artifactId><version>1.7.7</version></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency>
引入依赖以后,如果调用极光的 api 报错,可以重新打包到 maven 仓库一次
三、流程图以及代码
1、极光推送有三种推送目标:别名(alias)、tag(标签)、RegistrationID
本流程图只介绍 RegisterationID 的目标推送,别名以及标签目标的方式由业务后台服务端和 app 端来共同协商用什么来做标签或者别名,
2、代码
JiGuangPushUtil
package com.tanxi.faith.util;import cn.jiguang.common.ClientConfig;
import cn.jiguang.common.ServiceHelper;
import cn.jiguang.common.connection.NettyHttpClient;
import cn.jiguang.common.resp.APIConnectionException;
import cn.jiguang.common.resp.APIRequestException;
import cn.jiguang.common.resp.ResponseWrapper;
import cn.jpush.api.JPushClient;
import cn.jpush.api.push.PushResult;
import cn.jpush.api.push.model.Message;
import cn.jpush.api.push.model.Platform;
import cn.jpush.api.push.model.PushPayload;
import cn.jpush.api.push.model.audience.Audience;
import cn.jpush.api.push.model.audience.AudienceTarget;
import cn.jpush.api.push.model.notification.AndroidNotification;
import com.gizwits.boot.utils.ParamUtil;
import com.gizwits.boot.utils.SysConfigUtils;
import com.gizwits.lease.config.CommonSystemConfig;
import io.netty.handler.codec.http.HttpMethod;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.jpush.api.push.model.notification.*;import java.net.URI;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.Map;/*** Description:极光推送api* User: tanxi* Date: 2019-02-22*/
public class JiGuangUtil {public static void main(String[] args){
// testSendPush("推送消息","");}protected static final Logger LOG = LoggerFactory.getLogger("");// demo App defined in resources/jpush-api.confprotected static final String APP_KEY ="XXXXX";protected static final String MASTER_SECRET = "XXXXX";protected static final String GROUP_PUSH_KEY = "XXXXXX";protected static final String GROUP_MASTER_SECRET = "XXXXXX";public static final String TITLE = "Test from API example";public static final String ALERT = "Test from API Example - alert";public static final String MSG_CONTENT = "Test from API Example - msgContent";public static final String REGISTRATION_ID = "XXXXX";public static final String TAG = "tag_api";public static long sendCount = 0;private static long sendTotalTime = 0;private static void sendToJiGuang(String message,String mobile,Map<String,String> map){buildPushObject_ios_audienceMore_messageWithExtras(message,mobile,map);testSendPushWithCallback(message,mobile);}public static PushPayload buildPushObject_all_alias_alert(String message,String mobile) {return PushPayload.newBuilder().setPlatform(Platform.all()).setAudience(Audience.alias("alias1")).setNotification(Notification.alert(ALERT)).build();}// 使用 NettyHttpClient 异步接口发送请求public static void testSendPushWithCallback(String message,String mobile) {CommonSystemConfig commonSystemConfig = SysConfigUtils.get(CommonSystemConfig.class);String appkey = commonSystemConfig.getJiGuangAppKey();String appSecret = commonSystemConfig.getjiGuangAppSecret();ClientConfig clientConfig = ClientConfig.getInstance();String host = (String) clientConfig.get(ClientConfig.PUSH_HOST_NAME);final NettyHttpClient client = new NettyHttpClient(ServiceHelper.getBasicAuthorization(appkey, appSecret),null, clientConfig);try {URI uri = new URI(host + clientConfig.get(ClientConfig.PUSH_PATH));PushPayload payload = buildPushObject_all_alias_alert(message,mobile);client.sendRequest(HttpMethod.POST, payload.toString(), uri, new NettyHttpClient.BaseCallback() {@Overridepublic void onSucceed(ResponseWrapper responseWrapper) {LOG.info("Got result: " + responseWrapper.responseContent);}});} catch (URISyntaxException e) {e.printStackTrace();}}/***构建推送对象:平台是 Andorid 与 iOS,推送目标是 ("tag1" 与 "tag2" 的并集)* 交("alias1" 与 "alias2" 的并集),推送内容是 - 内容为 MSG_CONTENT 的消息,* 并且附加字段 from = JPush。* @param message* @return*/public static PushPayload buildPushObject_ios_audienceMore_messageWithExtras(String message,String mobile,Map<String,String> map) {Message.Builder builder = Message.newBuilder();//设置消息内容builder.setMsgContent(message);//设置附件字段,可以自定义设置Iterator<String> iterator = map.keySet().iterator();while(iterator.hasNext()){String key = iterator.next();builder.addExtra(key,map.get(key));}if (!ParamUtil.isNullOrEmptyOrZero(mobile)){/*** 推送的关键就是构建一个 payload 的对象,如下是构建一个推送平台是安卓、ios平台,推送目标是设置手* 机号为别名的自定义消息**/return PushPayload.newBuilder().setPlatform(Platform.android_ios()).setAudience(Audience.newBuilder()/*** 这里如改为 AudienceTarget.registrationId(String registerationID),即推送给 app 端 对应 * RegisterationID 的用户设备,可以点对点推送给某一个,也可以批量推送给用户*/ .addAudienceTarget(AudienceTarget.alias(mobile)).build()).setMessage(builder.build()).build();}// 假如手机号为空,推送给别名为 alias1 的目标return PushPayload.newBuilder().setPlatform(Platform.android_ios()).setAudience(Audience.newBuilder().addAudienceTarget(AudienceTarget.alias("alias1")).build()).setMessage(builder.build()).build();}public static void testSendPush(String appKey,String appSecret,String message,String mobile,Map<String,String> map) {ClientConfig clientConfig = ClientConfig.getInstance();final JPushClient jpushClient = new JPushClient(appSecret, appKey, null, clientConfig);// Here you can use NativeHttpClient or NettyHttpClient or ApacheHttpClient.// Call setHttpClient to set httpClient,// If you don't invoke this method, default httpClient will use NativeHttpClient.
// ApacheHttpClient httpClient = new ApacheHttpClient(authCode, null, clientConfig);
// jpushClient.getPushClient().setHttpClient(httpClient);final PushPayload payload = buildPushObject_ios_audienceMore_messageWithExtras(message,mobile,map);// // For push, all you need do is to build PushPayload object.
// PushPayload payload = buildPushObject_all_alias_alert();try {PushResult result = jpushClient.sendPush(payload);LOG.info("Got result - " + result);/*** 如果使用 NettyHttpClient(v3.2.15 版本新增),需要在响应返回后手动调用一下 NettyHttpClient 中的 close * 方法,否则进程不会退出*/// jpushClient.close();} catch (APIConnectionException e) {LOG.error("Connection error. Should retry later. ", e);LOG.error("Sendno: " + payload.getSendno());} catch (APIRequestException e) {LOG.error("Error response from JPush server. Should review and fix it. ", e);LOG.info("HTTP Status: " + e.getStatus());LOG.info("Error Code: " + e.getErrorCode());LOG.info("Error Message: " + e.getErrorMessage());LOG.info("Msg ID: " + e.getMsgId());LOG.error("Sendno: " + payload.getSendno());}}
}
ParameterUtil
public static boolean isNullOrEmptyOrZero(Object obj) {if (obj == null) {return true;}if (obj instanceof Long) {Long value = (Long) obj;return value <= 0;} else if (obj instanceof Integer) {Integer value = (Integer) obj;return value <= 0;} else if (obj instanceof Double) {Double value = (Double) obj;return value <= 0;} else if (obj instanceof String) {String value = (String) obj;return StringUtils.isEmpty(value) || StringUtils.isBlank(value);} else if (obj instanceof List) {List<?> value = (List<?>) obj;return value.size() <= 0;}return false;}
当需要调用api的时候,在代码里直接通过如下调用方式实现极光推送
JiGuangUtil.testSendPush(appkey,appSecret ,消息内容,手机号也就是我这里的推送目标,自定义即可用来做附加字段)
四、常见问题
常见问题指南见官网
四、总结
极光推送的实现并不复杂,只需要将极光推送的工作原理理解透彻,理解不同推送对象、不同推送目标的区别,在极光的后台我们去查看极光的推送历史。这里提一点,如果极光服务器所在地为北京的应用,调用方服务器也位于北京的话,使用 bjapi.jiguang.cn 作为调用地址,可以提升 api 响应速度。
以上就是本人总结的极光推送实战,如有错误或者交流,欢迎留言评论联系
来聊一聊那个很牛逼的极光推送相关推荐
- 环球黑卡是不是很牛逼?
环球黑卡 环球黑卡是很牛逼,估计听说过的人都有这样的疑问. 近段就有一个网友在支付宝上抽到了环球黑卡,如果很牛逼还能抽奖送? 所谓抽奖获得环球黑卡,可能是商家跟支付宝联合推出的活动,但是也不要太激动. ...
- Android之集成极光推送
安卓端集成极光推送是很常见的,极光推送的简单高效性适合很多想要集成推送的APP,如果你要自己装逼,也可以自己写推送,只要想做都是可以的. 第一步.Gradle配置(Module的build.gradl ...
- 世界上有哪些代码量很少,但很牛逼很经典的算法或项目案例?
来自公众号:五分钟学算法 今天分享四个代码量很少,但很牛逼很经典的算法或项目案例. 1.no code 项目地址: https://github.com/kelseyhightower/nocode ...
- Java 未死,依然很牛逼!
很多文章都在说 Java 快被取代了,其实不然,现在 Java 还是未来主导编程语言,依然很牛逼. 今天给大家带来一套珍贵的 Java 电子书,非常全面,包括 Java 语言基础.多线程并发编程.JV ...
- 【福利】Java 依然很牛逼!
很多文章都在说 Java 快被取代了,其实不然,现在 Java 还是未来主导编程语言,依然很牛逼. 今天给大家带来一套珍贵的 Java 电子书,非常全面,包括 Java 语言基础.多线程并发编程.JV ...
- 你以为有白金卡就很牛逼?错!
近段有个朋友办了一张平安银行的白金卡,额度5万元,然后他高兴得不得了,还到处炫耀,以为带个"白金"字就很牛逼,其实不然,表面上看,白金卡虽然高大上,其实也只是一种卡级而已. 所以今 ...
- css盒模型中margin很牛逼
css盒子模型,说简单也简单,用的时候也有不简单的. 其中margin的值可以为负值,并且为了实现margin,忽略父级的padding.border.甚至定位.这在布局上很有用,要注意. ----- ...
- IDEA 有个很牛逼的功能
IDEA 有个很牛逼的功能,那就是后缀补全(不是自动补全),很多人竟然不知道这个操作,还在手动敲代码. 这个功能可以使用代码补全来模板式地补全语句,如遍历循环语句(for.foreach).使用 St ...
- 国内的windows硬件检测软件算是很牛逼的吧!!!?
这几天的实践表明,免费的,windows操作系统上硬件驱动检测软件,国内做的挺牛逼的. 虽然这些软件有些流氓,比如鲁大师,比如驱动精灵. 但是,在硬件检测方面确实挺厉害的,客官的说. 缘由: 最近在搞 ...
最新文章
- 计算机组成原理考试计算题,计算机组成原理常考计算题.doc
- android编程中添加gif,Android应用开发之【Android】使用android-gif-drawable包加载GIF动图...
- Spring or hibernate saveOrUpdateAll 偶然失效
- [react] 你用过react版本有哪些?
- EM算法的九层境界:​Hinton和Jordan理解的EM算法
- 作者:纪珍(1982-),女,中国科学院国家空间科学中心副研究员
- possible SYN flooding on port 3690 Sending cookies
- 002-JavaScript基本应用
- oki5530sc打印错误_我用的是四通oki 5530sc针式打印机,打印时提示正在打印,但就是不打印...
- 力士乐伺服电机编码器调零_伺服电机编码器安装拆卸方法
- python截取视频制作gif表情包
- Tool之synergyc:synergyc的简介、安装、使用方法(鼠标键盘控制两台或多台电脑)之详细攻略
- 论文笔记:FLEX: Unifying Evaluation for Few-Shot NLP
- linux文件下生成一个文件,Linux系统下生成一个指定大小的文件要注意什么?
- 苹果微信换行怎么打_微信朋友圈发长文被折叠成一行怎么破?附苹果安卓解决方案...
- thinkphp 之接收请求参数并过滤
- css动画放大缩小效果
- 牛津英语字典pdf下载_牛津树1阶段精讲笔记分享
- 2018 Intellij IDEA 最新旗舰版注册激活破解
- 学习Python中turtle模块的基本用法(4:绘制科赫曲线和谢尔宾斯基三角形)