日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

接入 iOS

更新時(shí)間:

本文將向您詳細(xì)介紹將消息推送服務(wù)接入 iOS 客戶端的接入流程。

前提條件

您已將工程接入到 mPaaS。更多信息,請(qǐng)參見以下內(nèi)容:

操作步驟

要使用消息推送服務(wù),您需要完成以下接入步驟:

  1. 添加消息推送 SDK。

    根據(jù)您接入 mPaaS 采用的接入方式,添加消息推送 SDK。

    在接入 mPaaS 的三種接入方式中,均可以添加消息推送 SDK。

  2. 配置工程。需要在工程的 TARGETS 設(shè)置中開啟以下兩項(xiàng)配置:

    • Capabilities > Push Notificationspush-ca

    • Capabilities > Background Modes > Remote notificationspush-back

  3. 使用 SDK。下面對(duì)不同接入方式的 SDK 使用進(jìn)行說(shuō)明。

    • 基于 mPaaS 框架接入

      1. 注冊(cè) deviceToken(非必需)。

        消息推送 SDK 在應(yīng)用啟動(dòng)完成時(shí),會(huì)自動(dòng)請(qǐng)求注冊(cè) deviceToken,一般情況下您無(wú)需請(qǐng)求注冊(cè) deviceToken。但是當(dāng)特殊情況下(比如啟動(dòng)時(shí)有隱私管控,阻止一切網(wǎng)絡(luò)請(qǐng)求時(shí))您需要在管控授權(quán)后,再次觸發(fā)注冊(cè) deviceToken,示例代碼如下:

        - (void)registerRemoteNotification
        {
            // 注冊(cè)推送
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {// 10.0+
                UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
                center.delegate = self;
                [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        
                        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert|UNAuthorizationOptionSound|UNAuthorizationOptionBadge)
                                              completionHandler:^(BOOL granted, NSError * _Nullable error) {
                            // Enable or disable features based on authorization.
                            if (granted) {
                                dispatch_async(dispatch_get_main_queue(), ^{
                                    [[UIApplication sharedApplication] registerForRemoteNotifications];
                                });
                            }
                        }];
        
                }];
            } else {// 8.0,9.0
                UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge                                                                                         |UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil];
                [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
                [[UIApplication sharedApplication] registerForRemoteNotifications];
            }
        }
      2. 獲取 deviceToken 并綁定 userId。

        與基于 iOS 原生框架相比,基于 mPaaS 框架的應(yīng)用的生命周期被 mPaaS 框架接管,應(yīng)用獲取 deviceToken 的回調(diào)方法有所不同,代碼示例如下:

        // import <PushService/PushService.h>
        // 在 DTFrameworkInterface 分類中重寫如下方法
        - (DTFrameworkCallbackResult)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
        {
            [[PushService sharedService] setDeviceToken:deviceToken];
            [[PushService sharedService] pushBindWithUserId:@"your userid(需替換)" completion:^(NSException *error) {
            }];
        
            return DTFrameworkCallbackResultContinue;
        }
        說(shuō)明

        消息推送 SDK 同時(shí)提供了解綁的接口 - (void)pushUnBindWithUserId:(NSString *)userId completion:(void (^)(NSException *error))completion;,用于解除設(shè)備的 deviceToken 與當(dāng)前應(yīng)用的 userId 的綁定。如在用戶切換賬號(hào)后,可以調(diào)用解綁接口。

      3. 綁定用戶手機(jī)號(hào)。

        重要

        目前,僅杭州非金融區(qū)提供短信補(bǔ)充服務(wù)。

        將 deviceToken 和用戶的手機(jī)號(hào)碼綁定。綁定手機(jī)號(hào)碼后,用戶就可以通過該手機(jī)號(hào)碼收到相關(guān)推送短信。

        // 若在綁定接口上傳手機(jī)號(hào)碼,則可以使用短信補(bǔ)充服務(wù)
        - (void)pushBindWithUserId:(NSString *)userId phoneNumber:(NSString *)phoneNumber completion:(void (^)(NSException *error))completion;
      4. 接收推送的消息。

        基于 mPaaS iOS 框架的應(yīng)用,由于其生命周期被 mPaaS 框架接管,與基于 iOS 原生框架相比,收到消息的回調(diào)方法不同,代碼示例如下:

        // import <PushService/PushService.h>
        // 在 DTFrameworkInterface 分類中重寫如下方法
        - (DTFrameworkCallbackResult)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
        {
            // userInfo 為推送消息內(nèi)容,業(yè)務(wù)解析處理
            return DTFrameworkCallbackResultContinue;
        }
      5. 統(tǒng)計(jì)消息的打開率。

        為了統(tǒng)計(jì)消息在客戶端的打開率,您需要在 App 消息被用戶打開時(shí),調(diào)用 PushServicepushOpenLogReport 接口(10.1.32 及以上版本可用)上報(bào)消息打開事件。該事件上報(bào)后,您可以在 mPaaS 控制臺(tái)中的 消息推送 > 概覽 頁(yè)面中查看消息打開率的統(tǒng)計(jì)數(shù)據(jù)。

        /**
         * 打開推送消息的上報(bào)接口,用于統(tǒng)計(jì)推送消息的打開率
         * @param  userInfo 消息的 userInfo
         * @return
         */
        - (void)pushOpenLogReport:(NSDictionary *)userInfo;
    • 基于已有工程接入

      在基于已有工程且使用 mPaaS 插件或 CocoaPods 接入 iOS 客戶端的情況下,您需要完成以下操作。

      1. 注冊(cè) deviceToken(非必需)

        消息推送 SDK 在應(yīng)用啟動(dòng)完成時(shí),會(huì)自動(dòng)請(qǐng)求注冊(cè) deviceToken,一般情況下您無(wú)需請(qǐng)求注冊(cè) deviceToken。但是當(dāng)特殊情況下(比如啟動(dòng)時(shí)有隱私管控,阻止一切網(wǎng)絡(luò)請(qǐng)求時(shí))您需要在管控授權(quán)后,再次觸發(fā)注冊(cè) deviceToken,示例代碼如下:

        - (void)registerRemoteNotification
        {
            // 注冊(cè)推送
            if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 10.0) {// 10.0+
                UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
                center.delegate = self;
                [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
        
                        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert|UNAuthorizationOptionSound|UNAuthorizationOptionBadge)
                                              completionHandler:^(BOOL granted, NSError * _Nullable error) {
                            // Enable or disable features based on authorization.
                            if (granted) {
                                dispatch_async(dispatch_get_main_queue(), ^{
                                    [[UIApplication sharedApplication] registerForRemoteNotifications];
                                });
                            }
                        }];
        
                }];
            } else {// 8.0,9.0
                UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge                                                                                         |UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil];
                [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
                [[UIApplication sharedApplication] registerForRemoteNotifications];
            }
        }
      2. 獲取 deviceToken 并綁定 userId。

        mPaaS 提供的消息推送 SDK 中封裝了向 APNs 服務(wù)器注冊(cè)的邏輯,在程序啟動(dòng)后,Push SDK 自動(dòng)向 APNs 服務(wù)器注冊(cè)。您可在注冊(cè)成功的回調(diào)方法中獲取 APNs 下發(fā)的 deviceToken,然后調(diào)用 PushService 的接口方法,上報(bào)綁定 userId 至移動(dòng)推送核心。

        // import <PushService/PushService.h>
        - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
        {
            [[PushService sharedService] setDeviceToken:deviceToken];
            [[PushService sharedService] pushBindWithUserId:@"your userid(需替換)" completion:^(NSException *error) {
            }];
        
        }

        消息推送 SDK 同時(shí)提供了解綁的接口 - (void)pushUnBindWithUserId:(NSString *)userId completion:(void (^)(NSException *error))completion;,用于解除設(shè)備的 deviceToken 與當(dāng)前應(yīng)用的 userId 的綁定。如在用戶切換賬號(hào)后,可以調(diào)用解綁接口。

      3. 綁定用戶手機(jī)號(hào)。

        重要

        目前,僅杭州非金融區(qū)提供短信補(bǔ)充服務(wù)。

        將 deviceToken 和用戶的手機(jī)號(hào)碼綁定。綁定手機(jī)號(hào)碼后,用戶就可以通過該手機(jī)號(hào)碼收到相關(guān)推送短信。

        // 若在綁定接口上傳手機(jī)號(hào)碼,則可以使用短信補(bǔ)充服務(wù)
        - (void)pushBindWithUserId:(NSString *)userId phoneNumber:(NSString *)phoneNumber completion:(void (^)
      4. 接收推送的消息。

        客戶端收到推送的消息后,如果用戶點(diǎn)擊查看,系統(tǒng)將啟動(dòng)相應(yīng)應(yīng)用。可在 AppDelegate 的回調(diào)方法中完成收到 push 消息后的邏輯處理。

        • 在 iOS 10 以下系統(tǒng)中,通知欄消息或靜默消息的處理方法如下:

            // iOS 10 以下 Push 冷啟動(dòng)處理
            - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
            NSDictionary *userInfo = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
            if ([[[UIDevice currentDevice] systemVersion] doubleValue] < 10.0) {
                // iOS 10 以下 Push 冷啟動(dòng)處理
            }
          
            return YES;
          }
          
            // App 在前臺(tái)時(shí),普通推送的處理方法;App 在前臺(tái)或后臺(tái)時(shí),靜默推送的處理方法;iOS 10 以下系統(tǒng),通知欄消息處理方法
            - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler
            {
                //處理接受到的消息
            }
        • 在 iOS 10 及以上系統(tǒng)中,您需要實(shí)現(xiàn)以下代理方法來(lái)監(jiān)聽通知欄消息:

            // 注冊(cè) UNUserNotificationCenter delegate 
            if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 10.0) {
                    UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
                    center.delegate = self;
              }
          
             //應(yīng)用處于前臺(tái)時(shí)的遠(yuǎn)程推送接收
            - (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
            {
                NSDictionary *userInfo = notification.request.content.userInfo;
          
                if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
                    //應(yīng)用處于前臺(tái)時(shí)的遠(yuǎn)程推送接收
          
                } else {
                    //應(yīng)用處于前臺(tái)時(shí)的本地推送接收
          
                }
                completionHandler(UNNotificationPresentationOptionNone);
            }
          
            //應(yīng)用處于后臺(tái)或者活冷啟動(dòng)時(shí)遠(yuǎn)程推送接收
            - (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler
            {
                NSDictionary *userInfo = response.notification.request.content.userInfo;
          
                if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
                    //應(yīng)用處于后臺(tái)或者活冷啟動(dòng)時(shí)遠(yuǎn)程推送接收
          
                } else {
                    //應(yīng)用處于前臺(tái)時(shí)的本地推送接收
          
                }
                completionHandler();
          
            }
      5. 統(tǒng)計(jì)消息的打開率。

        基于已有工程統(tǒng)計(jì)消息打開率的操作方法和基于 mPaaS 框架完全相同。

  4. 配置推送證書。

    要使用 mPaaS 消息推送控制臺(tái)推送消息,您需要在控制臺(tái)中配置 APNs 推送證書。該證書必須是與客戶端簽名對(duì)應(yīng)的推送證書,否則客戶端會(huì)收不到推送消息。有關(guān)詳細(xì)的配置說(shuō)明,查看 配置 iOS 推送通道

后續(xù)操作

  • 在 mPaaS 消息推送控制臺(tái)配置完 APNs 證書后,可以按設(shè)備維度向應(yīng)用推送消息。消息推送服務(wù)使用蘋果的 APNs 服務(wù)向客戶端推送消息,更多信息請(qǐng)參見 蘋果及國(guó)外安卓設(shè)備推送流程

  • 上報(bào)用戶 ID 并由服務(wù)端綁定用戶和設(shè)備后,可以按用戶維度向應(yīng)用推送消息。

代碼示例

點(diǎn)擊此處 下載示例代碼包。

相關(guān)鏈接

Live Activity 消息推送

iOS 在 16.1 版本中推出了一個(gè)新功能:Live Activity(實(shí)時(shí)活動(dòng))。該功能可以將實(shí)時(shí)活動(dòng)展示在鎖屏界面上,幫助用戶從鎖定的屏幕實(shí)時(shí)獲知各種活動(dòng)的進(jìn)展。在主工程中,可以使用 ActivityKit 框架來(lái)開啟、更新、結(jié)束實(shí)時(shí)活動(dòng)。其中,更新和結(jié)束實(shí)時(shí)活動(dòng)還可以使用遠(yuǎn)程推送來(lái)實(shí)現(xiàn)。在 widget extension 中,可以使用 SwiftUI 和 WidgetKit 來(lái)創(chuàng)建 Live Activity 的界面。其中,Live Activity 遠(yuǎn)程推送更新功能,不支持 .p12 證書,因此需要用戶配置 .p8 證書。

同一個(gè)項(xiàng)目中可以同時(shí)開啟多個(gè) Live Activity,不同的 Live Activity,其 token 是不同的。

Live Activity 蘋果官方文檔

Live Activity 使用限制

  • 只能在 iOS 16.1 版本以上的系統(tǒng)上運(yùn)行。

  • 只支持 iPhone 設(shè)備,不支持 iPadOS,macOS,tvOS,watchOS。

  • 單個(gè) Live Activity 最多可運(yùn)行 8 個(gè)小時(shí),超過 8 小時(shí)系統(tǒng)會(huì)自動(dòng)停止 Live Activity 的運(yùn)行,但是不會(huì)立即從屏幕上被移除。

  • 停止運(yùn)行超過 4 小時(shí)后系統(tǒng)會(huì)自動(dòng)將其從屏幕上移除。

  • 資源文件尺寸需符合要求,詳情請(qǐng)參見 蘋果開發(fā)者文檔

  • 推送的內(nèi)容不能超過 4KB。

接入客戶端

配置工程支持 Live Activity

  1. 在主工程的 Info.plist 文件中添加一個(gè)鍵值對(duì),key 為 NSSupportsLiveActivities,值為 YES

    image.png

  2. 新建 Widget Extension,如果項(xiàng)目中已有,可跳過此步驟。

    image

    image

代碼實(shí)現(xiàn)

  1. 創(chuàng)建 model。

    • 在主工程代碼里新建一個(gè) swift 文件,在其中定義 ActivityAttributes 以及 Activity.ContentState。以下代碼為示例代碼,請(qǐng)按照實(shí)際業(yè)務(wù)編寫。

    import SwiftUI
    import ActivityKit
    
    struct PizzaDeliveryAttributes: ActivityAttributes {
        public typealias PizzaDeliveryStatus = ContentState
      
        public struct ContentState: Codable, Hashable {
            var driverName: String
            var estimatedDeliveryTime: ClosedRange<Date>
            
            init(driverName: String, estimatedDeliveryTime: ClosedRange<Date>) {
                self.driverName = driverName
                self.estimatedDeliveryTime = estimatedDeliveryTime
            }
            init(from decoder: Decoder) throws {
                let container: KeyedDecodingContainer<PizzaDeliveryAttributes.ContentState.CodingKeys> = try decoder.container(keyedBy: PizzaDeliveryAttributes.ContentState.CodingKeys.self)
                self.driverName = try container.decode(String.self, forKey: PizzaDeliveryAttributes.ContentState.CodingKeys.driverName)
                if let deliveryTime = try? container.decode(TimeInterval.self, forKey: PizzaDeliveryAttributes.ContentState.CodingKeys.estimatedDeliveryTime) {
                    self.estimatedDeliveryTime = Date()...Date().addingTimeInterval(deliveryTime * 60)
                } else if let deliveryTime = try? container.decode(String.self, forKey: PizzaDeliveryAttributes.ContentState.CodingKeys.estimatedDeliveryTime) {
                    self.estimatedDeliveryTime = Date()...Date().addingTimeInterval(TimeInterval.init(deliveryTime)! * 60)
                } else {
                    self.estimatedDeliveryTime = try container.decode(ClosedRange<Date>.self, forKey: PizzaDeliveryAttributes.ContentState.CodingKeys.estimatedDeliveryTime)
                }
            }
        }
      
        var numberOfPizzas: Int
        var totalAmount: String
    }
    
    • 主工程 target 和 Activity 都要選上。

    • 收到的推送消息由系統(tǒng)處理,開發(fā)者不能攔截。

    • ContentState 中為可以動(dòng)態(tài)更新的數(shù)據(jù),推送 Live Activity 通知時(shí),動(dòng)態(tài)更新的參數(shù)名和類型要和 ContentState 里配置的對(duì)應(yīng)上。

    • 如果有些數(shù)據(jù)需要經(jīng)過加工,需要重寫 ActivityAttributes.ContentStatedecoder 方法。

  2. 創(chuàng)建界面。

    在 Widget Extension 中創(chuàng)建實(shí)時(shí)活動(dòng)的界面。創(chuàng)建 Widget 并返回一個(gè) Activity Configuration

    具體 UI 請(qǐng)按照自己的業(yè)務(wù)編寫。

    image

  3. 使用 WidgetBundle。

    如果目標(biāo) App 既支持小組件也支持實(shí)時(shí)活動(dòng),請(qǐng)使用 WidgetBundle。

    import WidgetKit
    import SwiftUI
    
    @main
    structIslandBundle: WidgetBundle {
    varbody: someWidget {
    Island()
    IslandLiveActivity()
    }
    }
  4. 開啟實(shí)時(shí)活動(dòng)。

    func startDeliveryPizza() {
        let pizzaDeliveryAttributes = PizzaDeliveryAttributes(numberOfPizzas: 1, totalAmount:"$99")
        let initialContentState = PizzaDeliveryAttributes.PizzaDeliveryStatus(driverName: "TIM", estimatedDeliveryTime: Date()...Date().addingTimeInterval(15 * 60))
        do {
            let deliveryActivity = try Activity<PizzaDeliveryAttributes>.request(
                attributes: pizzaDeliveryAttributes,
                contentState: initialContentState,
                pushType: .token)
        } catch (let error) {
            print("Error requesting pizza delivery Live Activity \(error.localizedDescription)")
        }
    }
  5. 提交 Token。

    開啟實(shí)時(shí)活動(dòng)成功后,通過 pushTokenUpdates 方法拿到系統(tǒng)返回的 Live Activity 的推送 Token。 調(diào)用 PushService 的 liveActivityBindWithActivityId:pushToken:filter:completion: 方法上報(bào)。

    在上報(bào) Token 的同時(shí),需要將該實(shí)時(shí)活動(dòng)的標(biāo)識(shí)一起上報(bào)。實(shí)時(shí)活動(dòng)推送時(shí)需要用到該標(biāo)識(shí),服務(wù)器根據(jù)該標(biāo)識(shí)確認(rèn)推送目標(biāo)。該實(shí)時(shí)活動(dòng)的標(biāo)識(shí)請(qǐng)自定義,不同 Live Activity,其 id 不同(如果唯一會(huì)導(dǎo)致推送出現(xiàn)問題),同一個(gè) Live Activity,在 Token 更新時(shí)不要更換 id。

    說(shuō)明

    ActivityKit 為 swift 語(yǔ)言框架,且不支持直接 OC 調(diào)用,使用該框架 API 的時(shí)候,請(qǐng)?jiān)?swift 文件里面調(diào)用。由于 MPPushSDK 是 OC 語(yǔ)言,涉及到 swift 調(diào)用 OC,需要?jiǎng)?chuàng)建橋接文件。并在橋接文件里導(dǎo)入:#import <MPPushSDK/MPPushSDK.h>

    let liveactivityId = UserDefaults.standard.string(forKey: "pushTokenUpdates_id") ?? "defloutliveactivityId"
    Task {
        for await tokenData in deliveryActivity.pushTokenUpdates {
            let newToken = tokenData.map { String(format: "%02x", $0) }.joined()       
            PushService.shared().liveActivityBind(withActivityId: liveactivityId, pushToken: newToken, filter: .call) { excpt in
                guard let excpt = excpt else {
                    ///上報(bào)成功
                    return
                }
                if "callRepeat" == excpt.reason {
                    ///重復(fù)調(diào)用,請(qǐng)忽略
                    print("pushTokenUpdates_id——重復(fù)調(diào)用")
                } else {
                    ///上報(bào)失敗
                }
            }
        }
    }

    上報(bào)成功后,則可以使用實(shí)時(shí)活動(dòng)的標(biāo)識(shí)推送更新。

    說(shuō)明

    由于 iPhone 的 pushTokenUpdates 會(huì)同時(shí)被調(diào)用兩次,即在多個(gè) Live Activity 的場(chǎng)景中,新創(chuàng)建 Live Activity 時(shí)之前的 LiveActivity pushTokenUpdates 又會(huì)被重新喚醒一次,所以 SDK 提供了過濾功能,并由參數(shù) filter 控制:

    • filter 為 MPPushServiceLiveActivityFilterAbandon時(shí),SDK 會(huì)自動(dòng)直接拋棄重復(fù)的調(diào)用,不給回調(diào)。

    • filter 為 MPPushServiceLiveActivityFilterCall時(shí),SDK 會(huì)自動(dòng)過濾掉本次請(qǐng)求,給失敗回調(diào)(callRepeat),此時(shí) error.reason@"callRepeat",請(qǐng)忽略。

    • filter 為 MPPushServiceLiveActivityFilterReRefuse時(shí),SDK 內(nèi)部不做過濾。

    • 重復(fù)地調(diào)用相同的 activityId,相同的 pushToken 時(shí),如果上報(bào)失敗,客戶端重新上報(bào)不會(huì)被認(rèn)為是相同的調(diào)用。

    下面是 MPPushServiceLiveActivityFilterType 的定義:

    typedef NS_ENUM(NSInteger, MPPushServiceLiveActivityFilterType){
        MPPushServiceLiveActivityFilterAbandon,//直接拋棄,不給回調(diào)
        MPPushServiceLiveActivityFilterCall,//過濾掉本次請(qǐng)求,給失敗回調(diào)(callRepeat)
        MPPushServiceLiveActivityFilterRefuse//不做過濾
    };