前言
最近工作中实现远程推送点击状态栏的提醒,直接进入相应地详细界面的功能。遇到了问题,解决之后整理出来
第一步: 准备阶段
1. 配置远程推送证书
在苹果开发者网站bundleId 账号下,勾选远程推送。并配置远程推送证书
2. App工程支持远程推送
在 项目Targets->Siging&Capabilities 勾选远程推送,如下图所示
3.引入头文件 :
在AppDelegate.h
文档中引入头文件 #import
4.遵循协议代理 :
在AppDelegate.h
文档中遵循协议代理 @interface AppDelegate : UIResponder
第二步: 申请权限,注册通知
在 AppDelegate.m
中 的代理方法 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions中,添加如下代码:
if ([OS_VERSON floatValue] >= 10.0) { //iOS 10 later
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (!error && granted) { //用户点击允许
dispatch_async(dispatch_get_main_queue(), ^{
[application registerForRemoteNotifications];
});
//[self submitRemotState:@"1"];
}else{ //用户点击不允许
//[self submitRemotState:@"0"];
}
}];
// 可以通过 getNotificationSettingsWithCompletionHandler 获取权限设置
[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
// NSLog(@"========%@",settings);
}];
}else if ([OS_VERSON floatValue] >= 8.0 &&[OS_VERSON floatValue] < 10.0 ){//iOS 8 - iOS 10系统
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
[application registerUserNotificationSettings:settings];
//注册远端消息通知获取device token
[application registerForRemoteNotifications];
}else{ //iOS 8.0系统以下
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
}
deviceToken 获取 和处理
/// 此处需连外网才能触发,触发的时机是每次app启动时
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
if (![deviceToken isKindOfClass:[NSData class]]) return;
NSString *string1;
//兼容 iOS13 和 xcode 10.2 发版时候,数据格式问题
//该方法可以兼容所有系统,已测试12.0可获取到正确的token值 2020年09月22日 王磊
const unsigned *tokenBytes = [deviceToken bytes];
string1 = [NSString stringWithFormat:@"%08x%08x%08x%08x%08x%08x%08x%08x",
ntohl(tokenBytes[0]), ntohl(tokenBytes[1]), ntohl(tokenBytes[2]),
ntohl(tokenBytes[3]), ntohl(tokenBytes[4]), ntohl(tokenBytes[5]),
ntohl(tokenBytes[6]), ntohl(tokenBytes[7])];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 令牌提交给后台处理
dispatch_async(queue, ^{
/*
[ApplicationConfigServiceData appPushServer:@"" deviceToken:string1 success:^(id result) {
if ([OS_VERSON floatValue] <10.0) {//低系统手机需在这里获取用户是否授权状态
[self isAgreeRemotion]? [self submitRemotState:@"1"] :[self submitRemotState:@"0"];
}
}];
*/
});
}
第三步: 远程推送各代理方法介绍
根据不同业务需求,处理不同代理方法
UIApplication有两个关于接收到远程推送的代理:
/*
APP状态 消息推送 用户操作 是否触发
Not Running 收到推送消息提示 点击消息 触发 didReceiveNotificationResponse
Not Running 收到推送消息提示 点击APP NO
Background 收到推送消息提示 点击消息 触发 didReceiveNotificationResponse
Background 收到推送消息提示 点击APP NO
Active 可自定义 无 触发willPresentNotification
*/
#mark 在后台接收到远程推送消息触发(推送的消息数据格式必须要有"content-available":1,否则不触发)
/*
此方法还有一个触发时机,是app在前台,前提条件是必须有“content-available”:1。
此时,先触发willPresentNotification代理方法,然后再触发此fetchCompletionHandler代理方法
*/
1. - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
#mark 在前台接受到远程推送消息触发
/*
此回调方法触发时机:
1.app 在前台运行,接收到远程推送消息时,此时通知栏不会有消息提示。可在此回调方法中定义提醒弹框。
2.每次app 从前台通过home键进入后台时,会触发此方法。
*/
2.- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
#mark 点击通知栏消息触发
3.- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler