IOS開發apns推送的總結


在簡單項目中,有使用到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];

}

}

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容