Voice Over IP (VoIP) Best Practices
markdown
[原文網址](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/OptimizeVoIP.html#//apple_ref/doc/uid/TP40015243-CH30)
Voice over Internet Protocol (VoIP) 讓使用者可以透過網路撥打、接聽電話。因為 VoIP 非常仰賴網路,使得手機非常耗電。就算是沒有通話的時候 VoIP APP 還是持續待機消耗電量。
## 利用 VoIP 推播來避免不間斷的連結
在過去, VoIP 必須持續與伺服器進行連結來接收來電與其他資訊。這代表著週期性的訊息在 APP 與伺服器間來回傳送以保持雙方的連結能夠持續,哪怕沒有 APP 沒有在使用狀態。這項技術導致裝置不斷的被喚醒、不斷的浪費電。而且如果使用者關掉 VoIP APP,他將錯過所有的來電。
有別於持續性的連結,開發者們應該使用 [PushKit framework](https://developer.apple.com/documentation/pushkit) - 允許 APP 接收伺服器推播的 API。每次收到推播時,APP 會被通知進行相關處理。舉例來說,VoIP APP 會跳出來電通知,讓使用者決定要接聽還是掛掉電話。
以下為使用 PushKit 來接收 VoIP 推播的優點:
* 只有收到 VoIP 推播時裝置才會被喚醒 - 省電
* 標準推播只有在使用者觸發後 APP 才能動作,而 VoIP 推播能直接讓你的 APP 進行處理
* VoIP 是無延遲且高優先權的推播
* VoIP 可以夾帶更多的資料
* 收到 VoIP 推播時你的 APP 會自動重啟,就算它當時不是啟動狀態
* 收到 VoIP 推播時你的 APP 能執行程式進行處理,哪怕它當時是在背景
※ 注意:PushKit VoIP 只支援 iOS 8.0 以後
## 準備接收 VoIP 推播
跟其他 APP 一樣,你的 VoIP APP 也需要開啟背景模式,在 Xcode Project > Capabilities , 勾選 VoIP
別忘記替你的 VoIP APP創建憑證。每個 VoIP APP 都需要一個導向專屬 APP ID 的 VoIP 服務憑證。 這個憑證允許你的推播伺服器跟 VoIP 服務連結。 點進 [Apple 開發者網站](https://developer.apple.com/certificates) 並創建憑證、下載、並導入 Keychain。
## 設定 VoIP 推播
為了使 APP 能收到 VoIP 推播,在 appDelegate (或其他地方) 連結 PushKit。然後創建 PKPushRegistry ,設定它的 delegate 並註冊以接收 VoIP 推播
### Objective - C
```objective-c
// Link to the PushKit framework
#import
// Trigger VoIP registration on launch
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self voipRegistration];
return YES;
}
// Register for VoIP notifications
- (void) voipRegistration {
dispatch_queue_t mainQueue = dispatch_get_main_queue()
// Create a push registry object
PKPushRegistry * voipRegistry = [[PKPushRegistry alloc] initWithQueue: mainQueue];
// Set the registry's delegate to self
voipRegistry.delegate = self;
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
}
```
### Swift
``` swift
// Link to the PushKit framework
import PushKit
// Trigger VoIP registration on launch
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary?) -> Bool {
self.voipRegistration()
return true
}
// Register for VoIP notifications
func voipRegistration {
let mainQueue = dispatch_get_main_queue()
// Create a push registry object
let voipRegistry: PKPushRegistry = PKPushRegistry(mainQueue)
// Set the registry's delegate to self
voipRegistry.delegate = self
// Set the push type to VoIP
voipRegistry.desiredPushTypes = [PKPushTypeVoIP]
}
```
下一步,實現 delegate 方法來註冊推播。如果你的 APP 會收到標準推播和 VoIP 推播,那你的 APP 會收到兩種不同的 push token。 為了收到推播,這種兩 token 都需要傳給伺服器。 ### Objective-C ``` objective-c // Handle updated push credentials - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials: (PKPushCredentials *)credentials forType:(NSString *)type { // Register VoIP push token (a property of PKPushCredentials) with server } ``` ### Swift ``` swift // Handle updated push credentials func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) { // Register VoIP push token (a property of PKPushCredentials) with server } ```
最後, 實現處理推播的 delegate 方法。如果你的 APP 在收到推播時不是執行狀態,它會自動啟動 ### Objective - C ``` objective -c // Handle incoming pushes - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { // Process the received push } ``` ### Swift ``` swift // Handle incoming pushes func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) { // Process the received push } ```
![](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/xcode_project_capabilities_backgroundmodes_2x.png)
![](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/Art/voip_certificate_creation_2x.png)
下一步,實現 delegate 方法來註冊推播。如果你的 APP 會收到標準推播和 VoIP 推播,那你的 APP 會收到兩種不同的 push token。 為了收到推播,這種兩 token 都需要傳給伺服器。 ### Objective-C ``` objective-c // Handle updated push credentials - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials: (PKPushCredentials *)credentials forType:(NSString *)type { // Register VoIP push token (a property of PKPushCredentials) with server } ``` ### Swift ``` swift // Handle updated push credentials func pushRegistry(registry: PKPushRegistry!, didUpdatePushCredentials credentials: PKPushCredentials!, forType type: String!) { // Register VoIP push token (a property of PKPushCredentials) with server } ```
最後, 實現處理推播的 delegate 方法。如果你的 APP 在收到推播時不是執行狀態,它會自動啟動 ### Objective - C ``` objective -c // Handle incoming pushes - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { // Process the received push } ``` ### Swift ``` swift // Handle incoming pushes func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) { // Process the received push } ```
留言
張貼留言