1. 程式人生 > >細說 iOS 消息推送

細說 iOS 消息推送

not 個數 text payload 自己 是否 coffee reserve use

APNS的推送機制

與Android上我們自己實現的推送服務不一樣,Apple對設備的控制很嚴格。消息推送的流程必需要經過APNs:
技術分享

這裏 Provider 是指某個應用的Developer,當然假設開發人員使用AVOS Cloud的服務,把發送消息的請求托付給我們,那麽這裏的Provider就是AVOS Cloud的推送服務程序了。

上圖能夠分為三步:
第一步:AVOS Cloud推送服務程序把要發送的消息、目的設備的唯一標識打包,發給APNs。
第二步:APNs在自身的已註冊Push服務的應用列表中,查找有對應標識的設備。並把消息發送到設備。
第三步:iOS系統把發來的消息傳遞給對應的應用程序,而且依照設定彈出Push通知

為了實現消息推送,有兩點很重要:
1,App的推送證書
要能夠完整實現一條消息推送,須要我們在App ID中打開Push Notifications,須要我們準備好Provisioning Profile和SSL證書。而且一定要註意Development和Distribution環境是須要分開的。最後。把SSL證書導入到AVOS Cloud平臺。就能夠嘗試遠程消息推送了。詳細的操作流程能夠參考我們的使用指南:iOS推送證書設置指南。


2,設備標識DeviceToken
知道了誰要推送,或者說要推送給哪個App之後,APNs還須要知道推到哪臺設備上,這就是設備標識的作用。獲取設備標識的流程例如以下:

技術分享

第一步:App打開推送開關。用戶要確認TA希望獲得該App的推送消息
第二步:App獲得一個DeviceToken
第三步:App將DeviceToken保存起來,這裏就是通過[AVInstallation saveInBackground]將DeviceToken保存到AVOS Cloud
第四步:當某些特定事件發生。開發人員托付AVOS Cloud來發送推送消息。這時候AVOS Cloud的推送server就會給APNs發送一則推送消息,APNs最後消息送到用戶設備

推送相關的幾個概念

消息類型

一條消息推送過來,能夠有例如以下幾種表現形式:

  • 顯示一個alert或者banner。展現詳細內容
  • 在應用icon上提示一個新到消息數
  • 播放一段聲音
    開發人員能夠在每次推送的時候設置。在推送達到用戶設備時開發人員也能夠選擇不同的提示方式。

    本地消息通知

    iOS上有兩種消息通知,一種是本地消息(Local Notification),一種是遠程消息(Push Notification,也叫Remote Notification),設計這兩種通知的目的都是為了提醒用戶,如今有些什麽新奇的事情發生了。吸引用戶又一次打開應用。


    本地消息什麽時候實用呢?譬如你正在做一個To-do的工具類應用。對於用戶增加的每個事項,都會有一個完畢的時間點,用戶能夠要求這個To-do應用在事項過期之前的某一個時間點提醒一下TA。

    為了達到這一目的。App就能夠調度一個本地通知,在時間點到了之後發出一個Alert消息或者其它提示。
    我們在處理推送消息的時候。也能夠綜合運用這兩種方式。

    代碼裏面怎樣實現推送

    首先,我們要獲取DeviceToken。

    App須要每次啟動的時候都去註冊遠程通知——通過調用UIApplication的registerForRemoteNotificationTypes:方法,傳遞給它你希望支持的消息類型參數就可以,比如:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // do some initiale working
        ...
        
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
        return YES;
    }
    

    假設註冊成功,APNs會返回給你設備的token。iOS系統會把它傳遞給app delegate代理——application:didRegisterForRemoteNotificationsWithDeviceToken:方法,你應該在這種方法裏面把token保存到AVOS Cloud後臺。比如:

    - (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
        NSLog(@"Receive DeviceToken: %@", deviceToken);
        AVInstallation *currentInstallation = [AVInstallation currentInstallation];
        [currentInstallation setDeviceTokenFromData:deviceToken];
        [currentInstallation saveInBackground];
    }
    

    假設註冊失敗,application:didFailToRegisterForRemoteNotificationsWithError:方法會被調用,通過NSError參數你能夠看到詳細的出錯信息,比如:

    - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
        NSLog(@"註冊失敗,無法獲取設備ID, 詳細錯誤: %@", error);
    }
    

    請註意,註冊流程須要在app每次啟動時調用。這並不不會帶來額外的負擔。由於iOS操作系統在第一次獲得了有效的device token之後,會本地緩存起來,以後app再調用registerForRemoteNotificationTypes:的時候會立馬返回,並不會再進行網絡請求。另外。app層面不應該對device token進行緩存,由於device token也有可能變化——假設用戶重裝了操作系統。那麽APNs再次給出的device token就會和之前的不一樣,又或者是,用戶restore了原來的backup到新的設備上,那麽原來的device token也會失效。

    其次,我們要處理收到消息之後的回調

    我們能夠設想一下消息通知的幾種使用場景:
    1,在app沒有被啟動的時候,接收到了消息通知。這時候操作系統會依照默認的方式來展現一個alert消息。在app icon上標記一個數字,甚至播放一段聲音。
    2,用戶看到消息之後。點擊了一下actionbutton或者點擊了應用圖標
    假設actionbutton被點擊了,系統會通過調用application:didFinishLaunchingWithOptions:這個代理方法來啟動應用。而且會把notification的payload數據傳遞進去。
    假設應用圖標被點擊了。系統也一樣會調用application:didFinishLaunchingWithOptions:這個代理方法來啟動應用,唯一不同的是這時候啟動參數裏面不會有不論什麽notification的信息。
    演示樣例代碼例如以下:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // do initializing works
        ...
        
        if (launchOptions) {
            // do something else
            ...
        
            [AVAnalytics trackAppOpenedWithLaunchOptions:launchOptions];
        }
        
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
    
        return YES;
    }
    

    3,假設遠程消息發送過來的時候。app正在執行。這時候會發生什麽呢?
    app代理的application:didReceiveRemoteNotification:方法會被調用,同一時候遠程消息中的payload數據會作為參數傳遞進去。
    演示樣例代碼例如以下:

    - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
        if (application.applicationState == UIApplicationStateActive) {
            // 轉換成一個本地通知,顯示到通知欄,你也能夠直接顯示出一個alertView。僅僅是那樣稍顯aggressive:)
            UILocalNotification *localNotification = [[UILocalNotification alloc] init];
            localNotification.userInfo = userInfo;
            localNotification.soundName = UILocalNotificationDefaultSoundName;
            localNotification.alertBody = [[userInfo objectForKey:@"aps"] objectForKey:@"alert"];
            localNotification.fireDate = [NSDate date];
            [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
        } else {
            [AVAnalytics trackAppOpenedWithRemoteNotificationPayload:userInfo];
        }
    }
    

    常見問題FAQ

    我能推送長消息嗎

    不能,APNs限制了每一個notification的payload最大長度是256字節,超長的消息是不能發送的。

    推送怎麽加聲音提醒

    消息推送是能夠指定聲音的。譬如你能夠對正面的反饋使用歡快的聲音,對負面的反饋使用低沈一點的聲音,都能夠達到別出心裁讓人眼前一亮的目的。
    你須要先放一些aiff、wav或者caf音頻文件到app的資源文件裏。然後在推送的時候指定不同的音頻文件名稱就能夠了。
    技術分享

    推送的Badge是怎麽回事

    推送並不一定會導致應用圖標上紅色數字添加,是否顯示這一數字,顯示成多少。都取決於開發人員自己。
    在發送推送消息的時候,我們能夠選擇是否遞增這一數字;假設不選擇這一項。那麽消息推送並不會導致應用圖標上紅色數字的出現。
    技術分享
    好。如今問題來了。這個數字假設搞出來了,怎麽讓它消失掉呢?
    事實上我們僅僅須要在不論什麽時候設置 UIApplication.applicationIconBadgeNumber 屬性為0,就能夠讓這個數字消失掉。


    一般我們會選擇在應用啟動的時候(application:didFinishLaunchingWithOptions:方法中)。或者幹脆一點,在應用每次被切換到前臺的時候(applicationWillEnterForeground:方法中),調用這一行代碼。就可以立馬清除掉Badge數字了。

    AVOS Cloud平臺發出去的通知格式到底是什麽樣子的

    對於每一條推送消息。都包括一個payload,一般是組成了一個JSON的Dictionary,這當中不可缺少的是aps屬性,它相應的value也是一個Dictionary,包括以下一些內容:

  • alert消息(文本或Dictionary)
  • 應用圖標上的紅色數字
  • 播放的聲音文件名稱
    在由推送激活的app打開事件中,application:didFinishLaunchingWithOptions:的options參數就是這個大的Dictionary對象。

    {
        aps =     {
            alert = "hello, everyone";
            badge = 2;
            sound = default;
        };
    }
    

    這裏要註意的時alert部分。它的值能夠是一個String(文本消息),也能夠是一個JSON的Dictionary。當它是文本消息的時候,系統就會把這些文字顯示到一個alertview中;假設它也是由一個JSON Dictionary組成的話。其格式例如以下:

  • body
  • action-loc-key
  • loc-key
  • loc-args
  • launch-image
    body部分就是alertView中將要展現出來的文本消息,loc-屬性主要是用來實現本地化消息,launch-image僅僅是app主bundle裏的一個圖片文件的名稱。一般來說我們不指定這一屬性。

    怎樣顯示本地化的消息

    有兩種辦法能夠實現推送消息的本地化:
    1,在推送的payload中使用loc-key和loc-args來指定進行本地化,這樣Provider方僅僅須要依照統一的格式來發送就可以。消息的解析和組裝則由client來完畢。
    2。假設推送的payload裏面不包括loc-key/loc-args信息。那麽Provider方就須要自己做本地化處理,然後給不同的device發送不同的消息。為了做到這一點,還須要app在上傳device token的時候也把用戶的語言設置信息傳回來。
    眼下,由於AVOS Cloud主要就是瞄準中國大陸市場和海外中文用戶。所以我們在推送上還不提供多語言支持。

    應用該怎麽響應推送消息

    上面說的處理流程。僅僅能簡單展示一下遠程消息,激活用戶讓他們又一次回到app中來。可是有時候。我們希望帶給用戶更好的使用體驗。譬如假設我們告訴用戶:張三剛剛評論了你的照片。這時候用戶假設點擊actionbutton進入app。我們是展示詳細的評論頁面為好,還是展示通常的啟動頁面然後讓用戶自己去找張三的評論好?我想負責任的開發人員都會選擇前者:)

    要做到靈活響應不同類型的通知消息,我們須要在通知的payload中添加很多其它信息,而不能只唯獨alert出來的文字信息。

    對於AVOS Cloud消息推送平臺來講。就須要開發人員使用更高級功能的JSON格式。譬如我們發送這種json字符串
    {"action":{"type":4},"alert":"hello, everyone”} 終於在app內會收到這種UserInfo Dictionary:

    {
        action =     {
            type = 4;
        };
        aps =     {
            alert = "hello, everyone";
            badge = 4;
        };
    }
    

    “hello, everyone”會顯示到alertView中,可是整個Dictionary會通過launchOptions傳遞給application: didFinishLaunchingWithOptions: 方法,這樣我們在程序裏面就能夠對不同的消息實現不同的跳轉了。


  • http://blog.csdn.net/kylinbl/article/details/6729369

  • 細說 iOS 消息推送