zoukankan      html  css  js  c++  java
  • 81、iOS本地推送与远程推送详解

    一、简介

      分为本地推送和远程推送2种。可以在应用没打开甚至手机锁屏情况下给用户以提示。它们都需要注册,注册后系统会弹出提示框(如下图)提示用户石否同意,如果同意则正常使用;如果用户不同意则下次打开程序也不会弹出改提示框,需要用户到设置里面设置。一共有三种提示类型:

    UIUserNotificationTypeBadge:应用图标右上角的信息提示    

    UIUserNotificationTypeSound:播放提示音

    UIUserNotificationTypeAlert:提示框

    二、本地推送

    1.注册与处理

    代码如下:

    /// 一般在在启动时注册通知,程序被杀死,点击通知后调用此程序
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    - (void)registerAPN {

        // 注册通知

        if (@available(iOS 10.0, *)) { // iOS10 以上

            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

            [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {

                

            }];

        } else {// iOS8.0 以上

            UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil];

            [[UIApplication sharedApplication] registerUserNotificationSettings:setting];

        }

    }

    
        return YES;
    }
    /// 程序没有被杀死(处于前台或后台),点击通知后会调用此程序
    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification {
        // 这里添加处理代码
    }

    可以看到,处理代码有两个方法,一个是

    - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification;
    另一个是
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions;
    如果程序没有被杀死,即处于前台或者后台,那么调用前者;如果程序被杀死,则调用后者。

    - (void)applicationWillResignActive:(UIApplication *)application {

        #pragma mark -->NSLog(@" ===> 程序挂起 !");  比如:当有电话进来或者锁屏,这时你的应用程会挂起,在这时,UIApplicationDelegate委托会收到通知,调用 applicationWillResignActive 方法,你可以重写这个方法,做挂起前的工作,比如关闭网络,保存数据。

    }

    - (void)applicationDidEnterBackground:(UIApplication *)application {

        #pragma mark --> NSLog(@" ===> 程序进入后台 !");

    }

    - (void)applicationWillEnterForeground:(UIApplication *)application {

        #pragma mark --> NSLog(@" ===> 程序进入前台 !");

        [[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];

    }

    - (void)applicationDidBecomeActive:(UIApplication *)application {

        #pragma mark -->  NSLog(@" ===> 程序重新激活 !"); 应用程序在启动时,在调用了 applicationDidFinishLaunching 方法之后也会调用 applicationDidBecomeActive 方法,所以你要确保你的代码能够分清复原与启动,避免出现逻辑上的bug。(大白话就是说:只要启动app就会走此方法)。

    }

    - (void)applicationWillTerminate:(UIApplication *)application {

        #pragma mark --> 当用户按下按钮,或者关机,程序都会被终止。当一个程序将要正常终止时会调用 applicationWillTerminate 方法。但是如果长主按钮强制退出,则不会调用该方法。这个方法该执行剩下的清理工作,比如所有的连接都能正常关闭,并在程序退出前执行任何其他的必要的工作.

    }

    2.发送通知

    - (void)addLocalNotice {

        if (@available(iOS 10.0, *)) {

            UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];

            UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];

            // 标题

            content.title = @"测试标题";

            content.subtitle = @"测试通知副标题";

            // 内容

            content.body = @"测试通知的具体内容";

            // 声音

    //        content.sound = [UNNotificationSound defaultSound];

            content.sound = [UNNotificationSound soundNamed:@"Alert_ActivityGoalAttained_Salient_Haptic.caf"];

            // 角标 (我这里测试的角标无效,暂时没找到原因)

            content.badge = @1;

            // 多少秒后发送,可以将固定的日期转化为时间

            NSTimeInterval time = [[NSDate dateWithTimeIntervalSinceNow:2] timeIntervalSinceNow];

    //        NSTimeInterval time = 10;

            // repeats,是否重复,如果重复的话时间必须大于60s,要不会报错

            UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:time repeats:NO];

            

            /*

            //如果想重复可以使用这个,按日期

            // 周一早上 8:00 上班

            NSDateComponents *components = [[NSDateComponents alloc] init];

            // 注意,weekday默认是从周日开始

            components.weekday = 2;

            components.hour = 8;

            UNCalendarNotificationTrigger *calendarTrigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];

            */

            // 添加通知的标识符,可以用于移除,更新等操作

            NSString *identifier = @"noticeId";

            UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger];

            

            [center addNotificationRequest:request withCompletionHandler:^(NSError *_Nullable error) {

                NSLog(@"成功添加推送");

            }];

        }else {

            UILocalNotification *notif = [[UILocalNotification alloc] init];

            // 发出推送的日期

            notif.fireDate = [NSDate dateWithTimeIntervalSinceNow:5];

            // 推送的内容

            notif.alertBody = @"你已经10秒没出现了";

            // 可以添加特定信息

            notif.userInfo = @{@"noticeId":@"00001"};

            // 角标

            notif.applicationIconBadgeNumber = 1;

            // 提示音

            notif.soundName = UILocalNotificationDefaultSoundName;

            // 每周循环提醒

            notif.repeatInterval = NSCalendarUnitWeekOfYear;

            

            [[UIApplication sharedApplication] scheduleLocalNotification:notif];

        }

    }

    3. 取消通知

    // 取消所有本地通知
    [application cancelAllLocalNotifications];

    三、远程推送

    与Android上我们自己实现的推送服务不一样,Apple对设备的控制非常严格,消息推送的流程必须要经过APNs(Apple Push Notification service).

    一般情况下如果一个程序退到后台就不能运行代码(Audio、VoIP等等可以在后台运行),或者程序退出后,那么它就和对应应用的后台服务器断开了链接,就收不到服务器发送的信息了,但是每台设备只要联网就会和苹果的APNs服务器建立一个长连接(persistent IP connection),这样只要通过苹果的APNs服务器,我们自己的服务器就可以间接的和设备保持连接了,示意图如下:

    使用步骤:

    1 勾选Backgroud Modes -> Remote notifications,主要是iOS7之后,苹果支持后台运行,如果这里打开后,当接收到远程推送后,程序在后台也可以做一些处理,如下图所示:

     

    2.远程推送机制

      

    你的应用服务端将消息发送到apple的APNS服务器,APNS服务器将消息推送到指定的Iphone,最后由Iphone负责将消息推送至你的APP。在此先不说这个过程是如何实现的,仅仅看这个流程,你可能会觉得,在你们服务端和客户端之间增加了一个apple的APNS,不是增加开发者的负担么?其实结果恰恰相反,因为apple对推送的统一管理,使我们开发者的工作变得异常简单。

     3.服务端如何连接到客户端的

     如果你是做android开发的,你一定非常了解长链接与心跳包。事实上,大部分的android应用的推送也确实是通过长链接来实现的。因为android系统的开放性,APP是很容易做到自启动和后台长链接的,而心跳验证,就是始终保证长链接属于接通状态,然后由服务端直接推送消息。如果IOS开发者也采用这种思路,就十分困难了,在IOS中想要保持一个APP服务始终不被系统杀死,我只能说太难了。通过上面的流程图,对比android的推送思路,我们很容易明白,IOS中其实也始终有一个长链接,那就是系统本身,这个长链接始终与APNS服务器相连,然后统一管理所有应用程序的推送。

    4.
    这是IOS推送机制的优势?

    1、因为推送的服务端是appleID的验证用户,推送可靠性会高。

    2、所有推送消息由APNS统一管理,效率高。

    3、在客户端只需系统维护一个长链接,节省了用户流量消耗和手机的性能消耗,并且提高了安全性,使得有恶意推送和流氓软件的几率降低。

    准备工作:参考大神博客https://www.cnblogs.com/ludashi/p/4093454.html

  • 相关阅读:
    用反射的方法获取枚举值(数据字典)
    使用哈希加盐法来为密码加密(补充JAVA的实现)
    Mybatis使用TypeHandler实现数据的加解密转换
    学习Hadoop和Spark的好的资源
    Scala基本语法学习笔记
    Scala & IntelliJ IDEA环境搭建升级版:在JAVA中调用Scala的helloworld
    Scala & IntelliJ IDEA:环境搭建、helloworld
    【转】解决yum安装软件报Couldn't resolve host 'mirrorlist.centos.org问题
    使用nfs映射远程服务器磁盘目录
    MacOS系统升级后,IDEA的SVN不好用的问题
  • 原文地址:https://www.cnblogs.com/qiangzheVSruozhe/p/10577884.html
Copyright © 2011-2022 走看看