iOS集成環信推送,最詳細流程(證書創建、環信集成、測試)

一.推送的原理和流程(著急做推送的可以跳過這一步)
首先給大家推薦一個介紹推送機制很優秀的帖子:http://www.lxweimin.com/p/ac397a033dec ,里面關于本地推送和遠程推送的介紹都很詳細,至少我看了感覺還是收獲很多的.尤其是里面有幾張圖片不知道是博主在哪里找的,但是真的是一看就透,太贊了,所以我果斷盜過來了0.0. 這里我對推送的流程做了一個簡單的敘述,力求用最簡單的語言能說明整個推送的機制.

1.png
2.png

當我們的蘋果手機聯網的時候,會自動與蘋果的服務器建立長連接,長連接的好處有很多,比如系統升級、時間校準、數據傳輸和響應比較快以及數據可以保持最新狀態等功能.上面這兩張圖片簡單的講述了推送的流程:

1.首先我們需要將自己設備的UDID和應用的Bundle Identifier發送到蘋果的服務器,然后蘋果的服務器會返回給我們一個DeviceToken,這個在我看來就是創建推送證書和描述文件的過程.
2.我們將包含手機和應用標示的打包文件上傳到做推送的服務器上去,當我們從推送服務器的后臺發起推送消息的時候,推送服務器會將我們的DeviceToken和需要發送的消息Message發送到蘋果的APNS(Apple push Notification Service)服務器.
3.當蘋果的服務器收到DeviceToken和需要發送的消息Message時,會根據DeviceToken中的UDID查找設備,根據DeviceToken中的Bundle Identfier查找該應用,并將Message發送到該設備上.

下面是以QQ服務器為栗子說明的即時通訊的機制:

3.png

二.具體流程

我們創建一個名為TestDemo的工程,我是使用Xcode8.1來開發的,工程名為PushDemo,創建好的工程界面如下(Xcode8)

3.png

從Xcode8之后,Xcode提供了自動管理證書的功能,這個用起來很方便,我目前在工程中用到的最多的地方就是創建好一個Demo之后,如果想真機運行的話,那么只需要在Team選擇框里選擇我的開發賬戶,接下來下面會出現一個加載提示圈,等它加載完了就可以在真機上運行了,這個過程實際上是Xcode使用你當前的BundleId去該賬戶的開發這中心創建了對應的AppId和描述文件,但是我們既然是作為一個開發流程的記錄,就自己來創建這些東西,所以,我們取消選擇Automatically manage signing選項.此時界面如下:

4.png
  1. 首先我們先去官網創建AppID和描述文件.
    我們是要集成推送的,所以我們需要用到cer文件,這個東西實際上就是蘋果給開發者頒發的一個證書,我們需要將它導入到我們的AppId配置里,否則的話是無法集成推送的,還記得安裝應該的時候會提示"無法安裝為認證發布者的應用"之類的信息么,我猜測這個cer文件就是我們身份的標示,使我們開發的應用可以供人們正常安裝使用,關于證書有一篇很詳細的帖子,希望了解證書之類信息的看官可以去瞅瞅:http://m.blog.csdn.net/article/details?id=8617788
    創建cer文件的流程很簡單,打開"鑰匙串訪問"(雖然很好找,但是還是把圖貼出來吧,怕小朋友迷路)
    ![Uploading 6_078927.png . . .]
    5.png
6.png

打開鑰匙串之后點擊"從證書頒發機構請求證書"

7.png

郵箱和常用名隨便填寫,記住下面的選擇框選擇"存儲到磁盤"

8.png

點擊存儲

9.png

已經在桌面保存了

10.png

到此,我們已經創建好了cer文件,接著我們去開發者中心創建AppId和描述文件

  1. 創建AppId和描述文件

首先進入開發者中心,百度搜索Apple Developer,(哎 真的是詳細到家了啊,我都人不下去了)
上圖

11.png

輸入開發者賬戶,登錄進去

12.png

你將看到這個頁面

13.png

點擊看到:

14.png

輸入AppId文件名和BundleId

15.png

選中下面的PushNotifications

16.png

點擊Continue:

17.png

點擊register:

18.png

點擊Done回到AppId列表頁面

19.png

在AppId列表頁面可以看到我們的AppID了

20.png

但是,還沒有完成,因為我們是要做推送的,所以需要上傳我們的cer文件
,點擊我們的AppId,在展開的詳情里可以看到:

21.png

Push Notification的兩個指示燈還是黃色的狀態,我們要將它啟用,點擊Edit,在點開的頁面里滑動至底部,記得要選中Push Notification按鈕,接著點擊上方的開發證書下的創建證書按鈕:

22.png

點擊Continue

23.png

點擊 choose file:

24.png

將我們從開發機構請求的證書傳上去,之后點擊Register:

25.png

點擊Register之后的頁面,點擊download,將其下載到桌面上,download之后記得點擊done完成文件創建:

26.png

桌面上的文件:

27.png

現在我們就完成了給AppID創建開發者證書,然后我們要給它創建發布者證書,點擊Done之后回到AppIds列表,如果找不到的話,點擊右邊的App IDs

28.png

點開項目的AppId,此時界面如下,點擊最下面的CreateCertificate,開始給AppID創建發布者證書,給AppId創建發布者證書流程跟創建開發者證書是一樣的!給AppId創建發布者證書流程跟創建開發者證書是一樣的!給AppId創建發布者證書流程跟創建開發者證書是一樣的!重要的事情說三遍!!因為我不貼出來創建發布證書的圖了,所以各位根據創建開發證書的流程再走一遍就好,同樣也要將發布者證書下載到本地.:

29.png
30.png

當創建好之后在回到這個頁面時,應該顯示如下所示:

31.png

此時本地我們下載的文件如下:

32.png

然后將這兩個證書拖到鑰匙串里,步驟如下:
首先打開鑰匙串:

33.png
34.png

然后先點擊:系統-證書,然后將兩個文件拖進去,會提示你輸入開機密碼,輸入就好了(建議添加之前先對這個界面截屏,添加完之后可以對比剛剛添加了那些文件)

35.png

添加完之后是這個樣子,畫框的是我們的證書

36.png

然后選擇左邊的"登錄"選項,可以看到我們剛才創建的證書

37.png

選中第一個證書,然后右鍵(你懂得右鍵的意思),選擇導出...

38.png

選擇導出為P12文件,存儲在桌面上,獲取到P12文件.對這兩個證書進行同樣的操作.(記得標題有(Develop)的起名為Product文件,第二個證書導出的時候起名為Develop,名字可以自己定,只是為了區別)

39.png

然后會提示你輸入密碼,這里我設置的密碼是123456,自己設定好一定要記住,一會兒要用.

40.png

然后可以在桌面上看到我們導出的P12文件啦

41.png

現在我們就完成了所有的證書的創建,可以去環信上創建我們的應用啦.

3.創建真機調試文件以及導入到項目中

因為必須要進行真機測試,而且我們關閉了自動管理證書,就導致Xcode8不會自動幫我們生成證書,所以我們要自己創建真機調試證書并導入到項目中去,流程如下:

創建描述文件:

42.png

選擇開發模式,下一步:

43.png

選擇對應的AppID,選擇我們剛才創建的AppId:

44.png

選擇開發團隊,我一般都是全選的,下一步:

45.png

選擇真機調試的機器,全選,下一步:

46.png

下一步:

47.png

將創建好的描述文件下載下來,放到桌面上:

48.png

創建好的描述文件:

49.png

首先選擇debug模式下載的真機調試描述文件:

50.png

選擇桌面上剛剛下載的描述文件:

51.png

使用同樣的步驟,選擇Release模式下的真機調試文件,一模一樣的操作,不貼圖了.兩個文件都導入進去之后,插上真機,就可以進行真機調試了.

4.在環信創建我們的應用

首先百度搜索環信,打開他們的官網,先注冊賬戶,注冊過的可以跳過了,上圖:
注冊的時候選擇"注冊即時通訊云"

52.png

注冊的時候需要填寫各種信息,按照格式填寫就好了,填寫完之后登陸,點擊創建應用

53.png

填寫應用信息

54.png

填寫完如下圖咯

55.png

然后需要上傳我們的P12文件,圖片很清晰- -,不多說,第一次我選擇上傳的是生產證書:

56.png

第二次上傳開發證書:

57.png

至此,我們的證書開發也都上傳完了,路漫漫其修遠兮,開始集成環信到代碼里吧
5.集成環信到項目中
首先在這里下載最新的SDK(截至到寫本文時最新的SDK為)
http://www.easemob.com/download/im 環信推送SDK下載鏈接
點擊iOS的最新SDK下載,這里下載的是V3.x的SDK

58.png

下載到桌面是這個樣子

59.png

我們只需要將畫圈的兩個文件夾導進去工程里就好了,其他的用不上

60.png

導進去之后文件列表是這樣,編譯會出錯別急,慢慢改.

61.png

向項目里添加需要的庫

62.png

上面的圖片是截取的環信官方文檔,我添加完是這個樣子的:

63.png

方便復制庫名的文字:
CoreMedia.framework
AudioToolbox.framework
AVFoundation.framework
MobileCoreServices.framework
ImageIO.framework
libc++.dylib
libz.dylib
libstdc++.6.0.9.dylib
libsqlite3.dylib
(如果使用的是 xcode7,后綴為 tbd。)
這一步很重要,因為SDK 不支持 bitcode,所以要將 Build Settings → Linking → Enable Bitcode 中設置 NO。

64.png

command+B編譯工程,大量爆紅.別著急,修改我們的PCH文件就好了
在PCH文件添加

#ifdef __OBJC__
    #import <UIKit/UIKit.h>
#endif

將我們所有定義和添加的頭文件和宏定義,都放在#ifdef OBJC和#endif中間
就可以解決這個問題.

然后在項目里打開推送:

65.png

6.測試是否集成成功

首先,我們去環信的后臺給我們的應用添加一個用戶

66.png

用戶名我設置成了:13088888888 密碼設置成了:222222

67.png

接著我們要去appledate.m文件里添加東西了,很重要一步,廢話不多說,直接貼出來需要配置的代碼,直接拿去用0.0,需要添加的東西我在注釋里注釋的很明白...
記得要導進去頭文件

import "EMSDK.h"
@interface AppDelegate ()<EMChatManagerDelegate>

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //AppKey:注冊的AppKey,點擊"應用概述"可以看到AppKey,粘貼過來就可以。
    //apnsCertName:推送證書名,填寫你的開發證書或者發布證書名,就是上傳到環信后臺的兩個中的一個,什么環境下測試使用什么環境的證書。
    EMOptions *options = [EMOptions optionsWithAppkey:@"1192161108178165#testpushdemo"];
    options.apnsCertName = @"Develop";
    [[EMClient sharedClient] initializeSDKWithOptions:options];

    //登錄環信 這里使用的是我剛才在環信后臺創建的賬戶名和密碼,使用這個賬戶登錄,到時候如果在后臺給客戶端發消息的話,就可以找到該用戶
    [[EMClient sharedClient] loginWithUsername:@"13051698888"
                                      password:@"222222"
                                    completion:^(NSString *aUsername, EMError *aError) {
                                        if (!aError) {
                                            NSLog(@"環信登陸成功");
                                            EMPushOptions *emoptions = [[EMClient sharedClient] pushOptions];
                                            //設置有消息過來時的顯示方式:1.顯示收到一條消息 2.顯示具體消息內容.
                                            //自己可以測試下
                                            emoptions.displayStyle = EMPushDisplayStyleSimpleBanner;
                                            [[EMClient sharedClient] updatePushOptionsToServer];
                                        } else {
                                            NSLog(@"環信登陸失敗");
                                        }
                                    }];


    /**
     注冊APNS離線推送  iOS8 注冊APNS
     */
    if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
        [application registerForRemoteNotifications];
        UIUserNotificationType notificationTypes = UIUserNotificationTypeBadge |
        UIUserNotificationTypeSound |
        UIUserNotificationTypeAlert;
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:notificationTypes categories:nil];
        [application registerUserNotificationSettings:settings];
    }
    else{
        UIRemoteNotificationType notificationTypes = UIRemoteNotificationTypeBadge |
        UIRemoteNotificationTypeSound |
        UIRemoteNotificationTypeAlert;
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:notificationTypes];
    }

    //添加監聽在線推送消息
   [[EMClient sharedClient].chatManager addDelegate:self delegateQueue:nil];    
    return YES;
}

//監聽環信在線推送消息
- (void)messagesDidReceive:(NSArray *)aMessages{

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"收到環信通知" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
        [alertView show];

        //aMessages是一個對象,包含了發過來的所有信息,怎么提取想要的信息我會在后面貼出來.
}

// 將得到的deviceToken傳給SDK
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    [[EMClient sharedClient] bindDeviceToken:deviceToken];
}

// 注冊deviceToken失敗
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"error -- %@",error);
}

// APP進入后臺
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[EMClient sharedClient] applicationDidEnterBackground:application];
}

// APP將要從后臺返回
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[EMClient sharedClient] applicationWillEnterForeground:application];
}

上面的幾個方法在appdelegate里是必須重寫的,不然會直接導致推送不成功.其中.需要重點說明的是:

只有在應用完全退出被殺掉的狀態下,才可以收到環信推送的通知;
如果要發送在線的通知,需要在messagesDidReceive方法里獲取到環信推送的消息之后給用戶發起一個本地通知,這個大家可以自己研究下.
通過設置emoptions.displayStyle = EMPushDisplayStyleSimpleBanner;(上面代碼有)可以設置有通知過來的時候的顯示方式,顯示一個提示或者顯示完整的消息.
上傳證書下面填寫的應用包名,指的是你的BundleID !!!!我在這里踩了坑,切記!!.
測試推送:

在應用完全退出的情況下(使用在環信注冊的賬戶登錄一次,確認登錄成功之后再完全退出),選中我們的用戶,點擊發送消息:

68.png

點擊發送:

69.png

測試結果:

70.png

2.程序在線的時候測試推送,還是發送"你好啊",然后我們在messagesDidReceive攔截環信的EMMessage對象,針對EMMessage對象的解析方式如下,完整的抽取環信推送消息的方法:

- (void)messagesDidReceive:(NSArray *)aMessages{

        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"提示" message:@"收到環信通知" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil];
        [alertView show];

        for (EMMessage *message in aMessages) {
            EMMessageBody *msgBody = message.body;
            switch (msgBody.type) {
                case EMMessageBodyTypeText:
                {
                    // 收到的文字消息
                    EMTextMessageBody *textBody = (EMTextMessageBody *)msgBody;
                    NSString *txt = textBody.text;
                    NSLog(@"收到的文字是 txt -- %@",txt);
                }
                    break;
                case EMMessageBodyTypeImage:
                {
                    // 得到一個圖片消息body
                    EMImageMessageBody *body = ((EMImageMessageBody *)msgBody);
                    NSLog(@"大圖remote路徑 -- %@"   ,body.remotePath);
                    NSLog(@"大圖local路徑 -- %@"    ,body.localPath); // // 需要使用sdk提供的下載方法后才會存在
                    NSLog(@"大圖的secret -- %@"    ,body.secretKey);
                    NSLog(@"大圖的W -- %f ,大圖的H -- %f",body.size.width,body.size.height);
                    NSLog(@"大圖的下載狀態 -- %u",body.downloadStatus);


                    // 縮略圖sdk會自動下載
                    NSLog(@"小圖remote路徑 -- %@"   ,body.thumbnailRemotePath);
                    NSLog(@"小圖local路徑 -- %@"    ,body.thumbnailLocalPath);
                    NSLog(@"小圖的secret -- %@"    ,body.thumbnailSecretKey);
                    NSLog(@"小圖的W -- %f ,大圖的H -- %f",body.thumbnailSize.width,body.thumbnailSize.height);
                    NSLog(@"小圖的下載狀態 -- %u",body.thumbnailDownloadStatus);
                }
                    break;
                case EMMessageBodyTypeLocation:
                {
                    EMLocationMessageBody *body = (EMLocationMessageBody *)msgBody;
                    NSLog(@"緯度-- %f",body.latitude);
                    NSLog(@"經度-- %f",body.longitude);
                    NSLog(@"地址-- %@",body.address);
                }
                    break;
                case EMMessageBodyTypeVoice:
                {
                    // 音頻sdk會自動下載
                    EMVoiceMessageBody *body = (EMVoiceMessageBody *)msgBody;
                    NSLog(@"音頻remote路徑 -- %@"      ,body.remotePath);
                    NSLog(@"音頻local路徑 -- %@"       ,body.localPath); // 需要使用sdk提供的下載方法后才會存在(音頻會自動調用)
                    NSLog(@"音頻的secret -- %@"        ,body.secretKey);
                    NSLog(@"音頻文件大小 -- %lld"       ,body.fileLength);
                    NSLog(@"音頻文件的下載狀態 -- %u"   ,body.downloadStatus);
                    NSLog(@"音頻的時間長度 -- %u"      ,body.duration);
                }
                    break;
                case EMMessageBodyTypeVideo:
                {
                    EMVideoMessageBody *body = (EMVideoMessageBody *)msgBody;

                    NSLog(@"視頻remote路徑 -- %@"      ,body.remotePath);
                    NSLog(@"視頻local路徑 -- %@"       ,body.localPath); // 需要使用sdk提供的下載方法后才會存在
                    NSLog(@"視頻的secret -- %@"        ,body.secretKey);
                    NSLog(@"視頻文件大小 -- %lld"       ,body.fileLength);
                    NSLog(@"視頻文件的下載狀態 -- %u"   ,body.downloadStatus);
                    NSLog(@"視頻的時間長度 -- %u"      ,body.duration);
                    NSLog(@"視頻的W -- %f ,視頻的H -- %f", body.thumbnailSize.width, body.thumbnailSize.height);

                    // 縮略圖sdk會自動下載
                    NSLog(@"縮略圖的remote路徑 -- %@"     ,body.thumbnailRemotePath);
                    NSLog(@"縮略圖的local路徑 -- %@"      ,body.thumbnailLocalPath);
                    NSLog(@"縮略圖的secret -- %@"        ,body.thumbnailSecretKey);
                    NSLog(@"縮略圖的下載狀態 -- %u"      ,body.thumbnailDownloadStatus);
                }
                    break;
                case EMMessageBodyTypeFile:
                {
                    EMFileMessageBody *body = (EMFileMessageBody *)msgBody;
                    NSLog(@"文件remote路徑 -- %@"      ,body.remotePath);
                    NSLog(@"文件local路徑 -- %@"       ,body.localPath); // 需要使用sdk提供的下載方法后才會存在
                    NSLog(@"文件的secret -- %@"        ,body.secretKey);
                    NSLog(@"文件文件大小 -- %lld"       ,body.fileLength);
                    NSLog(@"文件文件的下載狀態 -- %u"   ,body.downloadStatus);
                }
                    break;

                default:
                    break;
            }
        }
}

發送成功之后打印結果如下:

2016-12-01 16:03:26.060088 PushDemo[1392:450230] 收到的文字是 txt -- 你好啊

三.結語

至此,我們就成功集成了環信推送到我們的項目中.另外提供一些在做推送的時候經常會用到的小方法

設置應用圖標右上角數字角標.

UIApplication *application = [UIApplication sharedApplication]; [application setApplicationIconBadgeNumber:3];

如果推送證書那里沒看特別明白的話,提供一個創建推送證書的鏈接:http://www.lxweimin.com/p/79061dda87e3

設置推送過來時候的apns昵稱:

[[EMClient sharedClient] setApnsNickname:@"推送昵稱"];

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,572評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,071評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,409評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,569評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,360評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,895評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,979評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,123評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,643評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,559評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,742評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,250評論 5 356
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,981評論 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,363評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,622評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,354評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,707評論 2 370

推薦閱讀更多精彩內容