在简单项目中,有使用到apns推送服务,许多文章有涉及到却没有讲清楚。最近做福路通项目,有使用到,做一个总结。
推送步骤为注册推送,接收推送进行处理,推送的类型分为1.程序运行时推送 2.程序未运行时推送。
1.注册推送,分为IOS8.0以下,IOS8.0以上IOS10.0以下,IOS10.0以上版本;在didRegisterForRemoteNotificationsWithDeviceToken方法中获取到deviceToken
1.程序运行时推送,又分为IOS7.0以下,IOS7.0以上IOS10.0以下,IOS10.0以上版本
2.程序未运行推送,在appdelegate中进行didFinishLaunchingWithOptions方法中进行处理
1.注册推送
在didFinishLaunchingWithOptions中注册
[self registerRemoteNotification];
注册方法:
#pragma mark 推送->注册
- (void)registerRemoteNotification
{
#ifdef __IPHONE_8_0
if([SYSTEM_VERSION floatValue]>=10.0){
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 必须写代理,不然无法监听通知的接收与点击
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 点击允许
NSLog(@"注册成功");
} else {
// 点击不允许
NSLog(@"注册失败");
}
}];
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"========%@",settings);
}];
}
else if ([SYSTEM_VERSION floatValue] >= 8.0) {
UIUserNotificationSettings *uns = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound) categories:nil];
// [[UIApplication sharedApplication] registerForRemoteNotifications];
[[UIApplication sharedApplication] registerUserNotificationSettings:uns];
} else {
UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
}
// 注册获得device Token
[[UIApplication sharedApplication] registerForRemoteNotifications];
#else
UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeBadge);
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
#endif
[[UIApplication sharedApplication] cancelAllLocalNotifications];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
}
获取deviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
_cid = [NSString stringWithFormat:@"%@", deviceToken];
//获取终端设备标识,这个标识需要通过接口发送到服务器端,服务器端推送消息到APNS时需要知道终端的标识,APNS通过注册的终端标识找到终端设备。
NSLog(@"My token is:%@", _cid);
}
2. 推送接收和点击跳转
//处理收到的消息推送->iOS版本7.0后
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//在此处理接收到的消息。
NSLog(@"Receive remote notification : %@",userInfo);
//当APP在前台运行时
if( [UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
//前台无法显示远程推送,所以添加了本地推送
[self addLocalNotification:userInfo];
}
//当APP在后台运行时,当有通知栏消息时
else if ([UIApplication sharedApplication].applicationState == UIApplicationStateInactive)
{
NSLog(@"通知后台测试");
[self jumpToBillInfo:userInfo];
}
else{
}
}
// iOS 10收到通知->前台
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 前台收到远程通知:");
}
else {
// 判断为本地通知
NSLog(@"iOS10 前台收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
}
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
}
// iOS 10通知的点击事件->前台、后台
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
NSDictionary * userInfo = response.notification.request.content.userInfo;
UNNotificationRequest *request = response.notification.request; // 收到推送的请求
UNNotificationContent *content = request.content; // 收到推送的消息内容
NSNumber *badge = content.badge; // 推送消息的角标
NSString *body = content.body; // 推送消息体
UNNotificationSound *sound = content.sound; // 推送消息的声音
NSString *subtitle = content.subtitle; // 推送消息的副标题
NSString *title = content.title; // 推送消息的标题
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 收到远程通知:");
[self jumpToBillInfo:userInfo];
}
else {
// 判断为本地通知
NSLog(@"iOS10 收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
[self jumpToBillInfo:userInfo];
}
completionHandler(); // 系统要求执行这个方法
}
3.发送本地通知
//发布本地通知
-(void)addLocalNotification:(NSDictionary*)userInfo{
//定义本地通知对象
UILocalNotification *notification=[[UILocalNotification alloc]init];
//设置调用时间
notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:5];//通知触发的时间,10s以后
// notification.repeatInterval=2;//通知重复次数
notification.repeatCalendar=[NSCalendar currentCalendar];//当前日历,使用前最好设置时区等信息以便能够自动同步时间
//设置通知属性
notification.alertBody=[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]; //通知主体
notification.applicationIconBadgeNumber=1;//应用程序图标右上角显示的消息数
notification.alertAction=@"打开应用"; //待机界面的滑动动作提示
notification.alertLaunchImage=@"Default";//通过点击通知打开应用时的启动图片,这里使用程序启动图片
notification.soundName=UILocalNotificationDefaultSoundName;//收到通知时播放的声音,默认消息声音
// notification.soundName=@"msg.caf";//通知声音(需要真机才能听到声音)
//设置用户信息
notification.userInfo=userInfo;//绑定到通知上的其他附加信息
//调用通知
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
4.app未打开时,在didFinishLaunchingWithOptions中写入:[self jumpViewController:launchOptions];
/**
当APP没有打开时,跳转
@param dic
*/
-(void)jumpViewController:(NSDictionary *)dic{
NSDictionary *remoteNotification = [dic objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(remoteNotification){
_isLaunchedByNotification = YES;
[self jumpToBillInfo:remoteNotification];
}
}
5.点击通知跳转ViewController
//跳转到BillInfoController页面
-(void)jumpToBillInfo:(NSDictionary*)userInfo{
//读取userNO和loginToken
NSString *userNO = [NSUserDefaultsUtils readUserDataWithKey:KEY_USERNO];
NSString *loginToken = [NSUserDefaultsUtils readUserDataWithKey:KEY_LOGIN_TOKEN];
if(![FormatUtils isNull:userNO]&&![FormatUtils isNull:loginToken]&&userInfo)
{
BillInfoController *_viewController = [[BillInfoController alloc]init];
_viewController.extras = @{@"platformNo":[userInfo objectForKey:@"PLNO"],@"ordType":[userInfo objectForKey:@"ORDTYPE"]};
UIViewController *result = nil;
UIWindow * window = [[UIApplication sharedApplication] keyWindow];
//app默认windowLevel是UIWindowLevelNormal,如果不是,找到UIWindowLevelNormal的
if (window.windowLevel != UIWindowLevelNormal)
{
NSArray *windows = [[UIApplication sharedApplication] windows];
for(UIWindow * tmpWin in windows)
{
if (tmpWin.windowLevel == UIWindowLevelNormal)
{
window = tmpWin;
break;
}
}
}
id nextResponder = nil;
UIViewController *appRootVC=window.rootViewController;
// 如果是present上来的appRootVC.presentedViewController 不为nil
if (appRootVC.presentedViewController) {
nextResponder = appRootVC.presentedViewController;
}else{
UIView *frontView = [[window subviews] objectAtIndex:0];
nextResponder = [frontView nextResponder];
}
if ([nextResponder isKindOfClass:[UITabBarController class]]){
UITabBarController * tabbar = (UITabBarController *)nextResponder;
UINavigationController * nav = (UINavigationController *)tabbar.viewControllers[tabbar.selectedIndex];
// UINavigationController * nav = tabbar.selectedViewController ; 上下两种写法都行
result=nav.childViewControllers.lastObject;
}else if ([nextResponder isKindOfClass:[UINavigationController class]]){
UIViewController * nav = (UIViewController *)nextResponder;
result = nav.childViewControllers.lastObject;
}else{
result = nextResponder;
}
[result.navigationController pushViewController:_viewController animated:YES];
//删除所有的通知
[[UIApplication sharedApplication] cancelAllLocalNotifications];
}
}