远程推送ios9&ios10

关于远程推送的原理可以参考这篇博客:
http://blog.tingyun.com/web/article/detail/571

模拟远程推送的工具:
https://github.com/stefanhafeneger/PushMeBaby
https://github.com/noodlewerk/NWPusher

ios8.0远程推送负载内容

内容格式必要要知道的啊,服务端一般会要我们客户端定义好格式给他们的。

每一条通知的消息都会组成一个JSON字典对象,其格式如下所示,示例中的key值为苹果官方所用key。自定义字段的时候要避开这些key值。
{
     "aps" : {  
         "alert"              :              {   // string or dictionary
            "title"          :   "string"
            "body"           :   "string",
            "title-loc-key"  :   "string or null"
            "title-loc-args" :   "array of strings or null"
            "action-loc-key" :   "string or null"
            "loc-key"        :   "string"
            "loc-args"       :   "array of strings"
            "launch-image"   :   "string"
         },
          "badge"             :    number,
          "sound"             :    "string"
          "content-available" :    number;
          "category"          :    "string"
     },
}

aps:推送消息必须有的key

alert:推送消息包含此key值,系统就会根据用户的设置展示标准的推送信息
badge:在app图标上显示消息数量,缺少此key值,消息数量就不会改变,消除标记时把此key对应的value设置为0
sound:设置推送声音的key值,系统默认提示声音对应的value值为default
content-available:此key值设置为1,系统接收到推送消息时就会调用不同的回调方法,iOS7之后配置后台模式
category:UIMutableUserNotificationCategory's identifier 可操作通知类型的key值

title:简短描述此调推送消息的目的,适用系统iOS8.2之后版本
body:推送的内容
title-loc-key:功能类似title,附加功能是国际化,适用系统iOS8.2之后版本
title-loc-args:配合title-loc-key字段使用,适用系统iOS8.2之后版本
action-loc-key:可操作通知类型key值,不详细叙述
loc-key:参考title-loc-key
loc-args:参考title-loc-args
launch-image:点击推送消息或者移动事件滑块时,显示的图片。如果缺少此key值,会加载app默认的启动图片。
当然以上key值并不是每条推送消息都必带的key值,应当根据需求来选择所需要的key值,除了以上系统所提供的key值外,你还可以自定义自己的key值,来作为消息推送的负载,自定义key值与aps此key值并列。如下格式:

{
    "aps" : {
        "alert" : "Provider push messag.",
        "badge" : 9,
        "sound" : "toAlice.aiff"
    },
    "Id"   : 1314,               //  自定义key值
    "type" : "customType"        //  自定义key值
}
{
ios10.0
{
  "aps" : {
    "alert" : {
      "title" : "iOS远程消息,我是主标题!-title",
      "subtitle" : "iOS远程消息,我是主标题!-Subtitle",
      "body" : "Dely,why am i so handsome -body"
    },
    "category" : "alert",
    "badge" : "2"
  }
}

<h1>一、ios8的远程推送

        // 远程推送APNs必须使用真机调试,并且必须使用付费的开发者账号配置好对应的bundle ID和真机推送证书

        UIApplication.shared.registerForRemoteNotifications()
      
        let acceptAction = UIMutableUserNotificationAction()
        acceptAction.identifier = "acceptAction"
        acceptAction.title = "接受"
        acceptAction.activationMode = .foreground
        acceptAction.isDestructive = true
        
        //拒绝按钮
        let rejectAction = UIMutableUserNotificationAction()
        rejectAction.identifier = "rejectAction"
        rejectAction.title = "拒绝"
        rejectAction.activationMode = .background
        rejectAction.isAuthenticationRequired = true //需要解锁才能处理
        rejectAction.isDestructive = true
        
        //输入按钮
        let inputAction = UIMutableUserNotificationAction()
        inputAction.behavior = .textInput
        inputAction.title = "输入"
        inputAction.identifier = "textInput"
        inputAction.isDestructive = false
        inputAction.activationMode = .background
        
        let categorys = UIMutableUserNotificationCategory()
        categorys.identifier = "alert"
        let actions = [acceptAction,rejectAction,inputAction]
        
        categorys.setActions(actions, for: .default)
        var set = Set<UIMutableUserNotificationCategory>()
        set.insert(categorys)
        let repeatSettings = UIUserNotificationSettings(types: [.alert,.badge,.sound], categories: set)
        UIApplication.shared.registerUserNotificationSettings(repeatSettings)

    //获取DeviceToken成功
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        //Swift中获取deviceToken
        //http://stackoverflow.com/questions/9372815/how-can-i-convert-my-device-token-nsdata-into-an-nsstring
        var token: String = ""
        for i in 0..<deviceToken.count {
            token += String(format: "%02.2hhx", deviceToken[i] as CVarArg)
        }
        
        print(token)
    }

  //获取DeviceToken失败
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        
    }

1.用户点击通知会调用的方法

  //MARK: ios 8.0之后点击横幅会调用的方法
// ----------------------------------------------------------------------------
// 监听远程推送通知点击(优先级较低),接收到通知,用户点击进入才会调用该方法
 当接收到推送通知之后, 并且满足一下条件
 app 在前台时 ,会调用该方法
 app 从后台进入到前台 (App一开始在后台, app 锁屏),点击通知会调用该方法
 app 完全退出
 如果app 完全退出, 这时候,如果用户点击通知, 打开APP , 不会调用这个方法
 func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
     print(userInfo)
     UIApplication.shared.applicationIconBadgeNumber = 10
     completionHandler(.newData)
  }

2.一接收到通知就会立即调用该方法
效果: 当用户收到通知之后, 即使没有点击也会调用这个方法
条件:
1.需要勾选后台模式 remote notification,在后台
2.必须保证发送的推送通知格式, 包括 "content-available":"随便传"
3.执行completionHandler 回调代码块

// ----------------------------------------------------------------------------
// 监听远程推送通知点击(优先级较高),一接收到通知就会立即调用该方法
    当接收到推送通知之后, 并且满足一下条件
    当我们实现, 这个方法时, 上面一个方法不再执行
    计时APP 完全退出, 也会调用这个方法
    completionHandler : 统计我们处理的时间, 耗电量, 刷新预览图片
    {"aps" :
        {
            "alert" : "This is some fancy message.",
            "badge":1,
            "content-available":"随便传"
        }
    }
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler;

执行completionHandler 作用

1> 系统会估量App消耗的电量,并根据传递的UIBackgroundFetchResult 参数记录新数据是否可用
2> 调用完成的处理代码时,应用的界面缩略图会自动更新

如果想要接收到通知后,不要用户点击通知, 就执行以下代码, 那么必须有三个要求:
1> 必须勾选后台模式Remote Notification ;
2> 告诉系统是否有新的内容更新(执行完成代码块)
3> 服务器发送通知的格式必须要有content-available字段("content-available":"随便传")

<h1>二、ios10的远程推送

注册通知:
        UIApplication.shared.registerForRemoteNotifications()
        
        let action1 = UNNotificationAction(identifier: "action1", title: "接受邀请", options: .authenticationRequired)
        let action2 = UNNotificationAction(identifier: "action2", title: "查看邀请", options: .foreground)
        let action3 = UNNotificationAction(identifier: "action3", title: "取消", options: .destructive)
        let action4 = UNTextInputNotificationAction(identifier: "action4", title: "输入", options: .foreground, textInputButtonTitle: "发送", textInputPlaceholder: "tell me loudly")
        let category1 = UNNotificationCategory(identifier: "alert", actions: [action1,action2,action3,action4], intentIdentifiers: [], options: .customDismissAction)
        
        var set = Set<UNNotificationCategory>()
        set.insert(category1)
        center.setNotificationCategories(set)

  //MARK: ios10 收到通知(本地和远端)
    /*
     苹果把本地通知跟远程通知合二为一。区分本地通知跟远程通知的类是UNPushNotificationTrigger.h类中,UNPushNotificationTrigger的类型是新增加的,通过它,我们可以得到一些通知的触发条件 ,解释如下:
     
     UNPushNotificationTrigger (远程通知) 远程推送的通知类型
     UNTimeIntervalNotificationTrigger (本地通知) 一定时间之后,重复或者不重复推送通知。我们可以设置timeInterval(时间间隔)和repeats(是否重复)。
     UNCalendarNotificationTrigger(本地通知) 一定日期之后,重复或者不重复推送通知 例如,你每天8点推送一个通知,只要dateComponents为8,如果你想每天8点都推送这个通知,只要repeats为YES就可以了。
     UNLocationNotificationTrigger (本地通知)地理位置的一种通知,
     当用户进入或离开一个地理区域来通知。
     现在先提出来,后面我会一一代码演示出每种用法。还是回到两个很吊的代理方法吧

     */
    //MARK: App处于前台接收通知时
    /*
        1.下面这个代理方法,只会是app处于前台状态 前台状态 and 前台状态下才会走,后台模式下是不会走这里的
     */
    public func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Swift.Void) {
        
        if notification.request.trigger is UNPushNotificationTrigger {
            //远程通知
            print("ios10.0 远程通知")
        }else {
            //本地通知
            print("ios10.0 收到本地通知")
        }
        
        completionHandler([.badge,.sound,.alert])
        /*
         4.不管前台后台状态下。推送消息的横幅都可以展示出来!后台状态不用说,前台时需要在前台代理方法中设置 ,设置如下:
         // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
         */
    }
    
    
    // The method will be called on the delegate when the user responded to the notification by opening the application, dismissing the notification or choosing a UNNotificationAction. The delegate must be set before the application returns from applicationDidFinishLaunching:.
    //App通知的点击事件
    /*
        2.下面这个代理方法,只会是用户点击消息才会触发,如果使用户长按(3DTouch)、弹出Action页面等并不会触发。点击Action的时候会触发!
     */
    public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Swift.Void){
        UIApplication.shared.applicationIconBadgeNumber = 10
        if response.notification.request.trigger is UNPushNotificationTrigger {
            if response.actionIdentifier == "action4" {
                let userSayStr = (response as? UNTextInputNotificationResponse)?.userText
                print("输入:\(userSayStr)")
            }else if response.actionIdentifier == "action3" {
                print("取消")
            }else if response.actionIdentifier == "action2"{
                print("看看邀请")
            }else if response.actionIdentifier == "action1" {
                print("接受邀请")
            }
        }else {
            print("ios10 本地通知")
        }
        
        completionHandler()
        /*
         3.点击代理最后需要执行:completionHandler(); // 系统要求执行这个方法
         不然会报:
         2016-09-27 14:42:16.353978 UserNotificationsDemo[1765:800117] Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.
         */
    }

参考文章:
http://www.jianshu.com/p/c623c2b5966a
http://www.jianshu.com/p/4b947569a548
http://www.jianshu.com/p/c58f8322a278
http://www.jianshu.com/p/81c6bd16c7ac
https://onevcat.com/2016/08/notification/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容