A brief analysis of the iOS message push

The purpose of message push is to remind users of something happening inside the APP at the current time and attract users to open the APP when the APP is cut to the background or the mobile phone lock screen.

Notification push has three types of notification:

  1. UIUserNotificationTypeBadge: application of BadgeValue little red circle
  2. Tip UIUserNotificationTypeSound: sound or vibration
  3. UIUserNotificationTypeAlert: show Alert Message content
Based on the principle of not disturbing users, APP message push requires users’ consent and registration in advance.




Whether to enable push.png

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    // The application starts the registration push
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0)
    {
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge |
                                                UIUserNotificationTypeAlert |
                                                UIUserNotificationTypeSound 
                                                categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
    }
    else
    {
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeAlert | 
                                                    UIRemoteNotificationTypeBadge | 
                                                    UIUserNotificationTypeSound]; }...return YES;
}

// In iOS8, you need to add this method. Register the push service through the new API. If the user does not allow push, the application will call this method at startup to get the user's Settings
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings 
{
    [application registerForRemoteNotifications];
}

// Failed to register the call
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error 
{
    NSLog(@" Remote notification registration failed: %@",error);
}Copy the code

If the user chooses to allow, apple will according to bundleID and mobile phone UDID deviceToken generated, then calls the application: didRegisterForRemoteNotificationsWithDeviceToken: Method to obtain the DeviceToken

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSLog(@"test:%@",deviceToken); // Obtain the device Token. If the Token is obtained, the registration is successful
    // The application should send the DeviceToken to the APP's server, which stores it for sending push messages
}Copy the code

There are two types of notification push:

  • LocalNotification
  • Offline notification (PushNotification or RemoteNotification)

Local message push

  1. It is used for tool software, such as transaction reminder software, to send notification prompts at a certain point in time.
  2. Real-time communication software, the form of notification client, such as real-time communication software, after receiving the chat message, notify the phone ring or vibration, or modify the TabBar Item BadgeValue, etc.

Offline message push

APP cuts to the background and prompts the user when the APP is killed.

Callback after receiving notification

After receiving the notification and clicking the local notification, the following two situations occur:

  1. Cut from the background to the front desk to open (program is not kill off) received local notifications will call didReceiveLocalNotification agent method, when applied at the front desk, received local push notifications will call, but don’t usually do




PNG representation of local push on mobile phone

- (void) application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification 
{
    switch (application.applicationState)
    {
        case UIApplicationStateActive:       // The activity is in the foreground, the screen is not locked
        {
        // The application is in the foreground when the local push is received
        // The interface changes the code, generally is the TabBar Item BadgeValue change
            [self playSoundAndVibration]; / / ringing
            return;
        }
            break;
        case UIApplicationStateInactive:     // When entering the notification bar, click a message to go back to the background
        {
            // When a local push is received, the application is cut to the background
            // Specific business execution code, jump or other
            [self playSoundAndVibration]; / / ringing
        }
            break;
        case UIApplicationStateBackground: // The program enters the background
        {
           NSLog(@ "% @",message);
           [self playSoundAndVibration]; / / ringing
           [self showNotificationWithMessage:message];
        }
              break;
        default:
            break; }} - (void)playSoundAndVibration
{
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval)
    {
        // If the time since the last ring and vibration is too short, skip the ring
        NSLog(@"skip ringing & vibration %@, %@"[NSDate date], self.lastPlaySoundDate);
        return;
    }
    self.lastPlaySoundDate = [NSDate date]; // Save the last ring time
    [[EMCDDeviceManager sharedInstance] playNewMessageSound]; // When the message is received, the audio is played
    [[EMCDDeviceManager sharedInstance] playVibration]; // When receiving a message, it vibrates
}

- (void)showNotificationWithMessage:(EMMessage *)message
{
    UILocalNotification *notification = [[UILocalNotification alloc] init]; // Send local push
    notification.fireDate = [NSDate date]; // When the notification is triggered

    notification.alertBody = NSLocalizedString(@"receiveMessage".@"you have a new message");

    notification.hasAction = NO;
    notification.timeZone = [NSTimeZone defaultTimeZone];
    NSTimeInterval timeInterval = [[NSDate date] timeIntervalSinceDate:self.lastPlaySoundDate];
    if (timeInterval < kDefaultPlaySoundInterval)
    {
        NSLog(@"skip ringing & vibration %@, %@"[NSDate date], self.lastPlaySoundDate);
    }
    else
    {
        notification.soundName = UILocalNotificationDefaultSoundName;
        self.lastPlaySoundDate = [NSDate date];
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:message.messageType] forKey:kMessageType];
    [userInfo setObject:message.conversationChatter forKey:kConversationChatter];
    notification.userInfo = userInfo;

    [[UIApplication sharedApplication] scheduleLocalNotification:notification]; // Send notifications
    [UIApplication sharedApplication].applicationIconBadgeNumber += 1;
}Copy the code
  1. Kill the program and run it again

Open the application, application will be executed: didFinishLaunchingWithOptions: callback method, the difference is that the normal startup launchOptions parameter is null, if the other way will start launchOptions with specific parameters.

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{
    if (launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]) 
    {
        NSDictionary*userInfo = [launchOptions objectForKey:@"UIApplicationLaunchOptionsRemoteNotificationKey"];
        / / the userInfo NSDictionary * = launchOptions [UIApplicationLaunchOptionsLocalNotificationKey];
        // Kill the app, click local notifications to open it, and pass the launchOptions to the app
        // So that we can make the corresponding jump etc
        [selfdidReceiveRemoteNotification:userInfo]; }...return YES;
}

#pragma mark - Kills processes and pushes information offline
- (void)didReceiveRemoteNotification:(NSDictionary *)userInfo
{
    // Facilitate the parsing of offline push messages
    NSError *parseError = nil;
    NSData  *jsonData = [NSJSONSerialization dataWithJSONObject:userInfo
                                                        options:NSJSONWritingPrettyPrinted error:&parseError];
    NSString *str =  [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"apns.content".@"Apns content")
                                                  message:str
                                                   delegate:nil
                                          cancelButtonTitle:NSLocalizedString(@"ok".@"OK")
                                          otherButtonTitles:nil];
    [alert show];
}Copy the code

The implementation of the push delegate method in the AppDelegate:

First APP installation:
-- > didRegisterForRemoteNotificationsWithDeviceToken is called;--> The system prompts the user whether to enable push;-- > didRegisterUserNotificationSettings is called;Copy the code
Non-initial startup:
--> Push is rejected:didRegisterUserNotificationSettingsIs called;--> Push is allowed-- > didRegisterForRemoteNotificationsWithDeviceToken is invoked-- > didRegisterUserNotificationSettings is invokedCopy the code
Users modify push Settings during operation:
-- > to refuse to allow: didRegisterForRemoteNotificationsWithDeviceToken is invoked--> Allow to deny: do nothingCopy the code

A little doubt??

In the Kill off the APP, click on the local push message, not in didFinishLaunchingWithOptions do after iOS7.0 processing, only in the following functions do processing, but I in the actual development, there is no such strange.

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo 
                                        fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
{
    // userInfo
}Copy the code