iOS开发 - ANPs推送通知

转自:http://blog.csdn.net/wangzi11322/article/details/45458591

推送通知

注意:这里说的推送通知跟NSNotification有所区别
NSNotification是抽象的,不可见的
推送通知是可见的(能用肉眼看到)

iOS中提供了2种推送通知
本地推送通知(Local Notification)
远程推送通知(Remote Notification)

推送通知的呈现效果总结

总结一下,推送通知有5种不同的呈现效果
在屏幕顶部显示一块横幅(显示具体内容)
在屏幕中间弹出一个UIAlertView(显示具体内容)
在锁屏界面显示一块横幅(锁屏状态下,显示具体内容)
更新app图标的数字(说明新内容的数量)
播放音效(提醒作用)

发出推送通知时,如果当前程序正运行在前台,那么推送通知就不会被呈现出来
点击推送通知后,默认会自动打开发出推送通知的app
不管app打开还是关闭,推送通知都能如期发出

本地推送通知

什么是本地推送通知
顾名思义,就是不需要联网就能发出的推送通知(不需要服务器的支持)

本地推送通知的使用场景
常用来定时提醒用户完成一些任务,比如
清理垃圾、记账、买衣服、看电影、玩游戏

如何发出本地推送通知

<code class="hljs objectivec has-numbering"><span class="hljs-comment">//创建本地推送通知对象</span>
<span class="hljs-built_in">UILocalNotification</span> *ln = [[<span class="hljs-built_in">UILocalNotification</span> alloc] init];

<span class="hljs-comment">//设置本地推送通知属性</span>
<span class="hljs-comment">//推送通知的触发时间(何时发出推送通知)</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSDate</span> *fireDate;
<span class="hljs-comment">//推送通知的具体内容</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSString</span> *alertBody;
<span class="hljs-comment">//在锁屏时显示的动作标题(完整标题:“滑动来” + alertAction)</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSString</span> *alertAction;
<span class="hljs-comment">//音效文件名</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSString</span> *soundName;
<span class="hljs-comment">//app图标数字</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>) <span class="hljs-built_in">NSInteger</span> applicationIconBadgeNumber;
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li></ul>
<code class="hljs objectivec has-numbering"><span class="hljs-comment">//调度本地推送通知(调度完毕后,推送通知会在特地时间fireDate发出)</span>
[[<span class="hljs-built_in">UIApplication</span> sharedApplication] scheduleLocalNotification:ln];

<span class="hljs-comment">//获得被调度(定制)的所有本地推送通知</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSArray</span> *scheduledLocalNotifications;
(已经发出且过期的推送通知就算调度结束,会自动从这个数组中移除)

<span class="hljs-comment">//取消调度本地推送通知</span>
- (<span class="hljs-keyword">void</span>)cancelLocalNotification:(<span class="hljs-built_in">UILocalNotification</span> *)notification;
- (<span class="hljs-keyword">void</span>)cancelAllLocalNotifications;

<span class="hljs-comment">//立即发出本地推送通知</span>
- (<span class="hljs-keyword">void</span>)presentLocalNotificationNow:(<span class="hljs-built_in">UILocalNotification</span> *)notification;
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li></ul>

本地推送通知的其他属性

<code class="hljs objectivec has-numbering"><span class="hljs-comment">//每隔多久重复发一次推送通知</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>) NSCalendarUnit repeatInterval;

<span class="hljs-comment">//点击推送通知打开app时显示的启动图片</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSString</span> *alertLaunchImage;

<span class="hljs-comment">//附加的额外信息</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) <span class="hljs-built_in">NSDictionary</span> *userInfo;

<span class="hljs-comment">//时区</span>
<span class="hljs-keyword">@property</span>(<span class="hljs-keyword">nonatomic</span>,copy) NSTimeZone *timeZone;
(一般设置为[NSTimeZone defaultTimeZone] ,跟随手机的时区)
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li></ul>

点击本地推送通知

<code class="hljs objectivec has-numbering"><span class="hljs-comment">//当用户点击本地推送通知,会自动打开app,这里有2种情况</span>
<span class="hljs-comment">//app并没有关闭,一直隐藏在后台</span>
<span class="hljs-comment">//让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)</span>
- (<span class="hljs-keyword">void</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didReceiveLocalNotification:(<span class="hljs-built_in">UILocalNotification</span> *)notification;

<span class="hljs-comment">//app已经被关闭(进程已死)</span>
<span class="hljs-comment">//启动app,启动完毕会调用AppDelegate的下面方法</span>
- (<span class="hljs-built_in">BOOL</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span class="hljs-built_in">NSDictionary</span> *)launchOptions;
launchOptions参数通过UIApplicationLaunchOptionsLocalNotificationKey取出本地推送通知对象
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

远程推送通知

什么是远程推送通知
顾名思义,就是从远程服务器推送给客户端的通知(需要联网)
远程推送服务,又称为APNs(Apple Push Notification Services)

为什么需要远程推送通知?
传统获取数据的局限性
只要用户关闭了app,就无法跟app的服务器沟通,无法从服务器上获得最新的数据内容

远程推送通知可以解决以上问题
不管用户打开还是关闭app,只要联网了,都能接收到服务器推送的远程通知

远程推送通知使用须知

所有的苹果设备,在联网状态下,都会与苹果的服务器建立长连接
什么是长连接
只要联网了,就一直建立连接

长连接的作用
时间校准
系统升级
查找我的iPhone
.. …

长连接的好处
数据传输速度快
数据保持最新状态

一.开发iOS程序的推送功能, iOS端需要做的事
1.请求苹果获得deviceToken
2.得到苹果返回的deviceToken
3.发送deviceToken给公司的服务器
4.监听用户对通知的点击

二.调试iOS的远程推送功能, 必备条件:
1.真机

2.调试推送需要的证书文件
1> aps_development.cer : 某台电脑就能调试某个app的推送服务
2> ios_development.cer : 让电脑具备真机调试的能力(调试设备)
3> iphone5_qq.mobileprovision : 某台电脑就能利用某台设备调试某个程序

三.发布具有推送服务的app
1> aps_production.cer : 如果发布的程序中包含了推送服务,就必须安装这个证书
2> ios_distribution.cer : 让电脑具备发布程序的能力
3> qq.mobileprovision : 某台电脑就能发布某个程序

注册远程通知

<code class="hljs fsharp has-numbering"><span class="hljs-comment">//客户端如果想接收APNs的远程推送通知,必须先注册(得到用户的授权)</span>
<span class="hljs-comment">//一般在App启动完毕后就马上注册</span>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    <span class="hljs-comment">// 注册远程通知</span>
       UIRemoteNotificationType <span class="hljs-class"><span class="hljs-keyword">type</span> =</span> UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound;
    [application registerForRemoteNotificationTypes:<span class="hljs-class"><span class="hljs-keyword">type</span>];</span>
    <span class="hljs-keyword">return</span> YES;
}
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>
<code class="hljs erlang has-numbering">//注册成功后会调用<span class="hljs-variable">AppDelegate</span>的下面方法,得到设备的device<span class="hljs-variable">Token</span>
<span class="hljs-pp">- <span class="hljs-params">(void)</span>application:<span class="hljs-params">(<span class="hljs-variable">UIApplication</span> *)</span>application didRegisterForRemoteNotificationsWithDeviceToken:<span class="hljs-params">(<span class="hljs-variable">NSData</span> *)</span>deviceToken
{
    NSLog<span class="hljs-params">(@<span class="hljs-string">"%@"</span>, device<span class="hljs-variable">Token</span>)</span>;
}
</span></code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li></ul>
<code class="hljs objectivec has-numbering"><span class="hljs-comment">//当用户点击远程推送通知,会自动打开app,这里有2种情况</span>
<span class="hljs-comment">//app并没有关闭,一直隐藏在后台</span>
<span class="hljs-comment">//让app进入前台,并会调用AppDelegate的下面方法(并非重新启动app)</span>
- (<span class="hljs-keyword">void</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didReceiveRemoteNotification:(<span class="hljs-built_in">NSDictionary</span> *)userInfo;

<span class="hljs-comment">//app已经被关闭(进程已死)</span>
<span class="hljs-comment">//启动app,启动完毕会调用AppDelegate的下面方法</span>
- (<span class="hljs-built_in">BOOL</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span class="hljs-built_in">NSDictionary</span> *)launchOptions;
launchOptions参数通过UIApplicationLaunchOptionsRemoteNotificationKey取出服务器返回的字典内容
</code><ul style="display: block;" class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li></ul>

PushMeBaby

PushMeBaby是一款用来测试ANPs的开源Mac项目
它充当了服务器的作用,用法非常简单
它负责将内容提交给苹果的APNs服务器,苹果的APNs服务器再将内容推送给用户的设备
PushMeBaby的主页
https://github.com/stefanhafeneger/PushMeBaby

远程推送获取DeviceToken实例

<code class="hljs objectivec has-numbering">
<span class="hljs-class"><span class="hljs-keyword">@interface</span> <span class="hljs-title">AppDelegate</span> ()</span>

<span class="hljs-keyword">@end</span>

<span class="hljs-class"><span class="hljs-keyword">@implementation</span> <span class="hljs-title">AppDelegate</span></span>


- (<span class="hljs-built_in">BOOL</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didFinishLaunchingWithOptions:(<span class="hljs-built_in">NSDictionary</span> *)launchOptions {
    <span class="hljs-comment">// Override point for customization after application launch.</span>

    <span class="hljs-keyword">if</span> ([UIDevice currentDevice]<span class="hljs-variable">.systemVersion</span><span class="hljs-variable">.doubleValue</span> <= <span class="hljs-number">8.0</span>) {
        <span class="hljs-comment">// 不是iOS8</span>
        UIRemoteNotificationType type = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert;
        <span class="hljs-comment">// 当用户第一次启动程序时就获取deviceToke</span>
        <span class="hljs-comment">// 该方法在iOS8以及过期了</span>
        <span class="hljs-comment">// 只要调用该方法, 系统就会自动发送UDID和当前程序的Bunle ID到苹果的APNs服务器</span>
        [application registerForRemoteNotificationTypes:type];
    }<span class="hljs-keyword">else</span>
    {
        <span class="hljs-comment">// iOS8</span>
        UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound;

        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:type categories:<span class="hljs-literal">nil</span>];
        <span class="hljs-comment">// 注册通知类型</span>
        [application registerUserNotificationSettings:settings];

        <span class="hljs-comment">// 申请试用通知</span>
        [application registerForRemoteNotifications];
    }

    <span class="hljs-comment">// 1.取出数据</span>
    <span class="hljs-built_in">NSDictionary</span> *userInfo = launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey];

    <span class="hljs-keyword">if</span> (userInfo) {
        <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;
        count++;
        <span class="hljs-built_in">UILabel</span> *label = [[<span class="hljs-built_in">UILabel</span> alloc] init];
        label<span class="hljs-variable">.frame</span> = CGRectMake(<span class="hljs-number">0</span>, <span class="hljs-number">40</span>, <span class="hljs-number">200</span>, <span class="hljs-number">200</span>);
        label<span class="hljs-variable">.numberOfLines</span> = <span class="hljs-number">0</span>;
        label<span class="hljs-variable">.textColor</span> = [<span class="hljs-built_in">UIColor</span> whiteColor];
        label<span class="hljs-variable">.font</span> = [<span class="hljs-built_in">UIFont</span> systemFontOfSize:<span class="hljs-number">11</span>];
        label<span class="hljs-variable">.backgroundColor</span> = [<span class="hljs-built_in">UIColor</span> orangeColor];
        label<span class="hljs-variable">.text</span> = [<span class="hljs-built_in">NSString</span> stringWithFormat:@<span class="hljs-string">" %@ \n %d"</span>, userInfo, count];
        [<span class="hljs-keyword">self</span><span class="hljs-variable">.window</span><span class="hljs-variable">.rootViewController</span><span class="hljs-variable">.view</span> addSubview:label];
    }


    <span class="hljs-keyword">return</span> <span class="hljs-literal">YES</span>;
}

<span class="hljs-comment">/**
 *  获取到用户对应当前应用程序的deviceToken时就会调用
 */</span>
- (<span class="hljs-keyword">void</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    <span class="hljs-built_in">NSLog</span>(@<span class="hljs-string">"%@"</span>, deviceToken);
    <span class="hljs-comment">// <47e58207 31340f18 ed83ba54 f999641a 3d68bc7b f3e2db29 953188ec 7d0cecfb></span>
    <span class="hljs-comment">// <286c3bde 0bd3b122 68be655f 25ed2702 38e31cec 9d54da9f 1c62325a 93be801e></span>
}

<span class="hljs-comment">/*
 ios7以前苹果支持多任务, iOS7以前的多任务是假的多任务
 而iOS7开始苹果才真正的推出了多任务
 */</span>
<span class="hljs-comment">// 接收到远程服务器推送过来的内容就会调用</span>
<span class="hljs-comment">// 注意: 只有应用程序是打开状态(前台/后台), 才会调用该方法</span>
<span class="hljs-comment">/// 如果应用程序是关闭状态会调用didFinishLaunchingWithOptions</span>
- (<span class="hljs-keyword">void</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didReceiveRemoteNotification:(<span class="hljs-built_in">NSDictionary</span> *)userInfo
{
    <span class="hljs-comment">/*
     如果应用程序在后台 , 只有用户点击了通知之后才会调用
     如果应用程序在前台, 会直接调用该方法
     即便应用程序关闭也可以接收到远程通知
     */</span>
    <span class="hljs-built_in">NSLog</span>(@<span class="hljs-string">"%@"</span>, userInfo);

<span class="hljs-comment">//    static int count = 0;</span>
<span class="hljs-comment">//    count++;</span>
<span class="hljs-comment">//    UILabel *label = [[UILabel alloc] init];</span>
<span class="hljs-comment">//    label.frame = CGRectMake(0, 250, 200, 200);</span>
<span class="hljs-comment">//    label.numberOfLines = 0;</span>
<span class="hljs-comment">//    label.textColor = [UIColor whiteColor];</span>
<span class="hljs-comment">//    label.text = [NSString stringWithFormat:@"%@ \n %d", userInfo, count];</span>
<span class="hljs-comment">//    label.font = [UIFont systemFontOfSize:11];</span>
<span class="hljs-comment">//    label.backgroundColor = [UIColor grayColor];</span>
<span class="hljs-comment">//    [self.window.rootViewController.view addSubview:label];</span>
}

<span class="hljs-comment">//接收到远程服务器推送过来的内容就会调用</span>
<span class="hljs-comment">// ios7以后用这个处理后台任务接收到得远程通知</span>
- (<span class="hljs-keyword">void</span>)application:(<span class="hljs-built_in">UIApplication</span> *)application didReceiveRemoteNotification:(<span class="hljs-built_in">NSDictionary</span> *)userInfo fetchCompletionHandler:(<span class="hljs-keyword">void</span> (^)(UIBackgroundFetchResult))completionHandler
{
    <span class="hljs-comment">/*
     UIBackgroundFetchResultNewData, 成功接收到数据
     UIBackgroundFetchResultNoData, 没有;接收到数据
     UIBackgroundFetchResultFailed 接收失败

     */</span>
<span class="hljs-comment">//    NSLog(@"%s",__func__);</span>
<span class="hljs-comment">//    NSLog(@"%@", userInfo);</span>

    <span class="hljs-built_in">NSNumber</span> *contentid =  userInfo[@<span class="hljs-string">"content-id"</span>];
    <span class="hljs-keyword">if</span> (contentid) {
        <span class="hljs-built_in">UILabel</span> *label = [[<span class="hljs-built_in">UILabel</span> alloc] init];
        label<span class="hljs-variable">.frame</span> = CGRectMake(<span class="hljs-number">0</span>, <span class="hljs-number">250</span>, <span class="hljs-number">200</span>, <span class="hljs-number">200</span>);
        label<span class="hljs-variable">.numberOfLines</span> = <span class="hljs-number">0</span>;
        label<span class="hljs-variable">.textColor</span> = [<span class="hljs-built_in">UIColor</span> whiteColor];
        label<span class="hljs-variable">.text</span> = [<span class="hljs-built_in">NSString</span> stringWithFormat:@<span class="hljs-string">"%@"</span>, contentid];
        label<span class="hljs-variable">.font</span> = [<span class="hljs-built_in">UIFont</span> systemFontOfSize:<span class="hljs-number">30</span>];
        label<span class="hljs-variable">.backgroundColor</span> = [<span class="hljs-built_in">UIColor</span> grayColor];
        [<span class="hljs-keyword">self</span><span class="hljs-variable">.window</span><span class="hljs-variable">.rootViewController</span><span class="hljs-variable">.view</span> addSubview:label];
        <span class="hljs-comment">//注意: 在此方法中一定要调用这个调用block, 告诉系统是否处理成功.</span>
        <span class="hljs-comment">// 以便于系统在后台更新UI等操作</span>
        completionHandler(UIBackgroundFetchResultNewData);
    }<span class="hljs-keyword">else</span>
    {
        completionHandler(UIBackgroundFetchResultFailed);
    }

}
<span class="hljs-keyword">@end</span></code>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值