實現iOS應用PUSH功能

1. push原理

iOS push 工作機制可以用下圖簡要概括

  • Provider:應用自己的服務器;
  • APNS:Apple Push Notification Service的簡稱,蘋果的PUSH服務器;

push的主要工作流程是:

  • iOS設備連接網絡後,會自動與APNS保持類似TCP的長鏈接,等待APNS推送消息的到來;
  • 應用啓動時註冊消息推送,並獲取設備的在APNS中註冊的唯一設備標示deviceToken上傳給應用服務器(即Provider);
  • 在需要給應用推送消息時,Provider把push內容、接收push消息的deviceToken按APNS指定的格式打包好,發送給APNS;
  • APNS收到Provider發送的消息後,查找deviceToken指定的設備,如果該設備已經和APNS建立了連接,則立即將消息推送給該設備,如果設備不在線,則在該設備下次連接到APNS後將消息推送到設備。請注意蘋果並不保證推送一定成功;
  • 設備收到push消息後,iOS系統會根據SSL證書判斷這個push消息是發給那個應用的,進而啓動相應客戶端。

上述過程中,有兩個關鍵步驟需要自己處理的是:1.客戶端獲取deviceToken,並上傳到Provider;2.Provider發送push消息到APNS。這兩個步驟中都需要蘋果的push證書授權,下面就來介紹如何生成push證書,以及Provisioning Profile。

2. push證書及Provisioning Profile生成

  • 用付費帳號登錄到http://developer.apple.com/iphone/index.action

  • 生成push證書前要先生成開發證書

    生成開發證書的過程不詳細介紹,可以參考如何聯機調試和發佈程序。只是有一點需要注意的,生成開發證書過程中需要通過Keychain生成一個CSR文件,默認名爲CertificateSigningRequest.certSigningRequest,這個文件將在生成push證書的時候用到。

  • 創建一個App ID

    • 創建過程中Description可以任意填寫,比如叫push_demo
    • Bundle Identifier一般用com.company.appname這樣的格式,例如com.mycompany.demo

    注意:要用push功能的Bundle Identifier一定不能出現通配符,比如com.mycompany.*,這樣的名字是不能使用push的。

  • 生成Push SSL Certificate

    生成好App ID後點擊Configure進入配置頁。打開Enable for Apple Push Notification service選項,該選項下有Development Push SSL CertificateProduction Push SSL Certificate兩個SSL Certificate可以配置,前面一個是用來的開發的push證書,後面一個是用來發布的。我們以開發push證書爲例,點擊Development Push SSL Certificate->Configure,後面會要求選擇CSR文件,這就是生成開發證書時的CertificateSigningRequest.certSigningRequest文件,選擇好CSR後就生成好相應的SSL Certificate了。下載下來,保存名爲aps_developer.cer

  • 從Keychain中導出私鑰、設置好密碼,命名爲private_key.p12

  • 生成push證書

    • 這時我們一共得到3個文件:

      1. CertificateSigningRequest.certSigningRequest
      2. private_key.p12
      3. aps_developer.cer
    • 將aps_developer.cer轉成pem格式

      openssl x509 -in aps_developer.cer -inform DER -out aps_developer.pem -outform PEM 
      
    • 將private_key.p12格式的私鑰轉換成private_key.pem

      openssl pkcs12 -nocerts -out private_key.pem -in private_key.p12
      

      這一步會要求輸入p12私鑰的密碼,以及設置新生成的pem的密碼。

    • 創建用於服務端的SSL p12格式證書,命名爲aps_developer.p12

      openssl pkcs12 -export -in aps_developer.pem -inkey private_key.pem -certfile CertificateSigningRequest.certSigningRequest -name "aps_developer" -out aps_developer.p12
      

      這一步會要求輸入private_key.pem的密碼,注意不是private_key.p12的密碼。如果密碼錯誤,或者CertificateSigningRequest.certSigningRequest文件不匹配都不能正常生成aps_developer.p12文件,如果生成的aps_developer.p12文件大小是0,說明生成過程中出了問題,請檢查pem私鑰、密碼、以及CertificateSigningRequest.certSigningRequest是否正確。

      aps_developer.p12就是Provider向APNS發送push消息需要的SSL證書。把這個證書和密碼提供給服務端,服務端就可以發送push消息給APNS了。這時服務端已經可以工作了,但客戶端還必須配置相應的Provisioning Profile才能啓動應用的push功能。

      服務器配置需注意的是,由於我們生成的是開發環境的push證書,所以服務器應該連接APNS的sandbox環境地址:gateway.sandbox.push.apple.com:2195,如果應用正式發佈,就要連接正式環境,必須生成相應的發佈證書,並連接APNS正式環境地址:gateway.push.apple.com:2195

  • 生成Provisioning Profile

    • 新建Profile,命名爲push_dev;
    • 選擇相應證書;
    • App ID選擇push_demo;
    • 選擇設備;
    • 下載並安裝該Profile供開發使用;

3. Xcode證書設置、Info.plist設置

  • 用Xcode打開客戶端工程,設置Info.plist的Bundle identifier爲com.mycompany.demo
  • 打開工程設置,必須將證書設置爲與push_dev關聯的證書。

4. 客戶端獲取deviceToken

服務端要發送push消息給某一設備還必須知道該設備的deviceToken。應用運行後獲取到deviceToken,然後上傳給服務器,下面介紹應用如何獲取deviceToken。應用必須先註冊使用push功能。

1
2
3
4
5
6
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
      // do something
      // ...
  }

在AppDelegate中添加下面方法來獲取deviceToken:

1
2
3
4
5
6
7
8
9
  - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
      NSString *token = [NSString stringWithFormat:@"%@", deviceToken];
      NSLog(@"%@", token);
  }

  - (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
      NSLog(@"%@", error);
  }

應用獲取到deviceToken後,上傳給Provider,Provider就可以用這個deviceToken給這個設備push消息了。

5. Payload格式及自定義數據

服務器配置好證書並拿到deviceToken後就可以向APNS發送消息了。發送消息的格式如下圖所示:

Payload就是push的消息負載,這就是應用需要關心的數據。 Payload是一個JSON字典,最大值是 256 字節,超過這個限制,APNS將拒絕轉發。基本格式如下:

1
2
3
4
5
6
7
8
  {
    "aps": {
      "alert":"Hello Push!",
      "badge":1,
      "sound":"default"
    }
  }

必須包含aps鍵值。badge表示應用程序圖標顯示的數字,sound表示收到push的提示音。 Payload的具體結構參考Apple Push Notification Service

要在這個結構中新增自定義數據,請加在aps空間之外。比如後臺推送消息給應用同時要求應用打開某個頁面:

1
2
3
4
5
6
7
8
9
  {
    "aps": {
      "alert":"Hello Push!",
      "badge":1,
      "sound":"default"
    },
    "page":"home"
  }

後臺告訴客戶端收到這個push後打開應用的主頁,這裏的page、home都是自己定義的。必須注意的是,Payload大小不能超過限制,所以可以把自定義數據更簡化點,比如可以把home與編號1對應,page簡寫爲p,這樣"p":1表示打開主頁,可以縮小Payload的大小。

6. 客戶端接收push消息

iOS系統收到push消息後,如果用戶點擊查看,系統將根據證書啓動相應應用。如果應用已經啓動,將調用AppDelegate的方法:

1
2
3
4
  - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
      // userInfo 就是push消息的Payload
  }

如果應用還沒有啓動,通過push冷啓動後,仍然能在啓動後獲取Payload:

1
2
3
4
5
  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
      NSDictionary* userInfo = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
      NSLog(@"Payload: %@", userInfo);
  }

目前爲止,push功能基本就完成了,可以開始push功能測試了,如果服務器還沒開發完成,或者想快速測試是否能正常push,可以使用下面的代碼實現後臺push測試。發送push前要配置好SSL證書,以及deviceToken和Payload結構。

object c 版本
c 版本
java 版本
php 版本

還有個小問題,當Payload設置了badge,應用圖標上將一直顯示一個數字提示,如果要清除數字提示,或者設置成其他數字,調用下面函數就可以完成。

1
2
  [[UIApplication sharedApplication] setApplicationIconBadgeNumber:number];

number爲0就會清除數字提示。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章