蘋果的遠程推送APNS:
原理過程什么的就不說了,這里主要是為了記錄一下今天解決推送所遇到的坑。
步驟主要分為四部分:
- 請求證書
- 處理證書以及p.12文件等問題
- 客戶端這邊根據需要設置一下
- 測試一下可行性
請求證書 && 處理證書及p.12文件
- 創建APP ID
登錄Apple Member Center :https://developer.apple.com/membercenter,選擇certificates,identifiers&profiles
選項,如下圖所示:
起始頁
選擇identity
中的APP IDs
,如下圖所示:
創建id
注意:創建Explicit App ID
時,要注意此時設置的Bundle ID要與APP以后的Bundle ID一致,如下圖所示:
Bundle ID
來開通Push功能,如下圖所示:
開通Push功能
按鈕,幾秒鐘之后下方會變成一個Done
,表示APP ID已經創建完成,如下圖所示:
感謝友盟+感謝友盟+感謝友盟+
至此,APP ID創建完畢。
- 創建CSR文件
如果你已經有CSR文件,請繼續進行下一步的設置。
CSR是Cerificate Signing Request的英文縮寫,即證書請求文件。證書申請者在申請數字證書時由CSP(加密服務提供者)在生成私鑰的同時也生成證書請求文件。證書申請者只要把CSR文件提交給證書頒發機構后,證書頒發機構使用其根證書私鑰簽名就生成了證書公鑰文件,也就是頒發給用戶的證書。
在電腦中找到鑰匙串----->鑰匙串訪問------>證書管理------>從證書頒發機構請求證書,如下圖所示:
設置完證書信息后,點擊“繼續”,然后選擇存儲位置,點擊存儲,至此,CSR文件創建成功。
- 創建開發調試證書
如果你已經有開發調試證書,請繼續進行下一步的設置。
選擇Development(如果是發布上線,需要選擇Distribution),如下圖所示:
在choose file...中選擇本地的CertificateSigningRequest(CSR)文件,然后點擊繼續,如下圖所示:
點擊Download,將證書下載到本地,雙擊下載的開發調試證書(文件名為:iOS_development.cer),就可以在鑰匙串訪問中的我的證書中找到。
至此,開發調試證書設置完畢。
-
添加測試設備
測試推送需要添加測試設備,添加方法如下所示:
這里寫圖片描述這里寫圖片描述這里寫圖片描述這里寫圖片描述 - 創建Provisioning Profiles文件
選擇Development,創建開發環境的Provisioning Profiles(如果是發布上線,需要選擇Distribution),如下圖所示:
這里寫圖片描述
這里寫圖片描述
創建新的Provisioning Profiles,并選擇之前生成好的App ID。如下圖所示:
這里寫圖片描述
選中創建的證書:
這里寫圖片描述
選中測試設備:
把創建的Provisioning Profiles,調試證書,推送證書下載下來(文件名:umengpushtestdemo.mobileprovision)以后雙擊證書。
- 創建推送證書
選擇Apple Push Notification service SSL(Sandbox)
這里寫圖片描述
注意:推送證書分為開發環境和生產環境,如果需要生成生產環境的推送證書請選擇: Apple Push Notification service SSL (Sandbox&Production)
,如下圖所示:這里寫圖片描述
選中APP ID后,點擊continue,直到上傳CRS文件,如下圖所示:
點擊Download,將證書下載到本地后,雙擊下載的開發環境推送證書(文件名為:aps_development.cer),就可以在鑰匙串訪問中的我的證書中找到。
** 這里我要說的坑就是,在雙擊開發證書之后,在登錄選項下,竟然沒有發現上述圖片所說的那個秘鑰!!!!!!!在這里我刪了又重來刪了有重來好幾次了**
最后。。。。我?直接拉進去,竟然可以了~
- 導出推送證書的P12文件
注意:在鑰匙串訪問(KeyChain)的我的證書中選擇剛剛導入的證書,選擇導出,注意不要選中私鑰,并設置相應密碼即可。
注意:此步驟所設置的密碼將在之后在U-Push后臺上傳推送證書時所使用。
生產環境的推送證書也是以同樣的方式導出。
至此,P12證書導出完畢。
上面所說的那些,我都是在友盟看回來的,感謝友盟
客戶端接收設置
1、注冊遠程推送以及設置相關選項:
// 這里其實還有個ios版本區分的,但是項目需求是7.0以上的版本,所以這里沒有考慮其他情況。
UIRemoteNotificationType types = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert;
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:types];
這里還需要對Capabilites進行設置以確保能接受到推送:
2、在APPDelegate.m的接收函數
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if (launchOptions) {
//如果應用還沒啟動,則通過push冷啟動后,仍能在激動之后獲取Dictionary
NSDictionary *userInfo = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey];
if (userInfo) {
//有推送消息優先處理推送消息
NSLog(@"Dictionary:%@",userInfo);
}
// 當userInfo設置了badge,應用圖標上將一直顯示一個數字提示,如果要清除數字提示,或者設置成其他數字,調用下面函數就可以完成。
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:0];
}
return YES;
}
//注冊成功回調方法,其中deviceTocken是APNS返回的token
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
NSLog(@"Devtocken:%@",deviceToken);
}
//注冊失敗返回調用方法,處理失敗情況
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
NSLog(@"獲取DeviceTocken失敗:%@",error);
}
//當程序在前臺運行,接收到消息不會有消息提示(提示框或橫幅)。
//當程序運行在后臺,接收到消息會有消息提示,點擊消息后進入程序,
//AppDelegate的didReceiveRemoteNotification函數會被調用,消息做為此函數的參數傳入
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)payload {
NSLog(@"remote notification: %@",[payload description]);
NSString* alertStr = nil;
NSDictionary *apsInfo = [payload objectForKey:@"aps"];
NSObject *alert = [apsInfo objectForKey:@"alert"];
if ([alert isKindOfClass:[NSString class]])
{
alertStr = (NSString*)alert;
}
else if ([alert isKindOfClass:[NSDictionary class]])
{
NSDictionary* alertDict = (NSDictionary*)alert;
alertStr = [alertDict objectForKey:@"body"];
}
application.applicationIconBadgeNumber = [[apsInfo objectForKey:@"badge"] integerValue];
//當程序存活并受到來自APNS的推送時執行的方法:
if ([application applicationState] == UIApplicationStateActive && alertStr != nil)
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pushed Message" message:alertStr delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
if ([application applicationState] == UIApplicationStateBackground) {
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Pushed Message" message:alertStr delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alertView show];
}
}
測試一下
在網上搜羅了一下,有好幾種方式可以達到檢測的目的,首推的,也是最簡單的,在Mac上運行的,直接在github上可以拿到改demo:PushMeBaby
這里只需要簡單的在APPdelegate中配置一下DeviceToken以及把推送證書放到項目工程中就可以了。 ** 此處有坑 **:這里需要把這個選項給選上,不然在讀取證書路徑的時候就會失敗。
** 同時這里還存在第二個坑:**
在設置deviceToken時,需要保留空格,去掉尖括弧
運行一下,push一下就可以了,有時候網絡問題也會導致一些延遲。
這里我其實還測試了另外的一種方法:php推送
1 .首先將證書文件和私鑰處理成單個方便使用的pem文件,假設CSR、p12和cer文件都放在桌面上。
$ cd ~/Desktop$ls
aps_development.cer
CertificateSigningRequest.certSigningRequest
PushKey.p12
2 .將aps_development.cer轉換為pem文件。
$ openssl x509 -in aps_development.cer -inform der -out PushCert.pem
$ls
aps_development.cer
CertificateSigningRequest.certSigningRequest
PushCert.pem
PushKey.p12
3 .將p12私鑰文件轉換為pem文件。
$ openssl pkcs12 -nocerts -out PushKey.pem -in PushKey.p12
Enter Import Password:
MAC verified OK
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
4 .將兩個文件合成同一個。
$ cat PushCert.pem PushKey.pem > ck.pem
$ls
aps_development.cer
CertificateSigningRequest.certSigningRequest
ck.pem
PushCert.pem
PushKey.pem
PushKey.p12
5 .測試證書是否有效。
$ openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem
如果有效的話,會輸出一堆信息,并且建立連接,否則不會成功建立連接。
6 .使用PHP進行測試,下載SimplePush.php,修改文件并填入deviceToken和密碼。在終端運行該代碼。
$ php simplepush.php Connected to APNSMessage successfully delivered
成功發送推送消息。
(此方法感謝:戴維營教育原創文章)
** 關于推送json格式的說明 **
- 推送負載:
遠程通知負載的大小根據Provider使用的API不同而不同。當使用HTTP/2 provider API時,負載最大為4096bytes,即4kB;當使用legacy binary interface時,負載最大為2048bytes,即2kB。當負載大小超過規定的負載大小時,APNs會拒絕發送此消息。
- 遠程推送負載內容
內容格式必要要知道的啊,服務端一般會要我們客戶端定義好格式給他們的。
每一條通知的消息都會組成一個JSON字典對象,其格式如下所示,示例中的key值為蘋果官方所用key。自定義字段的時候要避開這些key值。
每一條通知的消息都會組成一個JSON字典對象,其格式如下所示,示例中的key值為蘋果官方所用key。自定義字段的時候要避開這些key值。
{
"aps" : {
"alert" : { // string or dictionary
"title" : "string"
"body" : "string",
"title-loc-key" : "string or null"
"title-loc-args" : "array of strings or null"
"action-loc-key" : "string or null"
"loc-key" : "string"
"loc-args" : "array of strings"
"launch-image" : "string"
},
"badge" : number,
"sound" : "string"
"content-available" : number;
"category" : "string"
},
}
aps:推送消息必須有的key
alert:推送消息包含此key值,系統就會根據用戶的設置展示標準的推送信息
badge:在app圖標上顯示消息數量,缺少此key值,消息數量就不會改變,消除標記時把此key對應的value設置為0
sound:設置推送聲音的key值,系統默認提示聲音對應的value值為default
content-available:此key值設置為1,系統接收到推送消息時就會調用不同的回調方法,iOS7之后配置后臺模式
category:UIMutableUserNotificationCategory's identifier 可操作通知類型的key值
title:簡短描述此調推送消息的目的,適用系統iOS8.2之后版本
body:推送的內容
title-loc-key:功能類似title,附加功能是國際化,適用系統iOS8.2之后版本
title-loc-args:配合title-loc-key字段使用,適用系統iOS8.2之后版本
action-loc-key:可操作通知類型key值,不詳細敘述
loc-key:參考title-loc-key
loc-args:參考title-loc-args
launch-image:點擊推送消息或者移動事件滑塊時,顯示的圖片。如果缺少此key值,會加載app默認的啟動圖片。
后邊這一對是自定義的,但是要注意不可以和前面的重復
"badge" : number,
"sound" : "string"
"content-available" : number;
"category" : "string"
此處出自TIME_for 的《iOS推送之遠程推送(iOS Notification Of Remote Notification》)
搬運工再次感謝各位前輩的付出。謝謝!