这个看图效果最好请直接看下图:
我们手机经常会收到如上图弹框消息,我们今天说的就是上面的弹窗信息如何推送的。一般情况我们可以通过第三的服务来给自己的app发送推送消息例如:极光推送。
关于极光推送也是通过我们app开发同事了解到的。本来并不会跟我有任何交集,但是产品提了一个需求想通过我们自己的后台结合业务,推送自己的自定义消息弹窗。于是乎开始研究极光推送相关文档,特写此文章记录一下。
极光推送Java 后台对接有2中方式:
这里我们果断选择更为轻便的REST API。实现完成后最终的效果是:我们后台将要发送的推送消息发送给极光推送,然后极光推送在发送到我们的app上。
在讲代码实现之前我们需要先看一个极光推送文档 文档地址
我们这里使用的是Push API v3版本 v3 和v2 版本区别如下:
在进行使用前我们需要一定要注意的问题:
好了注意事项说完了我来正式结束调用REST API 具体内容:
极光推送的内容只能是 JSON 表示的一个推送对象,在通过HttpClinet调用时要在head头中指定Content-Type: application/json 同时发送的消息是json格式的字符串内容。
josn 内容主要有以下几块:
1 后台封装代码说明
代码并不复杂这里就不罗列代码了具体请参考下图中的代码示例或者github上的源码。
AppPushManger: 推送服务的门面。
AppPushParam:推送服务参数类 主要是用于设置 推送标题;推送消息;推送平台等具体的推送信息。
AppPushConfig: 推送第三方服务的配置信息的抽象接口
JiGuangConfig: 推送第三方服务配置的具体实现。
IAppPush: 推送服务的接口 主要用于AppPushManger(门面)调用。
AbstractAppPush: 推送服务IAppPush的push 方法具体实现类,同时定义 认证信息获取 (getAuthorization), 参数转换(convertAppPushParam), 调用推送第三放服务(post)三个抽象方法。如需有新的推送第三放服务接入可新定义AbstractAppPush的实现类即可。
JiGuangPushImpl: 极光推送服务实现,继承 AbstractAppPush 同时实现 认证信息获取 (getAuthorization), 参数转换(convertAppPushParam), 调用推送第三放服务(post)。其中具体的配置信息实现和参数转换器的实现是在JiGuangPushImpl构造中指定。具体请参考下面JiGuangPushImpl代码示例。
IAppPushParamConverter: AppPushParam 参数转换成 第三方服务规定的转换器抽象接口
JiGuangAppPushParamConverter: 极光推送AppPushParam 参数转换成 第三方服务规定的转换器具体实现。
PlatFormEnum: 推送平台的枚举配置类。
2 推送服务调用说明
后台服务调用AppPushManger 中的push方法,push方法中调用 IAppPush中的push方法 具体的IAppPush实现通过AppPushManger 的构造来进行传递。IAppPush的push方法具体实现是在 AbstractAppPush 进行实现的,我通过模板模式 在 AbstractAppPush 中将 认证信息获取 (getAuthorization), 参数转换(convertAppPushParam), 调用推送第三放服务(post) 定义成模板方法具体的实现在 JiGuangPushImpl中。
程序调用时序图:
注意 JiGuangPushImpl 右边的注释内容为: IAppPushParamConverter和AppPushConfig 的具体的实现是在JiGuangPushImpl 的构造方法中指定。
AbstractAppPush 具体代码如下:
package cn.zhuoqianmingyue.push.common;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import cn.zhuoqianmingyue.push.config.AppPushConfig;
import cn.zhuoqianmingyue.push.convert.IAppPushParamConverter;
import cn.zhuoqianmingyue.push.impl.JiGuangPushImpl;
import cn.zhuoqianmingyue.push.param.AppPushParam;
public abstract class AbstractAppPush implements IAppPush{
private static Logger log = LoggerFactory.getLogger(JiGuangPushImpl.class);
protected IAppPushParamConverter appPushParamConverter;
protected AppPushConfig appPushConfig;
/**
* @param appPushParam
* @return
*/
public boolean push(AppPushParam appPushParam){
String pushParmJsonStr = convertAppPushParam(appPushParam);
String authorization = getAuthorization(appPushConfig);
String returnJson = post(appPushConfig,authorization,pushParmJsonStr);
if(returnJson!=null){
log.info("app push sucess:"+returnJson);
return true;
}
log.info("app push fail!");
return false;
}
/**
* 认证信息获取
* @param appPushConfig
* @return
*/
public abstract String getAuthorization(AppPushConfig appPushConfig);
/**
* 参数转换
* @param appPushParam
*/
public abstract String convertAppPushParam(AppPushParam appPushParam);
/**
* 调用推送第三放服务
* @param appPushParam
* @param authorization
* @param pushParmJsonStr
* @return
*/
public abstract String post(AppPushConfig appPushConfig, String authorization, String pushParmJsonStr);
}
JiGuangPushImpl 具体代码如下:
package cn.zhuoqianmingyue.push.impl;
import org.apache.http.Header;
import org.apache.http.client.HttpClient;
import com.arronlong.httpclientutil.HttpClientUtil;
import com.arronlong.httpclientutil.builder.HCB;
import com.arronlong.httpclientutil.common.HttpConfig;
import com.arronlong.httpclientutil.common.HttpHeader;
import com.arronlong.httpclientutil.exception.HttpProcessException;
import cn.zhuoqianmingyue.push.common.AbstractAppPush;
import cn.zhuoqianmingyue.push.config.AppPushConfig;
import cn.zhuoqianmingyue.push.config.impl.JiGuangConfig;
import cn.zhuoqianmingyue.push.convert.impl.JiGuangAppPushParamConverter;
import cn.zhuoqianmingyue.push.param.AppPushParam;
import sun.misc.BASE64Encoder;
public class JiGuangPushImpl extends AbstractAppPush{
public JiGuangPushImpl() {
super.appPushParamConverter = new JiGuangAppPushParamConverter();
super.appPushConfig = new JiGuangConfig();
}
@Override
public String getAuthorization(AppPushConfig appPushConfig) {
String appKey = appPushConfig.getAppKey();
String masterSecret = appPushConfig.getMasterSecret();
String base64_auth_string = encryptBASE64(appKey + ":" + masterSecret);
String authorization = "Basic " + base64_auth_string;
return authorization;
}
@Override
public String convertAppPushParam(AppPushParam appPushParam) {
String pushParmJsonStr = appPushParamConverter.convert(appPushParam);
return pushParmJsonStr;
}
@Override
public String post(AppPushConfig appPushConfig, String authorization, String pushParmJsonStr) {
String returnJson = null;
Header[] headers = HttpHeader.custom()
.other("Authorization", authorization.trim())
.userAgent("Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.118 Safari/537.36").build();
try {
HCB hcb = HCB.custom()
.timeout(1000) //超时
.pool(100, 10);//启用连接池,每个路由最大创建10个链接,总连接数限制为100个
HttpClient client = hcb.build();
HttpConfig config = HttpConfig.custom()
.headers(headers) //设置headers,不需要时则无需设置
.url(appPushConfig.getPushUrl()) //设置请求的url
.json(pushParmJsonStr) //设置请求参数,没有则无需设置
.encoding("utf-8") //设置请求和返回编码,默认就是Charset.defaultCharset()
.client(client) //如果只是简单使用,无需设置,会自动获取默认的一个client对象
.inenc("utf-8") //设置请求编码,如果请求返回一直,不需要再单独设置
.inenc("utf-8"); //设置返回编码,如果请求返回一直,不需要再单独设置
returnJson = HttpClientUtil.post(config);//post请求
} catch (HttpProcessException e) {
e.printStackTrace();
}
return returnJson;
}
/**
* BASE64加密工具s
* @param str
* @return
*/
public static String encryptBASE64(String str) {
byte[] key = str.getBytes();
BASE64Encoder base64Encoder = new BASE64Encoder();
String strs = base64Encoder.encodeBuffer(key);
return strs;
}
}
测试类具体代码如下:
package cn.zhuoqianmingyue.push.test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.arronlong.httpclientutil.exception.HttpProcessException;
import cn.zhuoqianmingyue.push.common.AppPushManger;
import cn.zhuoqianmingyue.push.enumClass.PlatFormEnum;
import cn.zhuoqianmingyue.push.impl.JiGuangPushImpl;
import cn.zhuoqianmingyue.push.param.AppPushParam;
public class JiGuangPushTest {
public static void main(String[] args) throws HttpProcessException {
AppPushParam appPushParam = new AppPushParam();
//推送弹窗的信息内容
appPushParam.setTitle("标题");
appPushParam.setMessage("测试信息");
//推动的自定义信息
Map<String, String> homeExtrasInfo = new HashMap<String,String>();
appPushParam.setExtras(homeExtrasInfo);
//设置推送的平台
List<PlatFormEnum> platformList = new ArrayList<PlatFormEnum>();
platformList.add(PlatFormEnum.ANDROID);
//platformList.add(PlatFormEnum.IOS);
appPushParam.setPlatform(platformList);
//设置推送目标 如果不设置就是广播模式
Map<String, String[]> audience = new HashMap<String,String[]>();
audience.put("registration_id", new String[] {"140fe1da9efeac6fd85"});//指定设备的registration_id进行发送
appPushParam.setAudience(audience);
//设置开发环境 极光推送只是对ios有效
appPushParam.setPushEnvironment(false);
//设置离线消息保留时长(秒)
appPushParam.setTimeToLive(60);
AppPushManger manger = new AppPushManger(new JiGuangPushImpl());
manger.push(appPushParam);
}
}
代码具体细节请参考源码: 源码地址