This topic describes how to integrate the Mobile Push Service(MPS) with an iOS client.
Prerequisites
You have integrated your project with mPaaS. For more information, see the following topics:
Procedure
To use MPS, complete the following steps:
Add the MPS SDK.
Add the MPS SDK based on the method you used to integrate with mPaaS.
You can add the Message Push SDK to any of the three mPaaS connection types.
If you used the Integrate based on the mPaaS framework or Integrate based on an existing project and use the mPaaS plug-in method, select Push (Message Push) on the project editing page to add the MPS SDK.

If you used the Integrate based on an existing project and use CocoaPods method, add the dependency for the MPS component by adding
mPaaS_pod "mPaaS_Push"to the Podfile. Then, runpod installto add the MPS SDK.
Configure the project. In the TARGETS settings of your project, enable the following two capabilities:
Capabilities > Push Notifications

Capabilities > Background Modes > Remote notifications

Use the SDK. The following sections describe how to use the SDK for different integration methods.
Integrate based on the mPaaS framework
Register the deviceToken (optional)
The MPS SDK automatically requests to register the deviceToken when the application starts. You do not usually need to request this registration manually. However, in special cases, such as when privacy controls block all network requests at startup, you must trigger the deviceToken registration again after authorization is granted. The following code provides an example:
- (void)registerRemoteNotification { // Register for push notifications 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]; } }Obtain the deviceToken and bind the userId.
The lifecycle of applications based on the mPaaS framework is managed by the framework itself, which differs from native iOS applications. Therefore, the callback method for obtaining the deviceToken is also different. The following code provides an example:
// import <PushService/PushService.h> // Rewrite the following method in the DTFrameworkInterface category - (DTFrameworkCallbackResult)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [[PushService sharedService] setDeviceToken:deviceToken]; [[PushService sharedService] pushBindWithUserId:@"your userid(replace it)" completion:^(NSException *error) { }]; return DTFrameworkCallbackResultContinue; }NoteThe MPS SDK also provides a detach interface,
- (void)pushUnBindWithUserId:(NSString *)userId completion:(void (^)(NSException *error))completion;, to detach the device's deviceToken from the current application's userId. For example, you can call this interface after a user switches accounts.Bind the user's mobile phone number.
ImportantCurrently, the supplemental text message service is only available in the Hangzhou non-finance region.
Bind the deviceToken to the user's mobile phone number. After binding, the user can receive relevant push text messages to that number.
// If you upload a mobile phone number in the binding interface, you can use the text message supplement service - (void)pushBindWithUserId:(NSString *)userId phoneNumber:(NSString *)phoneNumber completion:(void (^)(NSException *error))completion;Receive push messages.
Because the lifecycle of applications based on the mPaaS iOS framework is managed by the framework, the callback method for receiving messages is different from that of native iOS applications. The following code provides an example:
// import <PushService/PushService.h> // Rewrite the following method in the DTFrameworkInterface category - (DTFrameworkCallbackResult)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { // userInfo is the content of the push message. Parse and process it as needed. return DTFrameworkCallbackResultContinue; }Track the message open rate.
To track the message open rate on the client, you must call the
pushOpenLogReportinterface ofPushService(available in version 10.1.32 and later) to report the message open event when a user opens the message. After this event is reported, you can view the open rate statistics on the Mobile Push Service > Overview page in the mPaaS console./** * The reporting interface for opening a push message, used to track the open rate of push messages * @param userInfo The userInfo of the message * @return */ - (void)pushOpenLogReport:(NSDictionary *)userInfo;
Integrate based on an existing project
If you integrated with the iOS client based on an existing project using the mPaaS plug-in or CocoaPods, complete the following operations.
Register the deviceToken (optional).
The MPS SDK automatically requests to register the deviceToken when the application starts. You do not usually need to request this registration manually. However, in special cases, such as when privacy controls block all network requests at startup, you must trigger the deviceToken registration again after authorization is granted. The following code provides an example:
- (void)registerRemoteNotification { // Register for push notifications 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]; } }Obtain the deviceToken and bind the userId.
The MPS SDK provided by mPaaS encapsulates the logic for registering with the Apple Push Notification service (APNs) server. After the application starts, the Push SDK automatically registers with the APNs server. You can obtain the deviceToken issued by APNs in the successful registration callback method. Then, call the
PushServiceinterface method to report and bind the userId to the MPS core.// import <PushService/PushService.h> - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { [[PushService sharedService] setDeviceToken:deviceToken]; [[PushService sharedService] pushBindWithUserId:@"your userid(replace it)" completion:^(NSException *error) { }]; }The MPS SDK also provides a detach interface,
- (void)pushUnBindWithUserId:(NSString *)userId completion:(void (^)(NSException *error))completion;, to detach the device's deviceToken from the current application's userId. For example, you can call this interface after a user switches accounts.Bind the user's mobile phone number.
ImportantCurrently, the supplemental text message service is only available in the Hangzhou non-finance region.
Bind the deviceToken to the user's mobile phone number. After binding, the user can receive relevant push text messages to that number.
// If you upload a mobile phone number in the binding interface, you can use the text message supplement service - (void)pushBindWithUserId:(NSString *)userId phoneNumber:(NSString *)phoneNumber completion:(void (^)Receive push messages.
After the client receives a push message, if the user taps to view it, the system launches the corresponding application. You can handle the logic for receiving push messages in the callback method of
AppDelegate.For systems earlier than iOS 10, handle notification bar messages or silent messages as follows:
// Handle push cold start for iOS versions earlier than 10 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSDictionary *userInfo = [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey]; if ([[[UIDevice currentDevice] systemVersion] doubleValue] < 10.0) { // Handle push cold start for iOS versions earlier than 10 } return YES; } // Method for handling normal pushes when the app is in the foreground. Method for handling silent pushes when the app is in the foreground or background. Method for handling notification bar messages for systems earlier than iOS 10. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { //Process the received message }For iOS 10 and later, you must implement the following delegate methods to listen for notification bar messages:
// Register UNUserNotificationCenter delegate if ([[[UIDevice currentDevice] systemVersion] doubleValue] >= 10.0) { UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter]; center.delegate = self; } //Receive remote push when the app is in the foreground - (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]]) { //Receive remote push when the app is in the foreground } else { //Receive local push when the app is in the foreground } completionHandler(UNNotificationPresentationOptionNone); } //Receive remote push when the app is in the background or during a cold start - (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]]) { //Receive remote push when the app is in the background or during a cold start } else { //Receive local push when the app is in the foreground } completionHandler(); }
Track the message open rate.
The method for tracking the message open rate for an existing project is the same as for the mPaaS framework.
Configure a push certificate.
To push messages using the mPaaS MPS console, you must configure an APNs push certificate in the console. This certificate must match the client signature. Otherwise, the client will not receive push messages. For more information, see Configure an iOS push channel.
What to do next
After you configure the APNs certificate in the mPaaS MPS console, you can push messages to the application by device. The MPS uses Apple's APNs to push messages to clients. For more information, see Push process for Apple and non-Chinese mainland Android devices.
After you report the user ID and the server binds the user to the device, you can push messages to the application by user.
Code sample
Click here to download the sample code package.
Related links
Live Activity message push
iOS 16.1 introduced a new feature: Live Activity. This feature displays real-time activities on the lock screen, helping users stay informed about the progress of various activities. In the main project, you can use the ActivityKit framework to start, update, and end a Live Activity. You can also use remote push notifications to update and end a Live Activity. In the widget extension, you can use SwiftUI and WidgetKit to create the Live Activity UI. The Live Activity remote push update feature does not support .p12 certificates. You must configure a .p8 certificate.
You can start multiple Live Activities in the same project. Different Live Activities have different tokens.
Live Activity official Apple documentation
Live Activity limits
Requires iOS 16.1 or later.
Supports only iPhone devices. It does not support iPadOS, macOS, tvOS, or watchOS.
A single Live Activity can run for a maximum of 8 hours. After 8 hours, the system automatically ends the Live Activity, but it is not immediately removed from the lock screen.
After being ended for more than 4 hours, the system automatically removes it from the lock screen.
The size of resource files must meet the requirements. For more information, see the Apple Developer documentation.
The push content cannot exceed 4 KB.
Integrate with the client
Configure the project to support Live Activity
In the
Info.plistfile of the main project, add a key-value pair. Set the key toNSSupportsLiveActivitiesand the value toYES.Create a Widget Extension. If your project already has one, skip this step.
Code implementation
Create a model.
In the main project code, create a new Swift file. In this file, define
ActivityAttributesandActivity.ContentStateas needed. The following code provides an example.
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 }You must select both the main project target and the Activity.
The system processes received push messages. Developers cannot intercept them.
The
ContentStatecontains data that can be dynamically updated. When pushing a Live Activity notification, the parameter names and types for dynamic updates must match those configured inContentState.If some data requires processing, you must override the
decodermethod ofActivityAttributes.ContentState.
Create the UI.
In the Widget Extension, create the Live Activity UI. Create a Widget that returns an
ActivityConfiguration.Implement the UI code based on your requirements.
Use WidgetBundle.
If the target app supports both widgets and Live Activities, use WidgetBundle.
import WidgetKit import SwiftUI @main structIslandBundle: WidgetBundle { varbody: someWidget { Island() IslandLiveActivity() } }Start the Live Activity.
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)") } }Submit the token.
After the Live Activity starts successfully, obtain the push token for the Live Activity from the system through the
pushTokenUpdatesmethod. Call theliveActivityBindWithActivityId:pushToken:filter:completion:method of PushService to report the token.When reporting the token, you must also provide a unique identifier for the Live Activity. The server uses this identifier to target pushes. You must customize this identifier and ensure it is unique for each Live Activity. Using the same ID for different Live Activities will cause push failures. Do not change the identifier for an active Live Activity, even when its token is updated.
NoteActivityKit is a Swift framework and does not support direct calls from Objective-C. When using this framework's API, you must call it from a Swift file. Because the mPaaS Push SDK is written in Objective-C, you must create a bridging header to call its methods from Swift. In the bridging header, import:
#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 { ///Reported successfully return } if "callRepeat" == excpt.reason { ///Repeated call, please ignore print("pushTokenUpdates_id——Repeated call") } else { ///Report failed } } } }After the token is reported successfully, you can use the Live Activity identifier to push updates.
NoteBecause
pushTokenUpdateson an iPhone can be called multiple times, in scenarios with multiple Live Activities, creating a new Live Activity may cause thepushTokenUpdatesmethod of a previous Live Activity to be called again. Therefore, the SDK provides a filtering feature controlled by the filter parameter:When filter is
MPPushServiceLiveActivityFilterAbandon, the SDK automatically discards the repeated call without a callback.When filter is
MPPushServiceLiveActivityFilterCall, the SDK discards the repeated request and provides a failure callback. In this case,error.reasonis@"callRepeat". You can ignore this error.When `filter` is set to
MPPushServiceLiveActivityFilterReRefuse, the SDK does not perform any internal filtering.If a report fails, a subsequent attempt from the client to report the same activityId and pushToken is not considered a repeated call.
The following is the definition of
MPPushServiceLiveActivityFilterType:typedef NS_ENUM(NSInteger, MPPushServiceLiveActivityFilterType){ MPPushServiceLiveActivityFilterAbandon,//Discard directly, no callback MPPushServiceLiveActivityFilterCall,//Filter this request, provide failure callback (callRepeat) MPPushServiceLiveActivityFilterRefuse//Do not filter };