关闭

Java NotNoop推送方式实例

标签: apnsjava
2734人阅读 评论(0) 收藏 举报
分类:

先熟悉一下主要的几个接口或者类:

com.notnoop.apns.internal包:

  • AbstractApnsService:一个抽象类,实现了ApnsService接口。主要包含三种表现形式:

  1. ApnsServiceImpl:基础消息处理类。
  2. BatchApnsService:批量消息处理类,默认每隔5秒钟,执行一次批量推送。
  3. QueuedApnsService:队列消息处理类,即使用阻塞队列方式处理消息。
  • ApnsConnection:作为应用连接到苹果APNS服务的接口。主要包含两种表现形式:

  1. ApnsConnectionImpl:基础连接类,实现了ApnsConnection接口。主要处理从消息发送到收到回执后的一系列过程。
  2. ApnsPooledConnection:以多线程的方式管理连接池。
  • ReconnectPolicies:Socket的连接策略,分为三种:Never、Always、EveryHalfHour。
  • Utilities:顾名思义,就是一个工具类,包含一些工具和常量。
com.notnoop.apns包:

  • APNS:作为与APNS交互的主要类,用于构建Payload和ApnsService。
  • ApnsDelegate:委托接口,委托收到苹果服务器的状态通知后的处理。如果消息实际到达了客户端,则服务器不会收到任何的状态通知。
  • ApnsDelegateAdapter:代理适配器,继承了ApnsDelegate接口,但不做任何事。
  • ApnsNotification:通知信息接口,包含通知的所有信息。
  • ApnsService:APNS服务接口。
  • ApnsServiceBuilder:ApnsService的生成器。
  • DeliveryError:APNS可能返回的错误。
  • EnhancedApnsNotification:通知信息类,继承了ApnsNotification接口。
  • PayloadBuilder:Payload生成器。
  • ReconnectPolicy:重连策略接口,基于ReconnectPolicies。
示例:
package com.xxx.pushmsg.service.ios.impl;

import com.xxx.common.constant.CacheConstant;
import com.xxx.common.utils.RedisUtils;
import com.xxx.common.utils.StringUtil;
import com.xxx.pushmsg.service.ios.IosPushMsgService;
import com.notnoop.apns.APNS;
import com.notnoop.apns.ApnsDelegate;
import com.notnoop.apns.ApnsService;
import com.notnoop.apns.PayloadBuilder;
import com.notnoop.exceptions.NetworkIOException;
import javapns.notification.transmission.NotificationProgressListener;
import javapns.notification.transmission.NotificationThread;
import javapns.notification.transmission.NotificationThreads;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Service
public class IosPushMsgServiceImpl implements IosPushMsgService {
   private static final Logger log = LoggerFactory.getLogger(IosPushMsgServiceImpl.class);
    private static final Logger logPush = LoggerFactory.getLogger("push_arrival_rate");
   public static final ConcurrentHashMap<Long, Integer> msgStateMap = new ConcurrentHashMap<Long, Integer>();
    @Value("${priest.pushmsg.production}")
    //是否是生产环境
    private boolean production;

    @Value("${priest.pushmsg.certificate.file.name}")
    //证书文件地址
    private String certificateName;

    ApnsService service = null;
    @Resource
    private RedisUtils redisUtils;
    //连接池大小
    private int capacity = 20;
    @Resource
    private ApnsDelegate delegate;
    @PostConstruct
    public void init() {
        String password = "123456"; // 证书密码
        try {
	    //初始化服务类型为基本消息处理类型,并且连接设置为连接池
            service = APNS.newService().withCert(certificateName, password)
                    .asPool(capacity).withDelegate(delegate).withAppleDestination(production).build();
        } catch (Exception e) {
            log.error("Init error Class::IosPushMsgServiceImpl Method::init", e);
        }

    }

   public void stopPush(Long msgId){
      
   }

    public boolean pushOffLineMessageNotnoop(Map<String, String> tokenMessgae, Map<String, Object> mapCustom) {

        if (MapUtils.isEmpty(tokenMessgae)) {
            return true;
        }
        //铃音,微信等应用实现语音呼叫时使用的方式是将此铃音设置为30秒的长铃音,最大限制为30秒。
String sound = "msg.wav"; try { this.send(tokenMessgae, null, sound, mapCustom); } catch (Exception ex) { log.error("OffLineMessageNotnoop Multi error Class::IosPushMsgServiceImpl Method::pushOffLineMessageNotnoop Param::message" + " Param::tokenMessgae:" + tokenMessgae + ",mapCustom:" + mapCustom, ex); } return true; }
    //发送方法
    private void send(Map<String, String> tokenMessage, String launchImage, String sound, Map<String, Object> mapCustom) {

        try {
            Long nowStart = System.currentTimeMillis();
            Map<String, String> mapCount = this.redisUtils.hGetAll(CacheConstant.CACHE_PREFIX_IOS_GROUP_PUSHMSG_COUNT);
            //发送消息
            Iterator<String> it = tokenMessage.keySet().iterator();
            while (it.hasNext()) {
                Long nowStart111 = System.currentTimeMillis();
                String token = it.next();
                //因为标准的Token大小为64位,因此如果Token不符合规范则不推
                if (token.length() < 64) {
                    continue;
                }
                String alert = tokenMessage.get(token);
                //构造Payload
                PayloadBuilder payloadBuilder = APNS.newPayload();
                //拼装消息
                payloadBuilder = payloadBuilder.alertBody(alert);

                if (!StringUtils.isEmpty(launchImage)) {
                    payloadBuilder = payloadBuilder.launchImage(launchImage);
                }
                if (!StringUtils.isEmpty(sound)) {
                    payloadBuilder = payloadBuilder.sound(sound);
                }
                //裁剪消息
                if (payloadBuilder.isTooLong()) {
                    payloadBuilder = payloadBuilder.shrinkBody();
                }
                payloadBuilder = payloadBuilder.forNewsstand();
                //增加额外的信息
                if(null != mapCustom)
                    payloadBuilder.customFields(mapCustom);
                Integer count = 1;
                if (mapCount.containsKey(token)) {
                    String countStr = mapCount.get(token);
                    count = StringUtil.isEmpty(countStr) ? 0 : Integer.valueOf(countStr);
                    if (count < 99) {
                        count = count + 1;
                    } else {
                        count = 99;
                    }
                }
                //设置小红圈上面的数字
                payloadBuilder.badge(count);
                //组装成json
                String payload = payloadBuilder.build();
                //发送消息
                service.push(token, payload, new Date(System.currentTimeMillis() + 1000 * 1000));
                Long nowEnd111 = System.currentTimeMillis();
                //重组消息体,去除其中的Emoji,否则发送消息体会出现问题
                String logContent = StringUtil.filterEmoji(alert).replaceAll("\r","").replaceAll("\n","");
                this.redisUtils.hPut(CacheConstant.CACHE_PREFIX_IOS_GROUP_PUSHMSG_COUNT, token, count);
                StringBuffer sb = new StringBuffer();
                sb.append("{\"token\":");
                sb.append("\"");
                sb.append(token);
                sb.append("\"");
                sb.append(",\"content\":");
                sb.append("{");
                sb.append("\"content\":");
                sb.append("\"");
                sb.append(logContent);
                sb.append("\"");
                sb.append(",\"createTime\":");
                sb.append(nowEnd111);
                sb.append("}");
                sb.append(",\"ret\":");
                sb.append("{\"ret_code\":0}");
                sb.append("}");
                logPush.info(sb.toString());
            }
            Long nowEnd = System.currentTimeMillis();
            log.info("IOSPushMsgSend Cost:" + (nowEnd - nowStart));
        } catch (NetworkIOException e) {
            log.error("Send Multi Error NetworkIOException At Class::IosPushMsgServiceImpl Method::send"
                    + " Param::tokenMessage:" + tokenMessage, e);
            if (e.toString().contains("certificate")) {
                //shortMessageService.sendMessage(Long.MAX_VALUE, null, "15001257920", e.toString());
            }
        } catch (Exception ex) {
            log.error("Send Multi Error Exception At Class::IosPushMsgServiceImpl Method::send"
                    + " Param::tokenMessage:" + tokenMessage, ex);
        } finally  {
        }
    }

   public static final NotificationProgressListener DEBUGGING_PROGRESS_LISTENER = new NotificationProgressListener() {
      public void eventThreadStarted(NotificationThread notificationThread) {
         log.info("EventThreadStarted [EVENT]: thread #" + notificationThread.getThreadNumber() + " started with "
                    + " devices beginning at message id #" + notificationThread.getFirstMessageIdentifier()
                    + " At Class::NotificationProgressListener Method::eventThreadStarted" + notificationThread.getFailedNotifications());
      }

      public void eventThreadFinished(NotificationThread thread) {
         log.info("EventThreadFinished [EVENT]: thread #" + thread.getThreadNumber() + " finished: pushed messages #"
                    + thread.getFirstMessageIdentifier() + " to " + thread.getLastMessageIdentifier() + " toward " + " devices"
                    + " At Class::NotificationProgressListener Method::eventThreadFinished" + thread.getFailedNotifications());
      }

      public void eventConnectionRestarted(NotificationThread thread) {
            log.info("EventConnectionRestarted [EVENT]: connection restarted in thread #" + thread.getThreadNumber()
                    + " because it reached " + thread.getMaxNotificationsPerConnection() + " notifications per connection"
                    + " At Class::NotificationProgressListener Method::eventConnectionRestarted" + thread.getFailedNotifications());
      }

      public void eventAllThreadsStarted(NotificationThreads notificationThreads) {
            log.info("EventAllThreadsStarted [EVENT]: all threads started: " + notificationThreads.getThreads().size()
            + " At Class::NotificationProgressListener Method::eventAllThreadsStarted" + notificationThreads.getFailedNotifications());
      }

      public void eventAllThreadsFinished(NotificationThreads notificationThreads) {
            log.info("EventAllThreadsFinished [EVENT]: all threads finished: " + notificationThreads.getThreads().size()
                    + " At Class::NotificationProgressListener Method::eventAllThreadsFinished" + notificationThreads.getFailedNotifications());
      }

      public void eventCriticalException(NotificationThread notificationThread, Exception exception) {
            log.info("EventCriticalException [EVENT]: critical exception occurred: " + exception
                    + " At Class::NotificationProgressListener Method::eventCriticalException" + notificationThread.getFailedNotifications());
        }
   };

    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

}


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:18089次
    • 积分:523
    • 等级:
    • 排名:千里之外
    • 原创:35篇
    • 转载:2篇
    • 译文:0篇
    • 评论:14条
    文章分类
    最新评论