我是靠谱客的博主 高挑夕阳,最近开发中收集的这篇文章主要介绍iOS推送javaPNS源码解析七,推送信息类,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

PushedNotification,该类用于获取推送消息结果信息。

所有属性如下:

 private Payload payload;消息体
 private Device device;目标设备
 private ResponsePacket response;推送返回response信息

 private int identifier;推送返回信息唯一标识 –好像没啥用
 private long expiry;失效时间 
 private int transmissionAttempts;推送次数
 private boolean transmissionCompleted;是否推送操作完成

 private Exception exception;异常

构造函数和set/get方法 不再一一说

 protected void setResponse(ResponsePacket response) {
  this.response = response;如果异常为空 就根绝response获取一个异常 如果异常中状态为0表示推送成功没有发生异常
  if (response != null && exception == null) exception = new ErrorResponsePacketReceivedException(response);
 }

是否推送成功

public boolean isSuccessful() {
  if (!transmissionCompleted) return false;推送操作未完成
  if (response == null) return true;返回response为null表示为完成
  if (!response.isValidErrorMessage()) return true;
  return false;
 }

public static List<PushedNotification> findSuccessfulNotifications(List<PushedNotification> notifications) {
  List<PushedNotification> filteredList = new Vector<PushedNotification>();
  for (PushedNotification notification : notifications) {
   if (notification.isSuccessful()) filteredList.add(notification);获取成功的
  }
  return filteredList;
 }

public static List<PushedNotification> findFailedNotifications(List<PushedNotification> notifications) {
  List<PushedNotification> filteredList = new Vector<PushedNotification>();
  for (PushedNotification notification : notifications) {
   if (!notification.isSuccessful()) {获取失败的
    filteredList.add(notification);
   }
  }
  return filteredList;
 }

 

public class PushedNotifications extends Vector<PushedNotification> implements List<PushedNotification> ;推送完成信息集合类,这个类也就是PushedNotification的集合,其主要方法是验证集合大小和推送成功失败的区分。

PushNotificationManager是推送的管理类,这个类用于启动连接服务器,执行推送操作。

private static int TESTS_SERIAL_NUMBER = 1;用于构造debug alert内容
 private int sslSocketTimeout = 30 * 1000; 连接超时时间

 static final Logger logger = Logger.getLogger(PushNotificationManager.class);日志
 private static final int DEFAULT_RETRIES = 3;默认推送次数
 private static final int SEQUENTIAL_IDENTIFIER = -1;推送消息返回信息唯一标识,默认为-1

 private static boolean useEnhancedNotificationFormat = true;使用推送返回消息校验

 private static boolean heavyDebugMode = false;是否debug
 private ConnectionToAppleServer connectionToAppleServer;连接到服务器
 private SSLSocket socket;安全连接socket
 private int retryAttempts = DEFAULT_RETRIES;默认推送次数

 private int nextMessageIdentifier = 1;推送消息返回信息唯一标识,如果是-1那么就是用这个自增数字
 private boolean trustAllServerCertificates = true;信任所有的服务器证书

 /* The DeviceFactory to use with this PushNotificationManager */
 @Deprecated
 private DeviceFactory deviceFactory;设备工厂 已经不个推荐

 private LinkedHashMap<Integer, PushedNotification> pushedNotifications = new LinkedHashMap<Integer, PushedNotification>();推送返回消息集合

set/get方法和构造函数不再说

 

初始化连接

public void initializeConnection(AppleNotificationServer server) throws CommunicationException, KeystoreException {
  try {
   this.connectionToAppleServer = new ConnectionToNotificationServer(server);
   this.socket = connectionToAppleServer.getSSLSocket();

   if (heavyDebugMode) {//日志信息
    dumpCertificateChainDescription();
   }
   logger.debug(“Initialized Connection to Host: [” + server.getNotificationServerHost() + “] Port: [” + server.getNotificationServerPort() + “]: ” + socket);
  } catch (KeystoreException e) {
   throw e;
  } catch (CommunicationException e) {
   throw e;
  } catch (Exception e) {
   throw new CommunicationException(“Error creating connection with Apple server”, e);
  }
 }

//使用已有服务器信息连接服务器,用于重连服务器发送发送失败的推送消息

 public void initializePreviousConnection() throws CommunicationException, KeystoreException {
  initializeConnection((AppleNotificationServer) this.connectionToAppleServer.getServer());
 }

//重连服务器
 public void restartConnection(AppleNotificationServer server) throws CommunicationException, KeystoreException {
  stopConnection();
  initializeConnection(server);
 }

//重连连接帮助类配置的服务器

 private void restartPreviousConnection() throws CommunicationException, KeystoreException {
  try {
   logger.debug(“Closing connection to restart previous one”);
   this.socket.close();
  } catch (Exception e) {
   /* Do not complain if connection is already closed… */
  }
  initializePreviousConnection();
 }

//停止连接

 public void stopConnection() throws CommunicationException, KeystoreException {
  processedFailedNotifications();
  try {
   logger.debug(“Closing connection”);
   this.socket.close();
  } catch (Exception e) {
   /* Do not complain if connection is already closed… */
  }
 }

//停止服务器连接前查询是否有发送失败的信息,如果有重连并重新推送

private int processedFailedNotifications() throws CommunicationException, KeystoreException {
  if (useEnhancedNotificationFormat) {//使用校验
   logger.debug(“Reading responses”);
   int responsesReceived = ResponsePacketReader.processResponses(this);//接收到的response的数量
   while (responsesReceived > 0) {
    PushedNotification skippedNotification = null;
    List<PushedNotification> notificationsToResend = new ArrayList<PushedNotification>();
    boolean foundFirstFail = false;
    for (PushedNotification notification : pushedNotifications.values()) {
     if (foundFirstFail || !notification.isSuccessful()) 
      if (foundFirstFail) notificationsToResend.add(notification);//一个推送失败后,那么它后边的也都是失败,这个跳过,后边的继续,如果这组推送中有两个失败,那么就不再推送,所以注意清空失效token
        else {
       foundFirstFail = true;
       skippedNotification = notification;
      }
     }
    }
    pushedNotifications.clear();
    int toResend = notificationsToResend.size();
    logger.debug(“Found ” + toResend + ” notifications that must be re-sent”);
    if (toResend > 0) {
     logger.debug(“Restarting connection to resend notifications”);
     restartPreviousConnection();
     for (PushedNotification pushedNotification : notificationsToResend) {
      sendNotification(pushedNotification, false);
     }
    }
    int remaining = responsesReceived = ResponsePacketReader.processResponses(this);//重发过后剩余的
     if (remaining == 0) {
     logger.debug(“No notifications remaining to be resent”);
     return 0;
    }
   }
   return responsesReceived;//这个数据也没啥用 很坑爹
  } else {
   logger.debug(“Not reading responses because using simple notification format”);
   return 0;
  }
 }
//构造推送消息
 private byte[] getMessage(String deviceToken, Payload payload, int identifier, PushedNotification message) throws IOException, Exception {
  logger.debug(“Building Raw message from deviceToken and payload”);

  /* To test with a corrupted or invalid token, uncomment following line*/
  //deviceToken = deviceToken.substring(0,10);

  // First convert the deviceToken (in hexa form) to a binary format
  byte[] deviceTokenAsBytes = new byte[deviceToken.length() / 2];
  deviceToken = deviceToken.toUpperCase();
  int j = 0;
  try {
   for (int i = 0; i < deviceToken.length(); i += 2) {
    String t = deviceToken.substring(i, i + 2);
    int tmp = Integer.parseInt(t, 16);
    deviceTokenAsBytes[j++] = (byte) tmp;
   }
  } catch (NumberFormatException e1) {
   throw new InvalidDeviceTokenFormatException(deviceToken, e1.getMessage());
  }
  preconfigurePayload(payload, identifier, deviceToken);
  // Create the ByteArrayOutputStream which will contain the raw interface
  byte[] payloadAsBytes = payload.getPayloadAsBytes();
  int size = (Byte.SIZE / Byte.SIZE) + (Character.SIZE / Byte.SIZE) + deviceTokenAsBytes.length + (Character.SIZE / Byte.SIZE) + payloadAsBytes.length;
  ByteArrayOutputStream bao = new ByteArrayOutputStream(size);

  // Write command to ByteArrayOutputStream
  // 0 = simple
  // 1 = enhanced
  if (useEnhancedNotificationFormat) {
   byte b = 1;
   bao.write(b);
  } else {
   byte b = 0;
   bao.write(b);
  }

  if (useEnhancedNotificationFormat) {
   // 4 bytes identifier (which will match any error packet received later on)
   bao.write(intTo4ByteArray(identifier));
   message.setIdentifier(identifier);

   // 4 bytes
   int requestedExpiry = payload.getExpiry();
   if (requestedExpiry <= 0) {
    bao.write(intTo4ByteArray(requestedExpiry));
    message.setExpiry(0);
   } else {
    long ctime = System.currentTimeMillis();
    long ttl = requestedExpiry * 1000; // time-to-live in milliseconds
    Long expiryDateInSeconds = ((ctime + ttl) / 1000L);
    bao.write(intTo4ByteArray(expiryDateInSeconds.intValue()));
    message.setExpiry(ctime + ttl);
   }
  }
  // Write the TokenLength as a 16bits unsigned int, in big endian
  int tl = deviceTokenAsBytes.length;
  bao.write(intTo2ByteArray(tl));

  // Write the Token in bytes
  bao.write(deviceTokenAsBytes);

  // Write the PayloadLength as a 16bits unsigned int, in big endian
  int pl = payloadAsBytes.length;
  bao.write(intTo2ByteArray(pl));

  // Finally write the Payload
  bao.write(payloadAsBytes);
  bao.flush();

  byte[] bytes = bao.toByteArray();

  if (heavyDebugMode) {
   try {
    FileOutputStream outf = new FileOutputStream(“apns-message.bytes”);
    outf.write(bytes);
    outf.close();
   } catch (Exception e) {
   }
  }

  logger.debug(“Built raw message ID ” + identifier + ” of total length ” + bytes.length);
  return bytes;
 }

private static final byte[] intTo2ByteArray(int value) {
  int s1 = (value & 0xFF00) >> 8;
  int s2 = value & 0xFF;
  return new byte[] { (byte) s1, (byte) s2 };
 }
private int newMessageIdentifier() {
  int id = nextMessageIdentifier;
  nextMessageIdentifier++;
  return id;
 }

//根据配置初始化一个消息信息

private void preconfigurePayload(Payload payload, int identifier, String deviceToken) {
  try {
   int config = payload.getPreSendConfiguration();
   if (payload instanceof PushNotificationPayload) {
    PushNotificationPayload pnpayload = (PushNotificationPayload) payload;
    if (config == 1) {
     pnpayload.getPayload().remove(“alert”);
     pnpayload.addAlert(buildDebugAlert(payload, identifier, deviceToken));
    }
   }
  } catch (Exception e) {
  }
 }

//创建debug消息信息
 private String buildDebugAlert(Payload payload, int identifier, String deviceToken) {
  StringBuilder alert = new StringBuilder();
  alert.append(“JAVAPNS DEBUG ALERT ” + (TESTS_SERIAL_NUMBER++) + “n”);

  /* Current date & time */
  alert.append(new SimpleDateFormat(“yyyy/MM/dd HH:mm:ss”).format(System.currentTimeMillis()) + “n”);

  /* Selected Apple server */
  alert.append(this.connectionToAppleServer.getServerHost() + “n”);

  /* Device token (shortened), Identifier and expiry */
  int l = useEnhancedNotificationFormat ? 4 : 8;
  alert.append(“” + deviceToken.substring(0, l) + “�” + deviceToken.substring(64 – l, 64) + (useEnhancedNotificationFormat ? ” [Id:” + identifier + “] ” + (payload.getExpiry() <= 0 ? “No-store” : “Exp:T+” + payload.getExpiry()) : “”) + “n”);

  /* Format & encoding */
  alert.append((useEnhancedNotificationFormat ? “Enhanced” : “Simple”) + ” format / ” + payload.getCharacterEncoding() + “” + “”);

  return alert.toString();
 }

 

推送方法

private void sendNotification(PushedNotification notification, boolean closeAfter) throws CommunicationException {
  try {
   Device device = notification.getDevice();
   Payload payload = notification.getPayload();
   try {
    payload.verifyPayloadIsNotEmpty();
   } catch (IllegalArgumentException e) {
    throw new PayloadIsEmptyException();
   } catch (Exception e) {
   }

   if (notification.getIdentifier() <= 0) notification.setIdentifier(newMessageIdentifier());
   if (!pushedNotifications.containsKey(notification.getIdentifier())) pushedNotifications.put(notification.getIdentifier(), notification);放入集合,
   int identifier = notification.getIdentifier();

以上为配置notification对象信息

   String token = device.getToken();
   // even though the BasicDevice constructor validates the token, we revalidate it in case we were passed another implementation of Device
   BasicDevice.validateTokenFormat(token);
   byte[] bytes = getMessage(token, payload, identifier, notification);

   /* Special simulation mode to skip actual streaming of message */
   boolean simulationMode = payload.getExpiry() == 919191;如果是仿真模式

   boolean success = false;

   BufferedReader in = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
   int socketTimeout = getSslSocketTimeout();
   if (socketTimeout > 0) this.socket.setSoTimeout(socketTimeout);
   notification.setTransmissionAttempts(0);
   // Keep trying until we have a success
   while (!success) {
    try {
     logger.debug(“Attempting to send notification: ” + payload.toString() + “”);
     logger.debug(”  to device: ” + token + “”);
     notification.addTransmissionAttempt();
     boolean streamConfirmed = false;
     try {
      if (!simulationMode) {
       this.socket.getOutputStream().write(bytes);
       streamConfirmed = true;
      } else {
       logger.debug(“* Simulation only: would have streamed ” + bytes.length + “-bytes message now..”);
      }
     } catch (Exception e) {
      if (e != null) {
       if (e.toString().contains(“certificate_unknown”)) {
        throw new InvalidCertificateChainException(e.getMessage());
       }
      }
      throw e;
     }
     logger.debug(“Flushing”);
     this.socket.getOutputStream().flush();
     if (streamConfirmed) logger.debug(“At this point, the entire ” + bytes.length + “-bytes message has been streamed out successfully through the SSL connection”);

     success = true;
     logger.debug(“Notification sent on ” + notification.getLatestTransmissionAttempt());
     notification.setTransmissionCompleted(true);

    } catch (IOException e) {
     // throw exception if we surpassed the valid number of retry attempts
     if (notification.getTransmissionAttempts() >= retryAttempts) {
      logger.error(“Attempt to send Notification failed and beyond the maximum number of attempts permitted”);
      notification.setTransmissionCompleted(false);
      notification.setException(e);
      logger.error(“Delivery error”, e);
      throw e;

     } else {
      logger.info(“Attempt failed (” + e.getMessage() + “)… trying again”);
      //Try again
      try {
       this.socket.close();
      } catch (Exception e2) {
       // do nothing
      }
      this.socket = connectionToAppleServer.getSSLSocket();
      if (socketTimeout > 0) this.socket.setSoTimeout(socketTimeout);
     }
    }
   }
  } catch (CommunicationException e) {
   throw e;
  } catch (Exception ex) {

   notification.setException(ex);
   logger.error(“Delivery error: ” + ex);
   try {
    if (closeAfter) {
     logger.error(“Closing connection after error”);
     stopConnection();
    }
   } catch (Exception e) {
   }
  }
 }

//给单独设备推送一个消息

public PushedNotification sendNotification(Device device, Payload payload) throws CommunicationException {
  return sendNotification(device, payload, true);
 }


 //给指定设备组发送推送,并关闭连接
 public PushedNotifications sendNotifications(Payload payload, List<Device> devices) throws CommunicationException, KeystoreException {
  PushedNotifications notifications = new PushedNotifications();
  for (Device device : devices)
   notifications.add(sendNotification(device, payload, false, SEQUENTIAL_IDENTIFIER));
  stopConnection();
  return notifications;
 }


 //给指定设备组推送 并在推送完毕后关闭连接
 public PushedNotifications sendNotifications(Payload payload, Device… devices) throws CommunicationException, KeystoreException {
  PushedNotifications notifications = new PushedNotifications();
  for (Device device : devices)
   notifications.add(sendNotification(device, payload, false, SEQUENTIAL_IDENTIFIER));
  stopConnection();
  return notifications;
 }

//给指定的设备发送推送
 public PushedNotification sendNotification(Device device, Payload payload, boolean closeAfter) throws CommunicationException {
  return sendNotification(device, payload, closeAfter, SEQUENTIAL_IDENTIFIER);
 }

//给指定的用户发送推送
 public PushedNotification sendNotification(Device device, Payload payload, int identifier) throws CommunicationException {
  return sendNotification(device, payload, false, identifier);
 }


 //给指定的设备发送推送
 public PushedNotification sendNotification(Device device, Payload payload, boolean closeAfter, int identifier) throws CommunicationException {
  PushedNotification pushedNotification = new PushedNotification(device, payload, identifier);
  sendNotification(pushedNotification, closeAfter);
  return pushedNotification;
 }

最后

以上就是高挑夕阳为你收集整理的iOS推送javaPNS源码解析七,推送信息类的全部内容,希望文章能够帮你解决iOS推送javaPNS源码解析七,推送信息类所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(54)

评论列表共有 0 条评论

立即
投稿
返回
顶部