iOS_APNS(蘋果遠(yuǎn)程推送)

感謝Hello杰少的文章,我在此基礎(chǔ)上進(jìn)行豐富

1/11. 獲取CSR文件
為了便于文件管理,所有文件都放在AppPush文件夾中。命令行中的命令也在改文件夾下。
本次操作基于開發(fā)模式下,生產(chǎn)模式下類同,相關(guān)文件改為在Distribution下創(chuàng)建即可。

2/11. 進(jìn)入MemberCenter,選擇創(chuàng)建 AppID。填寫App ID Description,然后選擇Explicit App ID(推送不能使用模糊匹配的id)填寫你所要開發(fā)的app的準(zhǔn)確Bundle ID。 同時(shí)要在App Services中勾選Push Notifications,然后continue,然后register。

應(yīng)用描述與Bundle ID
勾選Push

3/11. 接下來(lái)配置推送證書??梢栽赼ppID中配置,也可以在Certificates配置,但在appID中更便捷。 選擇剛剛創(chuàng)建的appID,然后可以看到Push Notifications處于可設(shè)置狀態(tài),選擇Edit。


Push Notifications處于可設(shè)置狀態(tài)

4/11. 接下來(lái)在push notifications下選擇創(chuàng)建證書,此時(shí)其實(shí)也就是跳轉(zhuǎn)到了Certificates中來(lái)配置。


crecer.png

5/11. 接下來(lái)continue,然后在提示要csr文件時(shí)提交剛開始創(chuàng)建的csr文件,然后生成證書,下載下來(lái)后保存文件名為aps_push.cer,然后雙擊證書自動(dòng)安裝到鑰匙串中。

6/11 接著還需要mobileprovision文件。選擇創(chuàng)建profile,然后選擇iOS App Development,點(diǎn)擊continue。選擇上面創(chuàng)建的AppID,選擇開發(fā)者賬號(hào),選擇測(cè)試設(shè)備,然后一路continue,最后輸入profile文件名,這里設(shè)為pushTest。然后Generate,再下載下來(lái)雙擊即可自動(dòng)安裝到xcode中。

7/11. 在鑰匙串中找到剛剛安裝的aps_push.cer證書,右鍵選擇導(dǎo)出,然后這里最好把存儲(chǔ)文件名修改為英文,然后選擇存儲(chǔ)。接著要求設(shè)置證書密碼,這里設(shè)置為abc123,然后還要輸入管理員密碼。搞定這些,所需要的p12文件就OK了。


exportCer.png
savep12.png

8/11. 在接下來(lái)還要對(duì)證書進(jìn)行整合處理,在終端中進(jìn)入AppPush文件夾,
然后執(zhí)行命令openssl x509 -in aps_push.cer -inform der -out PushCert.pem 獲得一個(gè)PushCert.pem文件。
接著再執(zhí)行命令openssl pkcs12 -nocerts -in pushTest.p12 -out PushKey.pem,這時(shí)需要輸入p12文件的密碼,就是上邊設(shè)置的abc123,然后還要設(shè)置PushKey.pem文件的密碼,依然設(shè)為abc123. 最后獲的一個(gè)PushKey.pem文件。
然后還有最后一擊,執(zhí)行命令cat PushCert.pem PushKey.pem > ck.pem 獲取最終服務(wù)器要用的ck.pem文件

9/11. 經(jīng)過(guò)以上的步驟,所需要的文件都準(zhǔn)備好了,但是為了確保完事具備,還要進(jìn)行簡(jiǎn)單的測(cè)試。
執(zhí)行命令telnet gateway.sandbox.push.apple.com 2195,檢測(cè)是否可以訪問(wèn)apple的推送服務(wù)器.顯示如下則表明是OK的。(中間需要使用control+c來(lái)中斷連接)

測(cè)試網(wǎng)絡(luò)

執(zhí)行命令openssl s_client -connect gateway.sandbox.push.apple.com:2195 -cert PushCert.pem -key PushKey.pem 測(cè)試上面生成的證書是否OK。內(nèi)容很多,但只用關(guān)心最后是否如圖所示,是則表示證書是OK的。這里也要輸入密碼及用control+c中斷連接

測(cè)試證書是否OK

10/11. 經(jīng)過(guò)上面的繁瑣步驟終于準(zhǔn)備好素材了。。。。。。開始實(shí)際代碼開發(fā)吧。 新建工程,保證工程的Bundle ID和上邊請(qǐng)求證書時(shí)使用的Bundle ID一致即可。然后代碼的戰(zhàn)場(chǎng)在AppDelegate.m中,不涉及其他地方。運(yùn)行一次程序,從log信息中獲取到deviceToken值(注意:如果上面沒(méi)有安裝profile文件,那么也會(huì)獲取到一個(gè)deviceToken值,但是這個(gè)值是沒(méi)卵用的)。

//
//  AppDelegate.m
//  apnsTest
//
//  Created by yuweiMac on 16/4/28.
//  Copyright ? 2016年 yuweiMac. All rights reserved.
//

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    //    調(diào)用該方法有3種路徑:點(diǎn)擊appIcon或者點(diǎn)擊通知進(jìn)入或者第三方應(yīng)用跳轉(zhuǎn)。
    //    如果點(diǎn)擊appIcon進(jìn)入時(shí)launchOptions為nil。其他則 !nil,但兩者的key同
    if (launchOptions == nil) {
        [self showAlertWithTitle:@"由AppIcon啟動(dòng)" msg:[launchOptions description]];
    }else{
        if ([[launchOptions allKeys] containsObject:@"UIApplicationLaunchOptionsURLKey"]) {
            [self showAlertWithTitle:@"由第三方應(yīng)用啟動(dòng)" msg:[launchOptions description]];
            
        } else {
            
            [self showAlertWithTitle:@"點(diǎn)擊通知啟動(dòng)" msg:[launchOptions description]];
        }
    }
    
    //    注冊(cè)推送權(quán)限.iOS8之前的注冊(cè)方式不一樣,但現(xiàn)在最低兼容ios8,忘了7吧
    //    if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
    //    {
    //IOS8
    //創(chuàng)建UIUserNotificationSettings,并設(shè)置消息的顯示類類型
    //    可以通過(guò)判斷是否已經(jīng)注冊(cè)遠(yuǎn)程通知來(lái)決定是否要進(jìn)行注冊(cè)操作,這里不這么做。
    //    if (![application isRegisteredForRemoteNotifications]) {
    
    //        注冊(cè)通知權(quán)限
    UIUserNotificationSettings *notiSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert) categories:nil];
    
    [application registerUserNotificationSettings:notiSettings];
    //        注冊(cè)遠(yuǎn)程通知
    [application registerForRemoteNotifications];
    //    }
    
    //    } else{ // ios7
    //        [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge                                       |UIRemoteNotificationTypeSound                                      |UIRemoteNotificationTypeAlert)];
    //    }
    
    return YES;
}


-(void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings{
    //    成功注冊(cè)消息通知權(quán)限
    NSLog(@"成功注冊(cè)消息通知");
}



-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    //    成功注冊(cè)遠(yuǎn)程推送并獲得deviceToken信息
    NSLog(@"didRegisterForRemote---deviceToken-->%@", deviceToken);
}

-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    //    注冊(cè)遠(yuǎn)程推送失敗
    NSLog(@"FailToRegisterForRemoteN---fail-->%@",error);
}

-(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo{
    
    //    當(dāng)應(yīng)用在前臺(tái)時(shí)接收到遠(yuǎn)程推送消息
    [self showAlertWithTitle:@"收到遠(yuǎn)程推送消息" msg:[userInfo description]];
}

//當(dāng)從第三方應(yīng)用跳轉(zhuǎn)到本應(yīng)用時(shí)會(huì)調(diào)用該方法
-(BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation{
    
    NSLog(@"-->%@   -->%@",url,sourceApplication);
    
    return YES;
}

//彈出信息警告框
-(void)showAlertWithTitle:(NSString*)title msg:(NSString*)msg{
    
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg  delegate:nil cancelButtonTitle:nil otherButtonTitles:@"確定",nil];
    [alert show];
}

@end

11//11.接下來(lái)要寫一個(gè)AppPush.php文件,來(lái)向apns服務(wù)器發(fā)送內(nèi)容。
需要注意的幾個(gè)地方:deviceToken填寫你接收到的token;passPhrase則填寫你的ck.pem設(shè)置的密碼。當(dāng)然如果你在上邊保存文件時(shí)命名不是ck,那還需要替換程序內(nèi)的文件名稱$pemFile。 最后再在終端中執(zhí)行命令php AppPush.php,然后一切都應(yīng)該很美好的OK了。


<?php

// ??????????deviceToken???????????????
$deviceToken = '493c0d7eaa19a529a4422cd9ee779fc474f95b9915051118887fed7e1b0af85f';

// Put your private key's passphrase here:
$passphrase = 'abc123';

$pemFile = 'ck.pem';

// Put your alert message here:
$message = 'My first push test!';

////////////////////////////////////////////////////////////////////////////////

$ctx = stream_context_create();
stream_context_set_option($ctx, 'ssl', 'local_cert', $pemFile);
stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase);

// Open a connection to the APNS server
$fp = stream_socket_client(
'ssl://gateway.sandbox.push.apple.com:2195', $err,
$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);

if (!$fp)
exit("Failed to connect: $err $errstr" . PHP_EOL);

echo 'Connected to APNS' . PHP_EOL;

// Create the payload body
$body['aps'] = array(
'alert' => $message,
'sound' => 'default'
);

// Encode the payload as JSON
$payload = json_encode($body);

// Build the binary notification
$msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;

// Send it to the server
$result = fwrite($fp, $msg, strlen($msg));

if (!$result)
echo 'Message not delivered' . PHP_EOL;
else
echo 'Message successfully delivered' . PHP_EOL;

// Close the connection to the server
fclose($fp);
?>

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容