Java NotNoop推送方式实例

原创 2015年07月10日 11:49:48

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

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;
    }

}


版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

[Java Web]Java的APNS类库 notnoop

Android应用一般通过后台向服务器轮询请求获取信息,而iOS应用则会在被切换到后台一段时间后停止运行,这时候如果想要达到信息的获取则只能依靠APNS(Apple Push Notification...

Java APNS使用填坑

1.java向ios推送消息有现成的类库java APNS可以使用,github地址:https://github.com/notnoop/java-apns 2.官网上给出了使用的demo: //S...

IOS push推送(javapns包与notnoop包的区别)

使用java进行IOS推送,开源的jar包比较有名的主要有两个,一个是javapns,一个是notnoop. 对于javapns,之前有介绍过,内存泄漏。这个问题算比较严重,表现在: 1.对于已推...
  • CICI622
  • CICI622
  • 2014年07月03日 09:46
  • 1455

[ThirdParty]notnoop / java-apns

notnoop/java-apns github:https://github.com/notnoop/java-apns 简介 java-apns是服务于APNS服务的java客户端,该库目的是...
  • sTeVes
  • sTeVes
  • 2013年04月29日 10:49
  • 1860

手把手教你配置苹果APNS推送服务

http://my.oschina.net/hejunbinlan/blog/494721 摘要 手把手教你配置苹果APNS推送服务 目录[-] 1. 什么是推送通知...

Apple Push Notification Service(APNS)开发指引

notnoop/java-apns github:https://github.com/notnoop/java-apns 简介 java-apns是服务于APNS服务的java客户端,该...

Java实现Redis的消息订阅和发布

1.  首先需要一个消息监听器类 package com.sogou.baike.testimport.testSubscribe; import redis.clients.jedis.Jedis...

Redis的pub/Sub(订阅与发布)在java中的实践

Pub/Sub功能(means Publish, Subscribe)即发布及订阅功能。基于事件的系统中,Pub/Sub是目前广泛使用的通信模型,它采用事件作为基本的通信机制,提供大规模系统所要求的松...
  • canot
  • canot
  • 2016年07月18日 09:02
  • 8207

Java之Redis队列+Websocket+定时器实现跑马灯实时刷新

开心一笑【老婆对老公说:老公你说我奇怪不奇怪啊,我既然可以用眼睛吃饭也。老公:说的新鲜,怎么用眼睛怎么吃饭啊。老婆说:我看你一眼就饱了……】提出问题项目中如何利用Redis队列+定时器(quartz)...

Redis应用3-基于Redis消息队列实现的异步操作

Redis实现消息队列的模式常用的消息队列有RabbitMQ, ActiveMQ, Kafka等,这都是开源的功能强大的消息队列,适合于在企业项目应用。Redis实现的消息队列代码原理 Redis...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java NotNoop推送方式实例
举报原因:
原因补充:

(最多只允许输入30个字)