iOS8 的 APNS(推送)-本地推送-服务器推送-地理位置推送
iOS8 的推送改变了很多,一个一个来说吧。
从哪说起呢,感觉怎么这么乱。先列个列表吧。
- 远程推送
- 初级
- 进阶(本地测试)(服务器测试)
- 地理位置推送
服务器推送
先说服务器推送,使用之前必须先注册这个推送,用户要允许这个程序进行推送
最简单的方法:
在 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
方法里
if (IOS8) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
UIUserNotificationSettings *set = [UIUserNotificationSettings settingsForTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:set];
}else{
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}
然后屏幕上就会询问是否允许推送
在 - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
方法中,可以得到 deviceToken
一般来说重装、更新都不会改变,手机还原、刷机才会改变。不过也不排除苹果突然用了什么新的算法,导致更改。所以妥当的做法是每次开启,都验证一次。
在 - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
方法里可以打印错误。
高级一点的做法
iOS8开放了通知的一些功能,比如左划处理
如果是未锁屏状态:
锁屏状态:
创建消息上面要添加的动作(按钮的形式显示出来)
UIMutableUserNotificationAction *action = [[UIMutableUserNotificationAction alloc] init];
action.identifier = @"action"; //按钮的标示
action.title=@"查看"; //按钮的标题
action.activationMode = UIUserNotificationActivationModeForeground; //当点击的时候启动程序
// action.authenticationRequired = YES;
// action.destructive = YES;
UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init]; //第二按钮
action2.identifier = @"action2";
action2.title=@"取消";
action2.activationMode = UIUserNotificationActivationModeBackground; //当点击的时候不启动程序,在后台处理
action.authenticationRequired = YES;//需要解锁才能处理,如果action.activationMode = UIUserNotificationActivationModeForeground;则这个属性被忽略
action.destructive = YES;
创建动作(按钮)的类别集合
UIMutableUserNotificationCategory *categorys = [[UIMutableUserNotificationCategory alloc] init];
categorys.identifier = @"alert";//这组动作的唯一标示
[categorys setActions:@[action,action2] forContext:(UIUserNotificationActionContextMinimal)];
创建UIUserNotificationSettings,并设置消息的显示类类型
UIUserNotificationSettings *uns = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound) categories:[NSSet setWithObjects:categorys, nil]];
注册推送
[[UIApplication sharedApplication] registerUserNotificationSettings:uns];
[[UIApplication sharedApplication] registerForRemoteNotifications];
若要使用远程推送,满足两个条件:
- 用户需要调用注册用户推送 registerUserNotificationSettings;
- 在 info.plist 文件中UIBackgroundModes必须包含远程通知。
1 上面已经介绍了,具体说 2,打开项目设置,按图设置即可
离线push数据包带上特定Category字段(字段内容需要前后台一起定义,必须要保持一致),手机端收到时,就能展示上述代码对应Category设置的按钮,和响应按钮事件。
//payload example: {"aps":{"alert":"杰哥是个天才!!", "sound":"default", "badge": 1, "category":"alert"}}
重大修改:离线push数据包之前能带的数据最多为256字节,现在APPLE将该数值放大到2KB。 这个应该是只针对IOS8的。
本地测试
在 - (void)applicationDidEnterBackground:(UIApplication *)application
方法中
UILocalNotification *notification = [[UILocalNotification alloc] init];
notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:5];
notification.timeZone=[NSTimeZone defaultTimeZone];
notification.alertBody=@"测试推送的快捷回复";
notification.category = @"alert";
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
就有如下效果:
远程测试
我假设你已经有下面三个文件:
CSR文件
P12私有密钥文件,Push.p12
SSL证书文件,aps_development.cer
我们用的是php环境,所以制作pem证书即可,java 环境需要p12证书,详细教程下方提供几个。
- 把.cer的SSL证书转换为.pem文件,执行命令
openssl x509 -in aps.cer -inform der -out apns-cer.pem
- 把私钥Push.p12文件转化为.pem文件。
首先输入Push.p12的密码,再给新文件设置密码(至少4位),确认一遍,完成
openssl pkcs12 -nocerts -out apns-key.pem -in EduPush.p12
- 去除密码
openssl rsa -in apns-key.pem -out apns-key-nop.pem
- 对生成的这两个pem文件再生成一个pem文件,来把证书和私钥整合到一个文件里
cat apns-key-nop.pem apns-cer.pem > cert.pem
php代码可以到这里下载,设置方法详见README文件
地理位置推送
这个推送是新的API才有的特性,必须配合CLLocation定位一起使用。
//Location Notification
CLLocationManager *locMan = [[CLLocationManager alloc] init];
locMan.delegate = self;
[locMan requestWhenInUseAuthorization];
#pragma mark - CLLocationManager
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
{
BOOL canUseLocationNotifications = (status == kCLAuthorizationStatusAuthorizedWhenInUse);
if (canUseLocationNotifications) {
[self startShowLocationNotification];
}
}
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
CLRegion *region = notification.region;
if (region) {
}
}
- (void)startShowLocationNotification
{
CLLocationCoordinate2D local2D ;
local2D.latitude = 123.0;
local2D.longitude = 223.0;
UILocalNotification *locNotification = [[UILocalNotification alloc] init];
locNotification.alertBody = @"你接收到了";
locNotification.regionTriggersOnce = YES;
locNotification.region = [[CLCircularRegion alloc] initWithCenter:local2D radius:45 identifier:@"local-identity"];
[[UIApplication sharedApplication] scheduleLocalNotification:locNotification];
}
如果没有开启Core Location 那么上面的didReceiveLocalNotification不会被调用