IOS 本地推送

? ? ? ?iOS中通知機(jī)制又叫消息機(jī)制,其包括兩類:一類是本地通知;另一類是推送通知,也叫遠(yuǎn)程通知。兩種通知在iOS中的表現(xiàn)一致,可以通過橫幅或者彈出提醒兩種形式告訴用戶,并且點(diǎn)擊通知可以會(huì)打開應(yīng)用程序,但是實(shí)現(xiàn)原理卻完全不同。

本地通知:

? ? ? ?本地通知是由本地應(yīng)用觸發(fā)的,它是基于時(shí)間行為的一種通知形式,例如鬧鐘定時(shí)、待辦事項(xiàng)提醒,又或者一個(gè)應(yīng)用在一段時(shí)候后不使用通常會(huì)提示用戶使用此應(yīng)用等都是本地通知。創(chuàng)建一個(gè)本地通知通常分為以下幾個(gè)步驟:

創(chuàng)建UILocalNotification。設(shè)置處理通知的時(shí)間fireDate。

配置通知的內(nèi)容:通知主體、通知聲音、圖標(biāo)數(shù)字等。

配置通知傳遞的自定義數(shù)據(jù)參數(shù)userInfo(這一步可選)。

調(diào)用通知,可以使用scheduleLocalNotification:按計(jì)劃調(diào)度一個(gè)通知,也可以使用presentLocalNotificationNow立即調(diào)用通知。


在AppDelegate中:

首先注冊(cè)通知:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

UIUserNotificationSettings *userNotification = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil];

[application registerUserNotificationSettings:userNotification];//注冊(cè)本地推送

return YES;

}

//通知回調(diào)

- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification{

NSLog(@"%@",notification.alertBody);

UILabel*label = [[UILabel alloc]init];

label.frame = CGRectMake(0, -60, [UIScreen mainScreen].bounds.size.width, 60);

label.layer.cornerRadius = 10;

label.backgroundColor = [UIColor blackColor];

label.text = notification.alertBody;

label.numberOfLines = 0;

label.textColor = [UIColor whiteColor];

label.font = [UIFont systemFontOfSize:14];

label.textAlignment = NSTextAlignmentCenter;

self.label = label;

[self appearView];

[self.window addSubview:self.label];

}

//頂部彈窗動(dòng)畫

-(void)appearView{

[UIView animateWithDuration:1 animations:^{

self.label.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 60);

} completion:^(BOOL finished) {}];

[self returnNotificationLabel];

}

//頂部彈窗消失

-(void)returnNotificationLabel{

[UIView animateWithDuration:1 delay:2 options:0 animations:^{

self.label.frame = CGRectMake(0, -60, [UIScreen mainScreen].bounds.size.width, 60);

} completion:^(BOOL finished) {

}];

}

在ViewController.h中

設(shè)置本地通知

- (IBAction)localPushNow:(id)sender {

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

//本地推送

UILocalNotification*notification = [[UILocalNotification alloc]init];

// 設(shè)置觸發(fā)通知的時(shí)間

NSDate * pushDate = [NSDate dateWithTimeIntervalSinceNow:10];

if (notification != nil) {

notification.fireDate = pushDate;

notification.timeZone = [NSTimeZone defaultTimeZone]; ? // 時(shí)區(qū)

notification.repeatInterval = kCFCalendarUnitDay;? ? // 通知重復(fù)提示的單位,可以是天、周、月

notification.soundName = UILocalNotificationDefaultSoundName; ? ?// 通知被觸發(fā)時(shí)播放的聲音

notification.alertBody = @"hello world ?。?!"; ? ? // 通知內(nèi)容

notification.applicationIconBadgeNumber = 0;

NSDictionary*info = [NSDictionary dictionaryWithObject:@"test" forKey:@"name"]; ?// 通知參數(shù)

notification.userInfo = info;

[[UIApplication sharedApplication] scheduleLocalNotification:notification];? // 執(zhí)行通知注冊(cè)

notification.timeZone = [NSTimeZone defaultTimeZone];

// 設(shè)置重復(fù)的間隔

notification.repeatInterval = kCFCalendarUnitSecond; ? ?// 設(shè)置重復(fù)的間隔

});

}

遠(yuǎn)程推送:

1.應(yīng)用程序注冊(cè)APNs推送消息。

說明:

a.只有注冊(cè)過的應(yīng)用才有可能接收到消息,程序中通常通過UIApplication的registerUserNotificationSettings:方法注冊(cè),iOS8中通知注冊(cè)的方法發(fā)生了改變,如果是iOS7及之前版本的iOS請(qǐng)參考其他代碼。

b.注冊(cè)之前有兩個(gè)前提條件必須準(zhǔn)備好:開發(fā)配置文件(provisioning profile,也就是.mobileprovision后綴的文件)的App ID不能使用通配ID必須使用指定APP ID并且生成配置文件中選擇Push Notifications服務(wù),一般的開發(fā)配置文件無法完成注冊(cè);應(yīng)用程序的Bundle Identifier必須和生成配置文件使用的APP ID完全一致。

2.iOS從APNs接收device token,在應(yīng)用程序獲取device token。

說明:

a.在UIApplication的-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken代理方法中獲取令牌,此方法發(fā)生在注冊(cè)之后。

b.如果無法正確獲得device token可以在UIApplication的-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error代理方法中查看詳細(xì)錯(cuò)誤信息,此方法發(fā)生在獲取device token失敗之后。

c.必須真機(jī)調(diào)試,模擬器無法獲取device token。

3.iOS應(yīng)用將device token發(fā)送給應(yīng)用程序提供商,告訴服務(wù)器端當(dāng)前設(shè)備允許接收消息。

說明:

a.device token的生成算法只有Apple掌握,為了確保算法發(fā)生變化后仍然能夠正常接收服務(wù)器端發(fā)送的通知,每次應(yīng)用程序啟動(dòng)都重新獲得device token(注意:device token的獲取不會(huì)造成性能問題,蘋果官方已經(jīng)做過優(yōu)化)。

b.通常可以創(chuàng)建一個(gè)網(wǎng)絡(luò)連接發(fā)送給應(yīng)用程序提供商的服務(wù)器端, 在這個(gè)過程中最好將上一次獲得的device token存儲(chǔ)起來,避免重復(fù)發(fā)送,一旦發(fā)現(xiàn)device token發(fā)生了變化最好將原有的device token一塊發(fā)送給服務(wù)器端,服務(wù)器端刪除原有令牌存儲(chǔ)新令牌避免服務(wù)器端發(fā)送無效消息。

4.應(yīng)用程序提供商在服務(wù)器端根據(jù)前面發(fā)送過來的device token組織信息發(fā)送給APNs。

說明:

a.發(fā)送時(shí)指定device token和消息內(nèi)容,并且完全按照蘋果官方的消息格式組織消息內(nèi)容,通常情況下可以借助其他第三方消息推送框架來完成。

5.APNs根據(jù)消息中的device token查找已注冊(cè)的設(shè)備推送消息。

說明:

a.正常情況下可以根據(jù)device token將消息成功推送到客戶端設(shè)備中,但是也不排除用戶卸載程序的情況,此時(shí)推送消息失敗,APNs會(huì)將這個(gè)錯(cuò)誤消息通知服務(wù)器端以避免資源浪費(fèi)(服務(wù)器端此時(shí)可以根據(jù)錯(cuò)誤刪除已經(jīng)存儲(chǔ)的device token,下次不再發(fā)送)。

下面將簡(jiǎn)單演示一下推送通知的簡(jiǎn)單流程:


@implementation AppDelegate

#pragma mark - 應(yīng)用程序代理方法

#pragma mark 應(yīng)用程序啟動(dòng)之后

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

_window=[[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];

_window.backgroundColor =[UIColor colorWithRed:249/255.0 green:249/255.0 blue:249/255.0 alpha:1];

//設(shè)置全局導(dǎo)航條風(fēng)格和顏色

[[UINavigationBar appearance] setBarTintColor:[UIColor colorWithRed:23/255.0 green:180/255.0 blue:237/255.0 alpha:1]];

[[UINavigationBar appearance] setBarStyle:UIBarStyleBlack];

KCMainViewController *mainController=[[KCMainViewController alloc]init];

_window.rootViewController=mainController;

[_window makeKeyAndVisible];

//注冊(cè)推送通知(注意iOS8注冊(cè)方法發(fā)生了變化)

[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert|UIUserNotificationTypeBadge|UIUserNotificationTypeSound categories:nil]];

[application registerForRemoteNotifications];

return YES;

}

#pragma mark 注冊(cè)推送通知之后

//在此接收設(shè)備令牌

-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{

[self addDeviceToken:deviceToken];

NSLog(@"device token:%@",deviceToken);

}

#pragma mark 獲取device token失敗后

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{

NSLog(@"didFailToRegisterForRemoteNotificationsWithError:%@",error.localizedDescription);

[self addDeviceToken:nil];

}

#pragma mark 接收到推送通知之后

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{

NSLog(@"receiveRemoteNotification,userInfo is %@",userInfo);

}

#pragma mark - 私有方法

/**

*? 添加設(shè)備令牌到服務(wù)器端

*

*? @param deviceToken 設(shè)備令牌

*/

-(void)addDeviceToken:(NSData *)deviceToken{

NSString *key=@"DeviceToken";

NSData *oldToken= [[NSUserDefaults standardUserDefaults]objectForKey:key];

//如果偏好設(shè)置中的已存儲(chǔ)設(shè)備令牌和新獲取的令牌不同則存儲(chǔ)新令牌并且發(fā)送給服務(wù)器端

if (![oldToken isEqualToData:deviceToken]) {

[[NSUserDefaults standardUserDefaults] setObject:deviceToken forKey:key];

[self sendDeviceTokenWidthOldDeviceToken:oldToken newDeviceToken:deviceToken];

}

}

-(void)sendDeviceTokenWidthOldDeviceToken:(NSData *)oldToken newDeviceToken:(NSData *)newToken{

//注意一定確保真機(jī)可以正常訪問下面的地址

NSString *urlStr=@"http://192.168.1.101/RegisterDeviceToken.aspx";

urlStr=[urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

NSURL *url=[NSURL URLWithString:urlStr];

NSMutableURLRequest *requestM=[NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10.0];

[requestM setHTTPMethod:@"POST"];

NSString *bodyStr=[NSString stringWithFormat:@"oldToken=%@&newToken=%@",oldToken,newToken];

NSData *body=[bodyStr dataUsingEncoding:NSUTF8StringEncoding];

[requestM setHTTPBody:body];

NSURLSession *session=[NSURLSession sharedSession];

NSURLSessionDataTask *dataTask= [session dataTaskWithRequest:requestM completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

if (error) {

NSLog(@"Send failure,error is :%@",error.localizedDescription);

}else{

NSLog(@"Send Success!");

}

}];

[dataTask resume];

}

@end

? ? ? ? ?iOS開發(fā)過程中如果需要進(jìn)行真機(jī)調(diào)試、發(fā)布需要注冊(cè)申請(qǐng)很多證書,會(huì)牽扯到一些特殊配置,這里就簡(jiǎn)單的對(duì)iOS開發(fā)的常用證書和秘鑰等做一說明。

證書

iOS常用的證書包括開發(fā)證書和發(fā)布證書,無論是真機(jī)調(diào)試還是最終發(fā)布應(yīng)用到App Store這兩個(gè)證書都是必須的,它是iOS開發(fā)的基本證書。

a.開發(fā)證書:開發(fā)證書又分為普通開發(fā)證書和推送證書,如果僅僅是一般的應(yīng)用則前者即可滿足,但是如果開發(fā)推送應(yīng)用則必須使用推送證書。

b.發(fā)布證書:發(fā)布證書又可以分為普通發(fā)布證書、推送證書、Pass Type ID證書、站點(diǎn)發(fā)布證書、VoIP服務(wù)證書、蘋果支付證書。同樣的,對(duì)于需要使用特殊服務(wù)的應(yīng)用則必須選擇對(duì)應(yīng)的證書。

應(yīng)用標(biāo)識(shí)

App ID,應(yīng)用程序的唯一標(biāo)識(shí),對(duì)應(yīng)iOS應(yīng)用的Bundle Identifier,App ID在蘋果開發(fā)者中心中分為通配應(yīng)用ID和明確的應(yīng)用ID,前者一般用于普通應(yīng)用開發(fā),一個(gè)ID可以適用于多個(gè)不同標(biāo)識(shí)的應(yīng)用;但是對(duì)于使用消息推送、Passbook、站點(diǎn)發(fā)布、iCloud等服務(wù)的應(yīng)用必須配置明確的應(yīng)用ID。

設(shè)備標(biāo)識(shí)

UDID,用于標(biāo)識(shí)每一臺(tái)硬件設(shè)備的標(biāo)示符。注意它不是device token,device token是根據(jù)UDID使用一個(gè)只有Apple自己才知道的算法生成的一組標(biāo)示符。


本文內(nèi)容自參考:http://www.cnblogs.com/kenshincui/p/4168532.html

http://www.cnblogs.com/kenshincui/p/4168532.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、簡(jiǎn)介 目前說的是基于ios10之前,所以有些類是過期的. 推送分為本地推送和遠(yuǎn)程推送2種??梢栽趹?yīng)用沒有打開甚...
    JingYa_Lu閱讀 969評(píng)論 0 0
  • 概述 在多數(shù)移動(dòng)應(yīng)用中任何時(shí)候都只能有一個(gè)應(yīng)用程序處于活躍狀態(tài),如果其他應(yīng)用此刻發(fā)生了一些用戶感興趣的那么通過通知...
    莫離_焱閱讀 6,708評(píng)論 1 8
  • 極光推送: 1.JPush當(dāng)前版本是1.8.2,其SDK的開發(fā)除了正常的功能完善和擴(kuò)展外也緊隨蘋果官方的步伐,SD...
    Isspace閱讀 6,873評(píng)論 10 16
  • *推送: 1、遠(yuǎn)程推送(Remote Notification) 2、本地推送(local Notificatio...
    磊CC閱讀 422評(píng)論 0 0
  • 美,我美么?我一直都不美,我很渴望變美。 我長(zhǎng)相普通,雖不拉全國(guó)顏值平均數(shù),但決不會(huì)是給加分的。 我身體比例不協(xié)調(diào)...
    小小火紅閱讀 610評(píng)論 0 1

友情鏈接更多精彩內(nèi)容