430 lines
18 KiB
Objective-C
430 lines
18 KiB
Objective-C
//
|
||
// AppDelegate+AliPushConfig.m
|
||
// Ifish
|
||
//
|
||
// Created by wbzhan on 2019/5/23.
|
||
// Copyright © 2019 lianlian. All rights reserved.
|
||
//
|
||
|
||
#import "AppDelegate+AliPushConfig.h"
|
||
#import <objc/runtime.h>
|
||
static const void *NotificationCenterKey = &NotificationCenterKey;
|
||
@implementation AppDelegate (AliPushConfig)
|
||
- (UNUserNotificationCenter *)notificationCenter {
|
||
return objc_getAssociatedObject(self, NotificationCenterKey);
|
||
}
|
||
- (void)setNotificationCenter:(UNUserNotificationCenter *)notificationCenter {
|
||
objc_setAssociatedObject(self, NotificationCenterKey, notificationCenter, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||
}
|
||
|
||
/**
|
||
* 向APNs注册,获取deviceToken 用于推送
|
||
* @param application
|
||
*/
|
||
- (void)registerAPNS:(UIApplication *)application {
|
||
|
||
float systemVersionNum = [[[UIDevice currentDevice] systemVersion] floatValue];
|
||
if (systemVersionNum >= 10.0) {
|
||
|
||
// iOS 10 notifications
|
||
self.notificationCenter = [UNUserNotificationCenter currentNotificationCenter];
|
||
|
||
// 创建 category,并注册到通知中心
|
||
[self createCustomNotificationCategory];
|
||
|
||
// 遵循协议
|
||
self.notificationCenter.delegate = self;
|
||
|
||
// 请求客户推送通知权限,以及推送的类型
|
||
[self.notificationCenter requestAuthorizationWithOptions:UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound completionHandler:^(BOOL granted, NSError * _Nullable error) {
|
||
|
||
if (granted) {
|
||
// granted
|
||
NSLog(@"\n ====== User authored notification.");
|
||
|
||
// 向APNs注册,获取deviceToken // 要求在主线程中
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[application registerForRemoteNotifications];
|
||
});
|
||
|
||
} else {
|
||
// not granted
|
||
NSLog(@"\n ====== User denied notification.");
|
||
|
||
// 即使客户不允许通知也想让它通知 // 待测试
|
||
// 向APNs注册,获取deviceToken // 要求在主线程中
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
[application registerForRemoteNotifications];
|
||
});
|
||
|
||
}}];
|
||
|
||
/**
|
||
* 主动获取设备通知是否授权 (iOS 10+)
|
||
*/
|
||
[self.notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
|
||
|
||
// 进行判断做出相应的处理
|
||
if (settings.authorizationStatus == UNAuthorizationStatusNotDetermined) {
|
||
NSLog(@"\n ====== 未选择是否允许通知");
|
||
} else if (settings.authorizationStatus == UNAuthorizationStatusDenied) {
|
||
NSLog(@"\n ====== 未授权允许通知");
|
||
} else if (settings.authorizationStatus == UNAuthorizationStatusAuthorized){
|
||
NSLog(@"\n ====== 已授权允许通知");
|
||
}
|
||
}];
|
||
|
||
|
||
} else if (systemVersionNum >= 8.0) { // 适配 iOS_8, iOS_10.0
|
||
|
||
// iOS 8 Notifications
|
||
// 不会有黄色叹号
|
||
#pragma clang diagnostic push
|
||
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
||
[application registerUserNotificationSettings:
|
||
[UIUserNotificationSettings settingsForTypes:
|
||
(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
|
||
[application registerForRemoteNotifications];
|
||
|
||
/*
|
||
// 提出弹窗,授权是否允许通知
|
||
UIUserNotificationSettings * settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil];
|
||
[[UIApplication sharedApplication] registerUserNotificationSettings:settings];
|
||
|
||
// 注册远程通知 (iOS_8+)
|
||
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
||
|
||
if ([[UIApplication sharedApplication] currentUserNotificationSettings].types == UIUserNotificationTypeNone) { //判断用户是否打开通知开关
|
||
NSLog(@"没有打开");
|
||
} else {
|
||
NSLog(@"已经打开");
|
||
}
|
||
*/
|
||
|
||
#pragma clang diagnostic pop
|
||
} else {
|
||
|
||
// iOS < 8 Notifications
|
||
#pragma clang diagnostic push
|
||
#pragma clang diagnostic ignored"-Wdeprecated-declarations"
|
||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:
|
||
(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound)];
|
||
/*
|
||
UIRemoteNotificationType types = UIRemoteNotificationTypeBadge|UIRemoteNotificationTypeSound|UIRemoteNotificationTypeAlert;
|
||
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
|
||
|
||
if ([[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone) { //判断用户是否打开通知开关
|
||
}
|
||
*/
|
||
|
||
#pragma clang diagnostic pop
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 主动获取设备通知是否授权 (iOS 10+) 可以单独调用
|
||
*/
|
||
- (void)getNotificationSettingStatus {
|
||
[self.notificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
|
||
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
|
||
NSLog(@"\n ====== 已经开启通知.");
|
||
} else {
|
||
NSLog(@"\n ====== 暂未开启通知.");
|
||
}}];
|
||
}
|
||
|
||
|
||
/**
|
||
* 创建并注册通知category (iOS 10+)
|
||
*/
|
||
- (void)createCustomNotificationCategory {
|
||
// 自定义 action1 和 action2
|
||
UNNotificationAction *action1 = [UNNotificationAction actionWithIdentifier:@"action1" title:@"test1" options: UNNotificationActionOptionNone];
|
||
UNNotificationAction *action2 = [UNNotificationAction actionWithIdentifier:@"action2" title:@"test2" options: UNNotificationActionOptionNone];
|
||
// 创建id为`test_category`的category,并注册两个action到category
|
||
// UNNotificationCategoryOptionCustomDismissAction 表明可以触发通知的 dismiss 回调
|
||
UNNotificationCategory *category = [UNNotificationCategory categoryWithIdentifier:@"test_category" actions:@[action1, action2] intentIdentifiers:@[] options: UNNotificationCategoryOptionCustomDismissAction];
|
||
// 注册category到通知中心
|
||
[self.notificationCenter setNotificationCategories:[NSSet setWithObjects:category, nil]];
|
||
}
|
||
|
||
|
||
/*
|
||
* APNs注册成功回调,将返回的deviceToken上传到CloudPush服务器
|
||
*/
|
||
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken NS_AVAILABLE_IOS(3_0) {
|
||
NSLog(@"Upload deviceToken to CloudPush server.");
|
||
|
||
//阿里推送注册成功回调
|
||
[CloudPushSDK registerDevice:deviceToken withCallback:^(CloudPushCallbackResult *res) {
|
||
if (res.success) {
|
||
|
||
NSString *userId = [dataContorl dataControlGetUserIdInfo];
|
||
NSString *device_Id = [CloudPushSDK getDeviceId];
|
||
NSLog(@"注册成功 device_token = %@",device_Id);
|
||
[FuncUserDefault setStr:device_Id key:kDeviceToken];//本机的devicetoken保存在本地
|
||
if (userId!=nil) {
|
||
NSArray *keys = @[@"deviceId",@"userId"];
|
||
NSArray *values = @[device_Id,userId];
|
||
|
||
[[AFNOHeaderHttpTool sharedInstance] postRequestWihtUrl:Push_BindDevice_Url keys:keys values:values success:^(NSDictionary *successDic) {
|
||
//绑定成功
|
||
[FuncUserDefault setBool:YES key:is_Bind_DeviceToken];
|
||
} failure:^(NSDictionary *errorDic) {
|
||
|
||
}];
|
||
}
|
||
} else {
|
||
NSLog(@"Register deviceToken failed, error: %@", res.error);
|
||
}
|
||
}];
|
||
}
|
||
|
||
/*
|
||
* APNs注册失败回调
|
||
*/
|
||
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
|
||
NSLog(@"\n ====== didFailToRegisterForRemoteNotificationsWithError %@", error);
|
||
}
|
||
|
||
#pragma mark SDK Init
|
||
- (void)registerAliPush {
|
||
// // 正式上线关闭
|
||
// if (DEBUG) {
|
||
// [CloudPushSDK turnOnDebug];
|
||
// }
|
||
// SDK初始化
|
||
[CloudPushSDK asyncInit:Ali_Push_APPKey appSecret:Ali_Push_APPSecret callback:^(CloudPushCallbackResult *res) {
|
||
if (res.success) {
|
||
NSLog(@"\n ====== 启动成功: %@.", [CloudPushSDK getDeviceId]);
|
||
} else {
|
||
NSLog(@"\n ====== 启动失败, error: %@", res.error);
|
||
}
|
||
}];
|
||
// 监听推送通道打开动作
|
||
[self listenerOnChannelOpened];
|
||
|
||
// 监听推送消息到达
|
||
[self registerMessageReceive];
|
||
// 主动获取设备通知是否授权 (iOS 10+)
|
||
[self getNotificationSettingStatus];
|
||
|
||
}
|
||
/**
|
||
* 注册推送通道 打开 监听
|
||
*/
|
||
- (void)listenerOnChannelOpened {
|
||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||
selector:@selector(onChannelOpened:)
|
||
name:@"CCPDidChannelConnectedSuccess"
|
||
object:nil];
|
||
|
||
}
|
||
/**
|
||
* 推送通道打开回调
|
||
* @param notification
|
||
*/
|
||
- (void)onChannelOpened:(NSNotification *)notification {
|
||
NSLog(@"\n ====== 温馨提示,消息通道建立成功,该通道创建成功表示‘在线’,可以接收到推送的消息");
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* 注册推送消息 到来 监听
|
||
*/
|
||
- (void)registerMessageReceive {
|
||
[[NSNotificationCenter defaultCenter] addObserver:self
|
||
selector:@selector(onMessageReceived:)
|
||
name:@"CCPDidReceiveMessageNotification"
|
||
object:nil];
|
||
}
|
||
|
||
/**
|
||
* 处理到来推送消息
|
||
* @param notification
|
||
*/
|
||
- (void)onMessageReceived:(NSNotification *)notification {
|
||
//消息在通知栏显示,属于透传内容
|
||
NSLog(@"\n ====== Receive one message !!!!!!!");
|
||
CCPSysMessage *message = [notification object];
|
||
NSString *title = [[NSString alloc] initWithData:message.title encoding:NSUTF8StringEncoding];
|
||
NSString *body = [[NSString alloc] initWithData:message.body encoding:NSUTF8StringEncoding];
|
||
NSLog(@"\n ====== Receive message title: %@, content: %@.", title, body);
|
||
NSLog(@"\n ====== 当前线程 %@",[NSThread currentThread]);
|
||
[CommonUtils showAlerWithTitle:IsEmptyStr(title)?@"新消息":title withMsg:body];
|
||
|
||
}
|
||
|
||
#pragma mark —页面跳转(暂时不做处理)
|
||
- (void)jumpViewController:(NSDictionary *)tfdic {
|
||
|
||
// NSDictionary *remoteNotification = [tfdic objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
|
||
// for (NSString *tfStr in remoteNotification) {
|
||
|
||
// 通知里面的内容需要包含 " "
|
||
// if ([tfStr isEqualToString:@"careline"]) {
|
||
// JumpViewController *_viewController = [[JumpViewController alloc]init];
|
||
// UINavigationController *nav= (UINavigationController *)self.window.rootViewController;
|
||
// [nav pushViewController:_viewController animated:YES];
|
||
// }
|
||
// }
|
||
}
|
||
|
||
|
||
/**
|
||
* iOS 10 + 实现两个代理方法之一。
|
||
* 当APP处于后台 点击通知栏通知
|
||
* 触发通知动作时回调,比如点击、删除通知和点击自定义 action(iOS 10+)
|
||
*/
|
||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
|
||
|
||
NSString *userAction = response.actionIdentifier;
|
||
|
||
// 点击通知打开app
|
||
if ([userAction isEqualToString:UNNotificationDefaultActionIdentifier]) {
|
||
NSLog(@"\n ====== User opened the notification.");
|
||
// 处理iOS 10通知,并上报通知打开回执
|
||
[self handleiOS10Notification:response.notification];
|
||
}
|
||
// 通知dismiss,category 创建时传入 UNNotificationCategoryOptionCustomDismissAction 才可以触发
|
||
if ([userAction isEqualToString:UNNotificationDismissActionIdentifier]) {
|
||
NSLog(@"\n ====== User dismissed the notification.");
|
||
}
|
||
// NSString *customAction1 = @"action1";
|
||
// NSString *customAction2 = @"action2";
|
||
//
|
||
// // 点击用户自定义Action1
|
||
// if ([userAction isEqualToString:customAction1]) {
|
||
// NSLog(@"User custom action1.");
|
||
// }
|
||
//
|
||
// // 点击用户自定义Action2
|
||
// if ([userAction isEqualToString:customAction2]) {
|
||
// NSLog(@"User custom action2.");
|
||
// }
|
||
completionHandler();
|
||
}
|
||
/**
|
||
* App 处于前台时收到通知 (iOS 10+ )
|
||
* iOS 10 + 实现两个代理方法之一。
|
||
* 只有当应用程序位于前台时,该方法才会在委托上调用。如果方法未被执行或处理程序没有及时调用,则通知将不会被提交。
|
||
* 应用程序可以选择将通知呈现为声音、徽章、警报和/或通知列表中。此决定应基于通知中的信息是否对用户可见。
|
||
*/
|
||
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
|
||
NSLog(@"\n ====== App 处于前台时收到通知 (iOS 10+ )");
|
||
|
||
// 处理iOS 10通知,并上报通知打开回执
|
||
[self handleiOS10Notification:notification];
|
||
|
||
/*
|
||
处理完成后调用 completionHandler ,用于指示在前台显示通知的形式
|
||
completionHandler() 功能:可设置是否在应用内弹出通知
|
||
在 iOS 10 中 通知在前台的显示设置:
|
||
*/
|
||
|
||
// 1、通知在前台不显示
|
||
// 如果调用下面代码: 通知不在前台弹出也不在通知栏显示
|
||
// completionHandler(UNNotificationPresentationOptionNone);
|
||
|
||
// 2、通知在前台显示
|
||
// 如果调用下面代码: 通知在前台弹出也在通知栏显示
|
||
// completionHandler(UNNotificationPresentationOptionAlert);
|
||
|
||
|
||
// 3、通知在前台显示 并带有声音
|
||
// 如果调用下面代码:通知弹出,且带有声音、内容和角标
|
||
// completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionBadge);
|
||
completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionBadge);
|
||
|
||
}
|
||
|
||
/**
|
||
* 处理App 处于前台时收到通知 (iOS 10+ )
|
||
*/
|
||
- (void)handleiOS10Notification:(UNNotification *)notification {
|
||
|
||
UNNotificationRequest *request = notification.request;
|
||
UNNotificationContent *content = request.content;
|
||
|
||
NSDictionary *userInfo = content.userInfo;
|
||
// 通知时间
|
||
NSDate *noticeDate = notification.date;
|
||
// 标题
|
||
NSString *title = content.title;
|
||
// 副标题
|
||
NSString *subtitle = content.subtitle;
|
||
// 内容
|
||
NSString *body = content.body;
|
||
// 角标
|
||
int badge = [content.badge intValue];
|
||
// 取得通知自定义字段内容,例:获取key为"category"的内容
|
||
NSString *extras = [userInfo valueForKey:@"category"];
|
||
// 通知角标数清0
|
||
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
|
||
// 同步角标数到服务端
|
||
[self syncBadgeNum:0];
|
||
|
||
// 通知打开回执上报
|
||
[CloudPushSDK sendNotificationAck:userInfo];
|
||
|
||
NSLog(@"\n ====== App 处于前台时收到通知 (iOS 10+ ) Notification, == date: %@, == title: %@, == subtitle: %@, == body: %@, == badge: %d, == extras: %@.", noticeDate, title, subtitle, body, badge, extras);
|
||
[CommonUtils showAlerWithTitle:IsEmptyStr(title)?@"新通知":title withMsg:body];
|
||
}
|
||
|
||
|
||
/* 同步通知角标数到服务端 */
|
||
- (void)syncBadgeNum:(NSUInteger)badgeNum {
|
||
[CloudPushSDK syncBadgeNum:badgeNum withCallback:^(CloudPushCallbackResult *res) {
|
||
if (res.success) {
|
||
NSLog(@"\n ====== Sync badge num: [%lu] success.", (unsigned long)badgeNum);
|
||
} else {
|
||
NSLog(@"\n ====== Sync badge num: [%lu] failed, error: %@", (unsigned long)badgeNum, res.error);
|
||
}
|
||
}];
|
||
}
|
||
|
||
// iOS 7+ 不论是前台还是后台只要有远程推送都会调用
|
||
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler NS_AVAILABLE_IOS(7_0) {
|
||
|
||
NSLog(@"\n ====== iOS 7+ 前台后台都会调用");
|
||
/*
|
||
建议使用该方法,还有一个作用。根据苹果给出的文档,系统给出30s的时间对推送的消息进行处理,此后就会运行CompletionHandler 程序块。
|
||
在处理这类推送消息(即程序被启动后接收到推送消息)的时候,通常会遇到这样的问题 :
|
||
就是当前的推送消息是当前程序正在前台运行时接收到的,还是说是程序在后台运行,用户点击系统消息通知栏对应项进入程序时而接收到的?这个其实很简单,用下面的代码就可以解决:
|
||
*/
|
||
|
||
// 做相应的判断是前台还是后台
|
||
if (application.applicationState == UIApplicationStateActive) {
|
||
|
||
// 程序当前正处于前台 如果不做处理里面不用写 就可以了
|
||
|
||
/*
|
||
关于userInfo的结构,参照苹果的官方结构:
|
||
{
|
||
"aps" : {
|
||
"alert" : "You got your emails.",
|
||
"badge" : 9,
|
||
"sound" : "bingbong.aiff"
|
||
"acme1" : "bar",
|
||
"acme2" : 42
|
||
}
|
||
|
||
即key aps 对应了有一个字典,里面是该次推送消息的具体信息。具体跟我们注册的推送类型有关。另外剩下的一些key就是用户自定义的了。
|
||
*/
|
||
|
||
} else if (application.applicationState == UIApplicationStateInactive) {
|
||
// // 程序处于后台 做相应的处理
|
||
// for (NSString *tfStr in userInfo) {
|
||
// if ([tfStr isEqualToString:@"careline"]) {
|
||
// JumpViewController *_viewController = [[JumpViewController alloc]init];
|
||
// UINavigationController *nav= (UINavigationController *)self.window.rootViewController;
|
||
// [nav pushViewController:_viewController animated:YES];
|
||
// }
|
||
// }
|
||
}
|
||
}
|
||
|
||
|
||
@end
|