/** ソケットの再接続 */ private synchronized void reconnectNotificationSocket() { apnsInputMonitoringThread = null; // 既存の接続をクローズ ApnsUtil.close(apnsNotificationSocket); // パケット送信量をリセット packetSize = 0; // Socket取得 apnsNotificationSocket = null; apnsNotificationSocket = ApnsUtil.createAPNSGatewaySocket(isProduction, factory, socksProxy); // APNsからの入力待ちスレッドを開始 try { apnsInputMonitoringThread = new ApnsInputMonitoringThread(apnsNotificationSocket.getInputStream()); apnsInputMonitoringThread.start(); } catch (IOException e) { logger.info("APNs入力ストリーム取得エラー", e); } logger.debug("APNsへのSocket通信を構築または再構築しました。"); }
/** * PUSH通知(複数件送信) * * @param apnsNotificationList 送信データリスト * @return 送信結果 */ public synchronized ApnsResult push(List<ApnsNotification> apnsNotificationList) { logger.info("PUSH通知 - 開始"); try { // Socketの生成 reconnectNotificationSocket(); // 通知リスト読み込み位置 int pos = 0; packetSize = 0; while (true) { int i; for (i = pos; i < apnsNotificationList.size(); i++) { pos = i; // 通知情報取り出し ApnsNotification apnsNotification = apnsNotificationList.get(i); // 実行Mapに格納 executeApnsNotificationMapIdentifier.put( apnsNotification.getIdentifier(), apnsNotification); executeIndexMapApnsNotification.put(apnsNotification, i); logger.trace( "deviceToken:{}, payload:{}", apnsNotification.getToken(), apnsNotification.getPayload()); // バイナリデータに変換 byte[] pushData = apnsNotification.getNotificationBytes(); if (pushData == null) { logger.info( "PUSHデータを生成できませんでした。token={}, payload={}", apnsNotification.getToken(), apnsNotification.getPayload()); // エラーにステータス変更 apnsNotification.setPushStatus(PushStatus.ERROR); // 読み飛ばし continue; } // パケット量制限を超える場合は再接続 if (this.maxPacket != 0 && this.packetSize > this.maxPacket) { reconnectNotificationSocket(); } try { // PUSH通知 OutputStream os = apnsNotificationSocket.getOutputStream(); os.write(pushData); os.flush(); // パケット量加算 packetSize += pushData.length; // 実行済にステータス設定 apnsNotification.setPushStatus(PushStatus.DONE); } catch (IOException e) { // OutputStream書き込みエラー logger.debug("APNs通知情報送信エラー。リトライを試行します。", e); pos = processPushError(i, apnsNotificationList); // forループを抜けてリトライ break; } // 待機 ApnsUtil.sleep(pushIntervalMs); // エラー確認 if (apnsInputMonitoringThread.hasError()) { pos = processPushError(i, apnsNotificationList); // forループを抜けてリトライ break; } pos++; } // 終端まで達していない場合は残りを処理 if (pos < apnsNotificationList.size()) { continue; } // 1秒間待機(最終通信後のAPNsからの入力を待つ) ApnsUtil.sleep(1000); // エラー確認 if (apnsInputMonitoringThread.hasError()) { pos = processPushError(i, apnsNotificationList); // リトライ continue; } // 全件処理完了 break; } return createApnsSendResult(apnsNotificationList, true, null); } catch (Exception e) { logger.error("PUSH通知処理中にException発生。", e); return createApnsSendResult(apnsNotificationList, false, e); } finally { ApnsUtil.close(apnsNotificationSocket); logger.info("PUSH通知 - 終了"); } }