現(xiàn)在為我們的項(xiàng)目添加推送功能有兩種方式
1:使用Token Authentication (p8)
方式,也是現(xiàn)在推薦的方式
Token Authentication (p8)
是 APNs 新推出的推送鑒權(quán)方式,這種新的方式有很多優(yōu)勢
- 同一個(gè)賬戶下所有 App 無論是測試 App 還是正式版 App募强,都能使用同一個(gè) key 來發(fā)推送消息和 voice-over-Internet Protocol (VoIP) 消息姿染,不再需要為每個(gè) App 生成一個(gè)證書
- 生成的 Auth Key 不再有過期時(shí)間赋咽,無需像證書那樣每年需要重新生成一次
- 生成過程簡單,不需要繁瑣菌湃、易錯(cuò)的證書導(dǎo)出操作
創(chuàng)建Token Authentication (p8)
點(diǎn)擊keys旁邊的添加,然后我們勾選圖中的選擇遍略,點(diǎn)擊continue
下載后會(huì)有一個(gè).p8文件惧所,
AuthKey_keyxxxxx.p8
如果我們使用第三方推送,比如友盟绪杏,個(gè)推等下愈,我們還需要
Team ID
這里以友盟推送示列,我們?nèi)ビ衙松吓渲靡幌吕倬茫詈簏c(diǎn)擊確認(rèn)添加势似,如果不出意外,添加成功
2:使用證書的方式來添加消息推送
1:從CA請(qǐng)求證書
2:蘋果開發(fā)者網(wǎng)站創(chuàng)建推送證書僧著,點(diǎn)擊+號(hào)
我們創(chuàng)建開發(fā)和發(fā)布環(huán)境都支持的證書
選擇我們要?jiǎng)?chuàng)建推送證書的App ID履因,綁定證書與App的關(guān)系,這個(gè)App就可以實(shí)現(xiàn)消息推送功能
選擇剛剛創(chuàng)建的CA證書
創(chuàng)建成功盹愚,下載證書搓逾,并添加到鑰匙串中
導(dǎo)出.p12文件備用
3:如果之前創(chuàng)建了App ID,我們需要為此App ID開啟推送
4:如果已經(jīng)創(chuàng)建描述文件杯拐,需要重新保存
5:使用證書方式推送霞篡,我們?nèi)ビ衙藶榇朔绞竭M(jìn)行配置
3:設(shè)置xcode,開啟推送功能
在xcode中為我們的項(xiàng)目打開我們的消息推送功能
其他消息推送功能也記錄下端逼,關(guān)于app后臺(tái)運(yùn)行的功能
voice over ip 簡稱voip
朗兵,需要配置證書,如果你的項(xiàng)目包含語音通話顶滩,類似微信語音視頻功能余掖,可以選擇此項(xiàng),app處于后臺(tái)或者殺死app礁鲁,收到此消息都會(huì)喚醒a(bǔ)pp執(zhí)行一個(gè)方法盐欺,審核需要提供呼叫功能演示視頻
Remote nitifications 靜默推送
,推送方式類似消息推送仅醇,不過不會(huì)彈出消息框冗美,app處于后臺(tái)會(huì)被喚醒調(diào)用一個(gè)方法,我們可以在這個(gè)方法中處理一些事情析二,但是殺掉app就收不到此推送
APNS
普通消息推送粉洼,app處于后臺(tái)或者殺死app都能收到节预,但不會(huì)喚醒a(bǔ)pp調(diào)用方法
這里我選擇開啟后臺(tái)的靜默推送
添加推送的代碼,使用友盟推送
// Push功能配置
UMessageRegisterEntity * entity = [[UMessageRegisterEntity alloc] init];
entity.types = UMessageAuthorizationOptionBadge|UMessageAuthorizationOptionAlert|UMessageAuthorizationOptionSound;
if (@available(iOS 10.0, *)) {
// 如果要在iOS10顯示交互式的通知属韧,必須注意實(shí)現(xiàn)以下代碼
UNNotificationAction *action1_ios10 = [UNNotificationAction actionWithIdentifier:@"action1_identifier" title:@"打開應(yīng)用" options:UNNotificationActionOptionForeground];
UNNotificationAction *action2_ios10 = [UNNotificationAction actionWithIdentifier:@"action2_identifier" title:@"忽略" options:UNNotificationActionOptionForeground];
//UNNotificationCategoryOptionNone
//UNNotificationCategoryOptionCustomDismissAction 清除通知被觸發(fā)會(huì)走通知的代理方法
//UNNotificationCategoryOptionAllowInCarPlay 適用于行車模式
UNNotificationCategory *category1_ios10 = [UNNotificationCategory categoryWithIdentifier:@"category1" actions:@[action1_ios10, action2_ios10] intentIdentifiers:@[] options:UNNotificationCategoryOptionCustomDismissAction];
NSSet *categories = [NSSet setWithObjects:category1_ios10, nil];
entity.categories = categories;
[UNUserNotificationCenter currentNotificationCenter].delegate = self;
}else {
// 如果你期望使用交互式(只有iOS 8.0及以上有)的通知安拟,請(qǐng)參考下面注釋部分的初始化代碼
UIMutableUserNotificationAction *action1 = [[UIMutableUserNotificationAction alloc] init];
action1.identifier = @"action1_identifier";
action1.title=@"打開應(yīng)用";
action1.activationMode = UIUserNotificationActivationModeForeground;//當(dāng)點(diǎn)擊的時(shí)候啟動(dòng)程序
UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init]; //第二按鈕
action2.identifier = @"action2_identifier";
action2.title=@"忽略";
action2.activationMode = UIUserNotificationActivationModeBackground;//當(dāng)點(diǎn)擊的時(shí)候不啟動(dòng)程序,在后臺(tái)處理
action2.authenticationRequired = YES;//需要解鎖才能處理宵喂,如果action.activationMode = UIUserNotificationActivationModeForeground;則這個(gè)屬性被忽略糠赦;
action2.destructive = YES;
UIMutableUserNotificationCategory *actionCategory1 = [[UIMutableUserNotificationCategory alloc] init];
actionCategory1.identifier = @"category1"; //這組動(dòng)作的唯一標(biāo)示
[actionCategory1 setActions:@[action1, action2] forContext:(UIUserNotificationActionContextDefault)];
NSSet *categories = [NSSet setWithObjects:actionCategory1, nil];
entity.categories = categories;
}
[UMessage registerForRemoteNotificationsWithLaunchOptions:launchOptions Entity:entity completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted) {
DLog(@"注冊(cè)消息通知成功");
}else {
}
}];
// 注冊(cè)消息推送成功,收到token
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//獲取終端設(shè)備標(biāo)識(shí)锅棕,這個(gè)標(biāo)識(shí)需要通過接口發(fā)送到服務(wù)器端愉棱,服務(wù)器端推送消息到APNS時(shí)需要知道終端的標(biāo)識(shí),APNS通過注冊(cè)的終端標(biāo)識(shí)找到終端設(shè)備哲戚。
NSLog(@"推送的token %@",[[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""]
stringByReplacingOccurrencesOfString: @">" withString: @""]
stringByReplacingOccurrencesOfString: @" " withString: @""]);
// DLog(@"推送的token %@", currentDeviceToken);
[UMessage registerDeviceToken:deviceToken];
}
// ios10以下 前臺(tái)收到推送消息
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
DLog(@"推送消息 didReceiveRemoteNotification")
}
// ios10以下 后臺(tái)收到消息推送
-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[UMessage setAutoAlert:NO];
DLog(@"推送消息 didReceiveRemoteNotification fetchCompletionHandler");
if([[[UIDevice currentDevice] systemVersion] intValue] < 10){
[UMessage didReceiveRemoteNotification:userInfo];
}
completionHandler(UIBackgroundFetchResultNewData);
}
//iOS10新增:處理前臺(tái) *收到通知的代理方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler API_AVAILABLE(ios(10.0)){
NSDictionary * userInfo = notification.request.content.userInfo;
if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
// 不要開啟彈出框
[UMessage setAutoAlert:NO];
// 應(yīng)用處于前臺(tái)時(shí)的遠(yuǎn)程推送接受
// 必須加這句代碼
[UMessage didReceiveRemoteNotification:userInfo];
}else{
//應(yīng)用處于前臺(tái)時(shí)的本地推送接受
}
DLog(@"推送消息 userNotificationCenter willPresentNotification");
completionHandler(UNNotificationPresentationOptionSound|UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionAlert);
}
//iOS10新增:處理后臺(tái) *點(diǎn)擊通知的代理方法(后臺(tái)靜默推送會(huì)調(diào)用此方法)
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler API_AVAILABLE(ios(10.0)){
NSDictionary * userInfo = response.notification.request.content.userInfo;
if (@available(iOS 10.0, *)) {
if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
//應(yīng)用處于后臺(tái)時(shí)的遠(yuǎn)程推送接受
//必須加這句代碼
[UMessage didReceiveRemoteNotification:userInfo];
}else{
//應(yīng)用處于后臺(tái)時(shí)的本地推送接受
}
} else {
// Fallback on earlier versions
}
DLog(@"推送消息 userNotificationCenter didReceiveNotificationResponse");
}
4:遇到的坑奔滑,關(guān)于使用友盟推送遇到的問題記錄
使用友盟推送時(shí),當(dāng)我們使用development證書調(diào)試時(shí)顺少,無法收到推送的消息朋其,推送失敗如下device-token全部失敗
我們可以發(fā)現(xiàn)下圖中,debug下選擇的development證書的ID與TeamID不相同
我們看看release下選擇的distribution證書ID和TeamID是相同的
嘗試在debug下使用distribution證書脆炎,真機(jī)無法運(yùn)行起來
解決辦法1:將程序打包成Ad hoc安裝梅猿,這樣就可以收到消息推送
解決辦法2:使用測試消息推送的工具,比如Pusher秒裕,測試工具需要選擇證書推送的情況下才能使用
5:記錄下消息推送的格式
iOS10之前的格式
{
"aps":{
"alert":"內(nèi)容",
"badge":1,
"sound":"default",
"userinfo":{"username":"tom"}
}
}
iOS 10及之后(iOS7袱蚓、iOS8、iOS9可通用此模板)
{
"aps":{
"alert":{
"title":"標(biāo)題", // iOS7几蜻、8設(shè)置無效喇潘,iOS9一般設(shè)置為appName
"subtitle":"子標(biāo)題", // 一般使用title就能滿足需求
"body":"內(nèi)容"
},
"badge":1, //角標(biāo)數(shù)
"sound":"default", //聲音
"userinfo":{ //通知內(nèi)容信息
"playid":"123",
"username":"tom",
"sex":1
}
}
}
參考文章:
https://leancloud.cn/docs/ios_push_cert.html#hash1133282448
https://developer.umeng.com/docs/66632/detail/66734
https://blog.csdn.net/zykccss/article/details/58259240