1. 程式人生 > >swift 遠端通知(二)接收

swift 遠端通知(二)接收

//
//  AppDelegate.swift
//  apnstest
//
//  Created by targetcloud on 2016/11/20.
//  Copyright © 2016年 targetcloud. All rights reserved.
//

import UIKit
import UserNotifications

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        if #available(iOS 10.0, *) {
            let center = UNUserNotificationCenter.current()
            center.requestAuthorization(options: UNAuthorizationOptions(rawValue : UNAuthorizationOptions.alert.rawValue | UNAuthorizationOptions.badge.rawValue | UNAuthorizationOptions.sound.rawValue)){ (granted: Bool, error:Error?) in
                if granted {
                    print("success")
                }
            }
            UIApplication.shared.registerForRemoteNotifications()
//            center.delegate = self
        }else if #available(iOS 8.0, *) {
            // 請求授權
            let type = UIUserNotificationType.alert.rawValue | UIUserNotificationType.badge.rawValue | UIUserNotificationType.sound.rawValue
            let set = UIUserNotificationSettings(types: UIUserNotificationType(rawValue: type), categories: nil)
            UIApplication.shared.registerUserNotificationSettings(set)
            // 需要通過裝置UDID, 和app bundle id, 傳送請求, 獲取deviceToken
            UIApplication.shared.registerForRemoteNotifications()
        }else {
            let type = UIRemoteNotificationType(rawValue: UIRemoteNotificationType.alert.rawValue | UIRemoteNotificationType.sound.rawValue | UIRemoteNotificationType.badge.rawValue)
            UIApplication.shared.registerForRemoteNotifications(matching: type)
        }
        return true
    }
    
    // 當請求完畢之後, 會呼叫這個方法, 把獲取到的deviceToken 返回給我們
    //04a359d9 ce5f9886 18db2072 602c0884 e8f3dcf0 4747ae8a 20863c20 eb0a8a6d
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        // 傳送給我們自己的伺服器
//        var token: String = ""
//        for i in 0..<deviceToken.count {
//            token += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
//        }
//        print(token)

        let tokenString = deviceToken.hexString
        print(">token: \(tokenString)")
        
        print(deviceToken)
    }
    
    // 當接收到遠端通知,以下2種模式生效
    // 1、APP在前臺
    // 2、從後臺進入到前臺(包含鎖屏到進入前臺)
    // App完全退出是不會執行這個方法的
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
        print("接收到遠端通知-〈1〉")
    }

    /*
     You've implemented -[<UIApplicationDelegate> application:didReceiveRemoteNotification:fetchCompletionHandler:], but you still need to add "remote-notification" to the list of your supported UIBackgroundModes in your Info.plist.
     ->在Capabilities中的Background Modes中開啟Remote notification
     
     同時實現了兩個接收方法只會呼叫下面這個
     
      業務需求: 只要接收到了通知, 不管當前APP 的狀態, 是在後臺, 還是鎖屏, 都直接執行這個方法
      1> 必須勾選後臺模式Remote Notification ;
      2> 告訴系統是否有新的內容更新(執行完成程式碼塊)
      3> 設定傳送通知的格式("content-available":"XXX")
     {"aps":{"alert":{"title":"標題","subtitle":"子標題","body":"來了一些遠端推送資訊."},"badge":1}}
     ->只有點選了通知後才會執行接收方法
     {"aps":{"alert":{"title":"標題","subtitle":"子標題","body":"來了一些遠端推送資訊."},"badge":1,"content-available":"XXX"}}
     ->不點選通知也會執行接收方法
    */
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        print("接收到遠端通知-〈2〉")
        
        let tv = UITextView(frame: CGRect(x: 0, y: 44, width: 300, height: 300))
        tv.backgroundColor = UIColor.cyan
        tv.text = "完全退出App也會呼叫這個方法"
        window?.rootViewController?.view.addSubview(tv)
        
        // 呼叫系統回撥程式碼塊的作用
        // 1> 系統會估量App消耗的電量,並根據傳遞的UIBackgroundFetchResult 引數記錄新資料是否可用
        // 2> 呼叫完成的處理程式碼時,應用的介面縮圖會自動更新
        //    縮圖是指兩次command+shift+h會看到tv(針對本例,UITextView已經在縮圖中更新了)
        completionHandler(.newData)
    }

}

extension Data {
    var hexString: String {
        return map { String(format: "%02.2hhx", arguments: [$0]) }.joined()
    }
}

->Capabilities中的Background Modes中開啟Remote notification


另外的話也開啟一下這個


/*
由於第二個接收方法功能強大,我們一般使用第二個接收方法,但需要說明的有2點:
     在有隻要接收到了通知,不管當前APP的狀態(是在後臺,還是鎖屏),都直接執行這個接收方法的業務需求時,需要做到上面程式碼註釋中提到的3點
     1> 必須勾選後臺模式Remote Notification 
     2> 告訴系統是否有新的內容更新(執行完成程式碼塊)
     3> 設定傳送通知的格式("content-available":"XXX")
          其中執行系統程式碼塊的作用是
          1> 系統會估量App消耗的電量,並根據傳遞的UIBackgroundFetchResult引數記錄新資料是否可用
          2> 呼叫完成的處理程式碼時,應用的介面縮圖會自動更新 
          其中"content-available":"XXX”的作用是
          1> {"aps":{"alert":{"title":"標題","subtitle":"子標題","body":"來了一些遠端推送資訊."},"badge":1}}
               ->只有點選了通知後才會執行接收方法
          2>{"aps":{"alert":{"title":"標題","subtitle":"子標題","body":"來了一些遠端推送資訊."},"badge":1,"content-available":"XXX"}}
               ->不點選通知也會執行接收方法
*/