天天看點

JAVA背景對接蘋果APNS(VOIP)實作推送

最近公司需要用蘋果APNs實作類似微信視訊接電話的效果,檢視了蘋果官網有VOIP這個東西,于是進行了研究開發。

首先總結一下接入流程:

  1. 在開發者中心申請對應的證書(推送證書,VOIP證書)
  2. IOS 注冊推送到APNs(直接調用PushKit 的API即可),回掉中的DeviceToken發送到我們自己的服務端(服務端儲存)
  3. 伺服器通發送HTTP推送消息請求到APNs伺服器。(這一步就是伺服器發送推送消息)
  4. IOS接受推送并處理。

BiBi一句。研究任何一樣東西首先檢視官網資料,千萬别怕英文,不知道的單詞可以查,雖然我也是個英語小白。不懂的然後再網上搜尋資料,這樣有利于學習!

蘋果開發者中心推送PushKit文檔

進入Setting Up a Remote Notification Server

可以看到整個APNs的工作流程。

JAVA背景對接蘋果APNS(VOIP)實作推送

下面基于“伺服器通發送HTTP推送消息請求到APNs伺服器”這一步進行開發。

  • 推送消息描述如下圖。大概意思就是App注冊,服務端建構消息發送到APNs。認證的方式有兩種:

    1、基于Token。使用開發者中心申請的.p8檔案和Key ID進行Token認證

    2、基于推送證書,使用.p12證書認證

    JAVA背景對接蘋果APNS(VOIP)實作推送
    此處由于公司要求我們使用.p12檔案進行開發。
  • 使用pushy進行開發。使用最新包!結合官網進行開發。
<dependency>
   <groupId>com.turo</groupId>
   <artifactId>pushy</artifactId>
   <version>0.13.10</version>
</dependency>
           

下面是我寫的一個APNs的一個推送Demo。

@Slf4j
public class APNsUtils {
    private static ApnsClient apnsClient = null;
    public static void main(String[] args) throws Exception {
    //IOS等終端裝置注冊後傳回的DeviceToken
        String deviceToken ="5d7cf67dd6ab56c6d699f86806682e7d99e019216df734f4c57196b84790b718";
//        String deviceToken = "74abd7d51c58a8db995fa53c3508a72481a9d4ad56e7ed1f7d12362f798a6906";
        /**
         * Use the voip push type for notifications that provide information about an incoming Voice-over-IP (VoIP)
         * call. For more information, see Responding to VoIP Notifications from PushKit.
         * If you set this push type, the apns-topic header field must use your app’s bundle ID with .voip
         * appended to the end. If you’re using certificate-based authentication,
         * you must also register the certificate for VoIP services.
         * The topic is then part of the 1.2.840.113635.100.6.3.4 or 1.2.840.113635.100.6.3.6 extension.
         */
         //這是你的主題,大多數情況是bundleId,voip需要在bundleId加上.voip。對應文檔中的apns-topic
         //此處可以參考https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/sending_notification_requests_to_apns?language=objc
      
        String topic = "com.voip.test.voip";
        String payload = "{ \"aps\" : {\"alert\" : \"測試\", \"sound\" : \"default\", \"badge\" :1},\"liguoxin\":\"liguoxin\" }";
        //有效時間
        Date invalidationTime= new Date(System.currentTimeMillis() + 60 * 60 * 1000L );
        //發送政策 apns-priority 10為立即 5為省電
        DeliveryPriority priority= DeliveryPriority.IMMEDIATE;
        //推送方式,主要有alert,background,voip,complication,fileprovider,mdm
        PushType pushType = VOIP;
        //推送的合并ID,相同的 apns-collapse-id會在App中合并
        String collapseId= UUID.randomUUID().toString();
        //apnsId 唯一标示,如果不傳,APNs會給我們生成一個
        UUID apnsId = UUID.randomUUID();
        //構造一個APNs的推送消息實體
        SimpleApnsPushNotification msg = new SimpleApnsPushNotification(deviceToken,topic,payload,invalidationTime,priority,pushType,collapseId,apnsId);
		//開始推送
        PushNotificationFuture<SimpleApnsPushNotification,PushNotificationResponse<SimpleApnsPushNotification>> future = getAPNSConnect().sendNotification(msg);
        PushNotificationResponse<SimpleApnsPushNotification> response = future.get();
        System.out.println(response.getRejectionReason());
        //如果傳回的消息中success為true那麼成功,否則失敗!
        //如果失敗不必驚慌,rejectionReason字段中會有失敗的原因。對應官網找到原因即可
        //https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/handling_notification_responses_from_apns?language=objc
        
        System.out.println("------------->"+response);
    }

    public static ApnsClient getAPNSConnect() {

        if (apnsClient == null) {
            try {
                /**
                 * Development server: api.sandbox.push.apple.com:443
                 * Production server: api.push.apple.com:443
                 *
                 * api.development.push.apple.com這個域名蘋果官網現在找不到了
                 */

                String SANDBOX_APNS_HOST = "api.sandbox.push.apple.com";
//                /Users/liguoxin/Desktop/p12/deve_push.p12
//                 /Users/liguoxin/Desktop/p12/distri_push.p12
               //四個線程
                EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);
                apnsClient = new ApnsClientBuilder().setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)
                        .setClientCredentials(new File("/Users/liguoxin/Desktop/p12/distri_push.p12"),"111111")
                        .setConcurrentConnections(4).setEventLoopGroup(eventLoopGroup).build();


//                EventLoopGroup eventLoopGroup = new NioEventLoopGroup(4);
//                apnsClient = new ApnsClientBuilder().setApnsServer(ApnsClientBuilder.DEVELOPMENT_APNS_HOST)
//                        .setSigningKey(ApnsSigningKey.loadFromPkcs8File(new File("/Users/liguoxin/Desktop/p12/deve_push.p8"),
//                                "我的temid", "我的keyid"))
//                        .setConcurrentConnections(4).setEventLoopGroup(eventLoopGroup).build();
            } catch (Exception e) {
                log.error("ios get pushy apns client failed!");
                e.printStackTrace();
            }
        }

        return apnsClient;

    }
}
           

推送結果如下,傳回success為true,推送成功。現在檢視手機已經收到消息了

JAVA背景對接蘋果APNS(VOIP)實作推送

繼續閱讀