zoukankan      html  css  js  c++  java
  • 极光消息推送服务器端开发实现推送(上)

    以前一直使用的极光的手动输入推送内容然后推送到客户端,今天遇到了推送频率比较高且比较有规律的内容,比如事实天气。这样就需要用我们自己的服务器来自动生成推送内容了。

    在官方的SDK文档中找了半天,终于找到了有点类似的接口了,进去先看看:http://docs.jpush.cn/pages/viewpage.action?pageId=2228302


    可以看到,上面两句话很醒目,我们看看它封装的REST API是个什么东西,再点进去看看


    上面两句话读了一下,大笑看来我们的运气还不错,这个应该就是了。

    好了我们进入上面的Java开发部分:https://github.com/jpush/jpush-api-java-client

    进去看了半天,大概明白意思了,已经帮助我们封装好了,现在我们只需要下载jar包和它提供的实例文档。


    进去后发现又对RESI API进行了更详细的说明,比如参数、频率限制等。

    好吧,我们看看推送消息和通知,如下图点击进入


    进去之后就看到了真真需要的api接口了,这里有各个方法和参数的说明。如果有的朋友还觉得看不懂,简单,直接下载示例代码(抄袭谁不会啊偷笑


    我下载官方示例代码,新建立了一个项目如下:


    消息发送端代码:

    package com.meritit.tuisong.service;
    import java.util.HashMap;
    import java.util.Map;
    
    import cn.jpush.api.ErrorCodeEnum;
    import cn.jpush.api.IOSExtra;
    import cn.jpush.api.JPushClient;
    import cn.jpush.api.MessageResult;
    
    public class JPushClientExample {
    
    	private static final String appKey ="5d30bebd28335593a13454861";	//必填,例如466f7032ac604e02fb7bda89
    
    	private static final String masterSecret = "0e0cc80c6f6a4703bec9ed191";//"13ac09b17715bd117163d8a1";//必填,每个应用都对应一个masterSecret
    
    	private static JPushClient jpush = null;
    
    	/**
    	 * 保存离线的时长。秒为单位。最多支持10天(864000秒)。
    	 * 0 表示该消息不保存离线。即:用户在线马上发出,当前不在线用户将不会收到此消息。
    	 * 此参数不设置则表示默认,默认为保存1天的离线消息(86400秒)。
    	 */
    	private static long timeToLive =  60 * 60 * 24;  
    
    	public static void main(String[] args) {
    		/*
    		 * Example1: 初始化,默认发送给android和ios,同时设置离线消息存活时间
    		 * jpush = new JPushClient(masterSecret, appKey, timeToLive);
    		 */
    
    		/*		
    		 * Example2: 只发送给android
    		 * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.Android);
    		 */
    
    		/*
    		 * Example3: 只发送给IOS
    		 * jpush = new JPushClient(masterSecret, appKey, DeviceEnum.IOS);
    		 */
    
    		/*
    		 * Example4: 只发送给android,同时设置离线消息存活时间
    		 * jpush = new JPushClient(masterSecret, appKey, timeToLive, DeviceEnum.Android);
    		 */
    
    
    		jpush = new JPushClient(masterSecret, appKey, timeToLive);
    
    		/*
    		 * 是否启用ssl安全连接, 可选
    		 * 参数:启用true, 禁用false,默认为非ssl连接
    		 */
    		//jpush.setEnableSSL(true);
    
    
    		//测试发送消息或者通知
    		testSend();
    	}
    
    	private static void testSend() {
    		// 在实际业务中,建议 sendNo 是一个你自己的业务可以处理的一个自增数字。
    		// 除非需要覆盖,请确保不要重复使用。详情请参考 API 文档相关说明。
    		int sendNo = getRandomSendNo();
    		String msgTitle = "+;//jpush""";
    		String msgContent = "\&;w""a--【
    push】";
    
    		/*
    		 * IOS设备扩展参数,
    		 * 设置badge,设置声音
    		 */
    
    		Map<String, Object> extra = new HashMap<String, Object>();
    		IOSExtra iosExtra = new IOSExtra(10, "WindowsLogonSound.wav");
    		extra.put("ios", iosExtra);
    
    		//对所有用户发送通知, 更多方法请参考文档
    		MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);
    		//MessageResult msgResult  = jpush.sendNotificationWithAlias(sendNo, "a", msgTitle, msgContent);
    
    		//覆盖指定msgId的消息,msgId可以从msgResult.getMsgid()获取。
    		//MessageResult msgResult = jpush.sendNotificationWithAppKey(sendNo, msgTitle, msgContent, 0, extra,msgResult.getMsgid());
    
    
    		if (null != msgResult) {
    			System.out.println("服务器返回数据: " + msgResult.toString());
    			if (msgResult.getErrcode() == ErrorCodeEnum.NOERROR.value()) {
    				System.out.println(String.format("发送成功, sendNo= %s,messageId= %s",msgResult.getSendno(),msgResult.getMsg_id()));
    			} else {
    				System.out.println("发送失败, 错误代码=" + msgResult.getErrcode() + ", 错误消息=" + msgResult.getErrmsg());
    			}
    		} else {
    			System.out.println("无法获取数据");
    		}
    
    	}
    
    	public static final int MAX = Integer.MAX_VALUE;
    	public static final int MIN = (int) MAX/2;
    
    	/**
    	 * 保持 sendNo 的唯一性是有必要的
    	 * It is very important to keep sendNo unique.
    	 * @return sendNo
    	 */
    	public static int getRandomSendNo() {
    		return (int) (MIN + Math.random() * (MAX - MIN));
    	}
    
    }

    执行结果如下:



    消息接收端代码:

    package com.meritit.tuisong.service;
    import java.util.List;
    
    import cn.jpush.api.JPushClient;
    import cn.jpush.api.receive.ReceiveResult;
    
    
    public class ReceiveClientExample {
    
    	private static final String appKey ="5d30bebd28335593a13454861";	//必填,例如466f7032ac604e02fb7bda89
    
    	private static final String masterSecret = "0e0cc80c6f6a4703bec9ed191";//"13ac09b17715bd117163d8a1";//必填
    	
    	
    	public static void main(String[] args) {
    		JPushClient JPushClient = new JPushClient(masterSecret, appKey);
    		
    		String msgId = "1236722141";
    		
    		String[] msgIds = {"1236722141","910981248","911034889"};
    		
    		//获取一条
    		ReceiveResult receiveResult =  JPushClient.getReceived(msgId);
    		if(receiveResult == null){
    			System.out.println("获取receive 数据失败!"+receiveResult);
    		}else{
    			//gson toJson 之后,NULL值的字段会被过滤掉
    			System.out.println("received result:"+receiveResult.toString());
    		}
    	
    	
    		// 获取多条
    		List<ReceiveResult> receiveResults = JPushClient.getReceiveds(msgIds);
    		if(receiveResults == null ){
    			System.out.println("获取receive 数据失败!");
    		}else{
    			System.out.println("成功获取了:"+receiveResults);
    		}
    	
    	}
    }
    
    执行结果:

    测试已经成功,下面我们来看看源代码是怎么做的,其他的其实只是数据封装,我们来看看关键的一句代码

    MessageResult msgResult = jpush.sendCustomMessageWithAppKey(sendNo,msgTitle, msgContent);

    查看源代码,如下:

    	public MessageResult sendCustomMessageWithAppKey(int sendNo, String msgTitle, String msgContent) {
    		CustomMessageParams p = new CustomMessageParams();
    		p.setReceiverType(ReceiverTypeEnum.APPKEYS);
    		return sendCustomMessage(p, sendNo, msgTitle, msgContent, null, null);
    	}
    发现实际是调用的sendCustomMessage方法

    	protected MessageResult sendCustomMessage(CustomMessageParams p, int sendNo, String msgTitle, String msgContent, String msgContentType, Map<String, Object> extra) {
    		if (null != msgContentType) {
    			p.getMsgContent().setContentType(msgContentType);
    		}
    		if (null != extra) {
    			p.getMsgContent().setExtra(extra);
    		}
    		return sendMessage(p, sendNo, msgTitle, msgContent);
    	}
    这里进行了空值判断,实际又调用了sendMessage方法

    	protected MessageResult sendMessage(MessageParams p, int sendNo, String msgTitle, String msgContent) {
    		p.setSendNo(sendNo);
    		p.setAppKey(this.getAppKey());
    		p.setMasterSecret(this.masterSecret);
    		p.setTimeToLive(this.timeToLive);
    		p.setSendDescription(this.getSendDescription());
    		for (DeviceEnum device : this.getDevices()) {
    			p.addPlatform(device);
    		}
    		if (null != msgTitle) {
    			p.getMsgContent().setTitle(msgTitle);
    		}
    		p.getMsgContent().setMessage(msgContent);
    	
    		return sendMessage(p);
    	}
    在这里将参数封装到消息对象中调用sendMessage

    	protected MessageResult sendMessage(MessageParams params) {
    		return httpClient.sendPush(BaseURL.ALL_PATH, enableSSL, params);
    	}
    再进到sendPush方法中看看,哦,大概明白了,实际上是用的http请求发送消息的。

    	public MessageResult sendPush(final String path, final boolean enableSSL, final MessageParams messageParams) {
    		MessageResult messageResult = ValidateRequestParams.vidateParams(messageParams);
    		if(messageResult != null) return messageResult;
    
    		String pushResult = sendPost(path, enableSSL, parse(messageParams),RequestTypeEnum.PUSH.value(),null);
    		return gson.fromJson(pushResult, MessageResult.class);
    	}
    关键看倒数第二行代码

    	private String sendPost( String path, final boolean enableSSL, String params,Integer reqeustType,String authCode){
    		return sendRequest(path, enableSSL, params, "POST", reqeustType,authCode);
    	}

    	private String sendRequest(String path, final boolean enableSSL, String params,String method,Integer reqeustType,String authCode){
    		HttpURLConnection conn = null;
    		DataOutputStream outStream = null;
    		StringBuffer sb = new StringBuffer();
    
    		try {
    			if (enableSSL) {
    				initSSL();
    			}			
    
    			URL url = new URL(BaseURL.getUrlForPath(path,enableSSL,reqeustType));
    			conn = (HttpURLConnection) url.openConnection();
    			conn.setConnectTimeout(DEFAULT_CONNECTION_TIMEOUT);
    			conn.setReadTimeout(DEFAULT_SOCKET_TIMEOUT);
    			conn.setUseCaches(false);
    			conn.setDoOutput(true);
    			conn.setRequestMethod(method);
    			conn.setRequestProperty("Connection", "Keep-Alive");
    			conn.setRequestProperty("Charset", CHARSET);
    			if(authCode != null && !authCode.isEmpty()){
    				conn.setRequestProperty("Authorization", authCode);
    			}
    
    			if(method.equals("POST")){
    				byte[] data = params.getBytes(CHARSET);
    				conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    				conn.setRequestProperty("Content-Length", String.valueOf(data.length));
    				outStream = new DataOutputStream(conn.getOutputStream());
    				outStream.write(data);
    				outStream.flush();
    			}
    
    			if (conn.getResponseCode() == 200) {
    				logger.info("Congratulations!The request was successful. response status is 200");
    				InputStream in = conn.getInputStream();
    				InputStreamReader reader = new InputStreamReader(in, CHARSET);
    				char[] buff = new char[1024];
    				int len;
    				while ((len = reader.read(buff)) > 0) {
    					sb.append(buff, 0, len);
    				}
    			} else {		
    				logger.log(Level.WARNING,"Sorry!The request was fault. response " +
    						"status = "+conn.getResponseCode()+",errormsg = "+conn.getHeaderField(0));
    
    				String errmsg = "";
    				if(reqeustType == RequestTypeEnum.RECEIVE.value()){
    					errmsg = ErrorCodeEnum.errorMsg(conn.getResponseCode());
    					errmsg = errmsg == null ? conn.getHeaderField(0) : errmsg;
    				}else{
    					errmsg = conn.getHeaderField(0);
    				}
    				BaseResult result = new BaseResult(errmsg,conn.getResponseCode());
    				return result.toString();
    			}
    
    		}
    		catch (SocketTimeoutException e) {		
    			logger.log(Level.SEVERE,"God! the server throw SocketTimeout Exception." +
    					"please check it out the error message:"+e.getMessage());
    			BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONTIMEOUT.value());
    			return baseResult.toString();
    		}
    		catch (ConnectException e) {
    			logger.log(Level.SEVERE,"God! the server throw Connect Exception ." +
    					"please check it out the error message:"+e.getMessage());
    			BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONREFUSED.value());
    			return baseResult.toString();
    		}
    		catch (UnknownHostException e) {
    			logger.log(Level.SEVERE,"God! the server throw UnknownHost Exception ." +
    					"please check it out the error message:"+e.getMessage());
    			BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.CONNECTIONREFUSED.value());
    			return baseResult.toString();
    		}
    		catch (Exception e) {
    			logger.log(Level.SEVERE,"God! the server throw exception." +
    					"please check it out the error message:"+e.getMessage());
    			BaseResult baseResult = new BaseResult(e.getMessage().toString(),ErrorCodeEnum.UnknownException.value());
    			return baseResult.toString();
    		} 
    		finally {		
    			if (null != outStream) {
    				try {
    					outStream.close();
    				} catch (IOException e) {
    					e.printStackTrace();
    				}
    			}
    			if (null != conn) {
    				conn.disconnect();
    			}
    		}
    		return sb.toString();
    	}

    学过Android的朋友对这个应该很熟悉吧!比如里面的URL请求地址,看第9行代码
    URL url = new URL(BaseURL.getUrlForPath(path,enableSSL,reqeustType));

    	public  static String getUrlForPath(final String path,boolean enableSSL,Integer type) {
    		return getHostname(enableSSL,type) + path;
    	}

    	private static String getHostname(boolean enableSSL,Integer type) {
    		if(type == RequestTypeEnum.PUSH.value())
    			return enableSSL? HOST_NAME_SSL :HOST_NAME;
    		
    		if(type == RequestTypeEnum.RECEIVE.value())
    			return enableSSL? RECEIVE_HOST_NAME:RECEIVE_HOST_NAME;
    		
    		return null;
    	}
    在这里进行判断,如果enableSSL为false则发送消息请求地址为HOST_NAME,实际上这个enableSSL在BaseClient类中默认为false

    public boolean enableSSL = false;
    HOST_NAME就是官方文档中所说的默认请求地址:

    public static String HOST_NAME = "http://api.jpush.cn:8800";

    public static  String RECEIVE_HOST_NAME = "https://report.jpush.cn:443";  












  • 相关阅读:
    glog入门demo
    gflag的简单入门demo
    caffe库源码剖析——net层
    排序算法的c++实现——计数排序
    docker的/var/lib/docker目录迁移
    SpringCloud Ribbon 负载均衡 通过服务器名无法连接的神坑一个
    Spring Boot Cache使用与整合
    Navicat Keygen
    Windows / Office
    docker swarm 搭建与服务更新
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6469250.html
Copyright © 2011-2022 走看看