在簡單項目中,有使用到apns推送服務(wù)伐坏,許多文章有涉及到卻沒有講清楚怔匣。最近做福路通項目,有使用到桦沉,做一個總結(jié)。
推送步驟為注冊推送金闽,接收推送進(jìn)行處理纯露,推送的類型分為1.程序運(yùn)行時推送 2.程序未運(yùn)行時推送。
1.注冊推送代芜,分為IOS8.0以下埠褪,IOS8.0以上IOS10.0以下,IOS10.0以上版本挤庇;在didRegisterForRemoteNotificationsWithDeviceToken方法中獲取到deviceToken
1.程序運(yùn)行時推送钞速,又分為IOS7.0以下,IOS7.0以上IOS10.0以下嫡秕,IOS10.0以上版本
2.程序未運(yùn)行推送渴语,在appdelegate中進(jìn)行didFinishLaunchingWithOptions方法中進(jìn)行處理
1.注冊推送
在didFinishLaunchingWithOptions中注冊
[self registerRemoteNotification];
注冊方法:
#pragma mark 推送->注冊
- (void)registerRemoteNotification
{
#ifdef __IPHONE_8_0
if([SYSTEM_VERSION floatValue]>=10.0){
//iOS10特有
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
// 必須寫代理,不然無法監(jiān)聽通知的接收與點(diǎn)擊
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
// 點(diǎn)擊允許
NSLog(@"注冊成功");
} else {
// 點(diǎn)擊不允許
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];
//獲取終端設(shè)備標(biāo)識昆咽,這個標(biāo)識需要通過接口發(fā)送到服務(wù)器端驾凶,服務(wù)器端推送消息到APNS時需要知道終端的標(biāo)識,APNS通過注冊的終端標(biāo)識找到終端設(shè)備掷酗。
NSLog(@"My token is:%@", _cid);
}
2. 推送接收和點(diǎn)擊跳轉(zhuǎn)
//處理收到的消息推送->iOS版本7.0后
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler{
//在此處理接收到的消息调违。
NSLog(@"Receive remote notification : %@",userInfo);
//當(dāng)APP在前臺運(yùn)行時
if( [UIApplication sharedApplication].applicationState == UIApplicationStateActive)
{
//前臺無法顯示遠(yuǎn)程推送,所以添加了本地推送
[self addLocalNotification:userInfo];
}
//當(dāng)APP在后臺運(yùn)行時泻轰,當(dāng)有通知欄消息時
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 前臺收到遠(yuǎn)程通知:");
}
else {
// 判斷為本地通知
NSLog(@"iOS10 前臺收到本地通知:{\\\\nbody:%@技肩,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@浮声,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
}
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要執(zhí)行這個方法虚婿,選擇是否提醒用戶殖告,有Badge、Sound雳锋、Alert三種類型可以設(shè)置
}
// iOS 10通知的點(diǎn)擊事件->前臺黄绩、后臺
- (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; // 收到推送的消息內(nèi)容
NSNumber *badge = content.badge;? // 推送消息的角標(biāo)
NSString *body = content.body;? ? // 推送消息體
UNNotificationSound *sound = content.sound;? // 推送消息的聲音
NSString *subtitle = content.subtitle;? // 推送消息的副標(biāo)題
NSString *title = content.title;? // 推送消息的標(biāo)題
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
NSLog(@"iOS10 收到遠(yuǎn)程通知:");
[self jumpToBillInfo:userInfo];
}
else {
// 判斷為本地通知
NSLog(@"iOS10 收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@玷过,\\\\nsound:%@爽丹,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
[self jumpToBillInfo:userInfo];
}
completionHandler();? // 系統(tǒng)要求執(zhí)行這個方法
}
3.發(fā)送本地通知
//發(fā)布本地通知
-(void)addLocalNotification:(NSDictionary*)userInfo{
//定義本地通知對象
UILocalNotification *notification=[[UILocalNotification alloc]init];
//設(shè)置調(diào)用時間
notification.fireDate=[NSDate dateWithTimeIntervalSinceNow:5];//通知觸發(fā)的時間,10s以后
//? ? notification.repeatInterval=2;//通知重復(fù)次數(shù)
notification.repeatCalendar=[NSCalendar currentCalendar];//當(dāng)前日歷辛蚊,使用前最好設(shè)置時區(qū)等信息以便能夠自動同步時間
//設(shè)置通知屬性
notification.alertBody=[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]; //通知主體
notification.applicationIconBadgeNumber=1;//應(yīng)用程序圖標(biāo)右上角顯示的消息數(shù)
notification.alertAction=@"打開應(yīng)用"; //待機(jī)界面的滑動動作提示
notification.alertLaunchImage=@"Default";//通過點(diǎn)擊通知打開應(yīng)用時的啟動圖片,這里使用程序啟動圖片
notification.soundName=UILocalNotificationDefaultSoundName;//收到通知時播放的聲音粤蝎,默認(rèn)消息聲音
//? ? notification.soundName=@"msg.caf";//通知聲音(需要真機(jī)才能聽到聲音)
//設(shè)置用戶信息
notification.userInfo=userInfo;//綁定到通知上的其他附加信息
//調(diào)用通知
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}
4.app未打開時,在didFinishLaunchingWithOptions中寫入:[self jumpViewController:launchOptions];
/**
當(dāng)APP沒有打開時袋马,跳轉(zhuǎn)
@param dic
*/
-(void)jumpViewController:(NSDictionary *)dic{
NSDictionary *remoteNotification = [dic objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if(remoteNotification){
_isLaunchedByNotification = YES;
[self jumpToBillInfo:remoteNotification];
}
}
5.點(diǎn)擊通知跳轉(zhuǎn)ViewController
//跳轉(zhuǎn)到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默認(rèn)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];
}
}