<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jack Jiang

    我的最新工程MobileIMSDK:http://git.oschina.net/jackjiang/MobileIMSDK
    posts - 494, comments - 13, trackbacks - 0, articles - 1

    本文作者:陳裕發(fā), 騰訊系統(tǒng)測試工程師,由騰訊WeTest整理發(fā)表。

    1、引言

    開發(fā)iOS系統(tǒng)中的Push推送,通常有以下3種情況:

    1)在線Push:比如QQ、微信等IM界面處于前臺時,聊天消息和指令都會通過IM自建的網(wǎng)絡(luò)長連接通道推送過來,這種Push在本文中暫且稱為“在線Push”;

    2)本地Push:這種就是最常見的iOS系統(tǒng)通知(作用相當于傳統(tǒng)PC端的提示窗口,在iOS10以后全部整合到UserNotifications.framework框架了),不涉及任何網(wǎng)絡(luò)數(shù)據(jù),僅僅是讓APP擁有一個統(tǒng)一系統(tǒng)通知方式而已,比如:鬧鐘的定時提醒等;

    3)離線/遠程Push:這就是iOS程序員最熟悉的APNs這一套東西了,它使得APP處于后臺或者被kill的情況下仍能收到網(wǎng)絡(luò)通知,最常見的應(yīng)場景就是IM聊天工具了。

    本文將對iOS Push的在線push、本地push及離線(遠程)push進行了詳細梳理,介紹相關(guān)邏輯、測試時要注意的要點以及相關(guān)工具的使用。小小的Push背后蘊藏著大大的邏輯,我們一起來學(xué)習(xí)吧!

    消息推送/im開發(fā)學(xué)習(xí)交流:

    - 即時通訊開發(fā)交流3群:185926912[推薦]

    - 移動端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動端IM

    (本文同步發(fā)布于:http://www.52im.net/thread-1762-1-1.html

    2、相關(guān)文章

    移動端實時消息推送技術(shù)淺析

    iOS的推送服務(wù)APNs詳解:設(shè)計思路、技術(shù)原理及缺陷等

    信鴿團隊原創(chuàng):一起走過 iOS10 上消息推送(APNS)的坑

    掃盲貼:淺談iOS和Android后臺實時消息推送的原理和區(qū)別

    3、iOS的Push種類

    3.1 在線push

    在線push:當用戶在線(APP在前臺)時,收到的狀態(tài)欄的消息提醒,稱為在線push。這個功能與蘋果系統(tǒng)無關(guān),是我們自己的APP開發(fā)的一種功能,該push與設(shè)置中是否打開“通知”無關(guān)。

    這里以iOS Qzone為例,當APP在前臺時,自己發(fā)的說說被點贊了,收到的在線push如下:

    3.2 離線/遠程push

    離線push:當APP在離線(kill掉進程、切到后臺、鎖屏)時,收到的消息提醒,稱為離線push。離線push是需要經(jīng)過蘋果的APNs服務(wù)器才可以推送到某臺設(shè)備的某個APP上的,這是和本地push的本質(zhì)區(qū)別。push與設(shè)置中是否打開“通知”有關(guān)。

    這里最簡單的以大家常用的手機QQ為例,當APP在后臺、鎖屏或者被kiil了進程時,收到了消息:

    一種特殊的遠程push:靜默push

    嚴格來說,靜默push屬于遠程push的一種特殊情況,靜默push用的場景不較少,這里只做簡要介紹。

    首先我們看看離線(遠程)push與靜默push的區(qū)別:

    【普通離線(遠程)push】:收到推送后(有文字有聲音),點開通知,進入APP后,才執(zhí)行-- (void)application:(UIApplication didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void result))handler *)application *)userInfo (^)(UIBackgroundFetchResult

    【靜默push】:收到推送(沒有文字沒有聲音),不用點開通知,不用打開APP,就能執(zhí)行(void)application:(UIApplication )application)userInfo didReceiveRemoteNotification:(NSDictionary fetchCompletionHandler:(void (^)(UIBackgroundFetchResultresult))handler,用戶完全感覺不到。

    所以靜默push又被我們稱做 Background Remote Notification(后臺遠程推送)。靜默推送是在iOS7之后推出的一種推送方式。它與其他推送的區(qū)別在于允許應(yīng)用收到通知后在后臺(background)狀態(tài)下運行一段代碼,可用于從服務(wù)器獲取內(nèi)容更新。

    3.3 本地push

    本地push:本地推送和遠程推送的功能是一樣的,都是要提醒用戶去做某些事情。但是和遠程推送不同的就是本地推送是不需要設(shè)備聯(lián)網(wǎng)的,而遠程推送是必需要設(shè)備聯(lián)網(wǎng)的,因為只有聯(lián)網(wǎng)狀態(tài)下,才能和蘋果的APNs服務(wù)器建立長連接,從而推送消息。本地推送是由App自己設(shè)定的,并且發(fā)送給安裝此App的這臺設(shè)備,屬于一對一的對應(yīng)關(guān)系。比較典型的應(yīng)用是鬧鐘類似的場景。該push與設(shè)置中是否打開“通知”有關(guān)。

    最容易看到本地push的場景,可以直接在手機設(shè)置一個計時器,計時器時間到了就會彈出本地push:

    由于本地push原理和作用相對于在線push和離線push都更為簡單明了,下文主要介紹在線push和離線push。

    4、本地push實現(xiàn)

    4.1 iOS10以前本地push彈出方式

    試驗過iOS10以前的本地push方法在iOS10+的系統(tǒng)也能使用,不過可能有些參數(shù)不生效。

    1)立即展示( iOS10以前)

    本地push稍微簡單,有兩種方式可以調(diào)用,一種是presentLocalNotificationNow方法,立即展示本地push:

    2)延遲展示( iOS10以前)

    另一種是用scheduleLocalNotification方法按計劃來彈本地推送:

    如果使用這種方法,需要對推送的時間進行設(shè)置,舉個例子,設(shè)為5秒后:

    4.2 設(shè)置本地push內(nèi)容( iOS10以前)

    其中alertBody是消息內(nèi)容鎖屏與不鎖屏?xí)r效果如下:

    applicationIconBadgeNumber是消息數(shù)量,我們可以看到這里設(shè)置為66:

    4.3 處理本地push ( iOS10以前)

    1)App沒有啟動情況下處理本地push

    這種情況下,當點擊通知時,會啟動App,而在App中,開發(fā)人員可以通過實現(xiàn)AppDelegate中的方法:- (BOOL)application:UIApplication)application didFinishLaunchingWithOptions:NSDictionary *)launchOptions,然后從lauchOptions中獲取App啟動的原因,若是因為本地通知,則可以App啟動時對App做對應(yīng)的操作,比方說跳轉(zhuǎn)到某個畫面等等。

    2)App運行在后臺及前臺

    上面的2種情況的處理基本一致, 不同點只有當運行再后臺的時候,會有彈窗提示用戶另外一個App有通知,對于本地通知單的處理都是通過AppDelegate的方法:- (void)application

    UIApplication )application didReceiveLocalNotification:UILocalNotification *)notification來處理的。

    4.4 iOS10以后本地push彈出方式

    iOS10以后,本地通知可以由使用 UNUserNotificationCenter來管理。

    創(chuàng)建方法:

    接下來需要需創(chuàng)建一個包含待通知內(nèi)容的 UNMutableNotificationContent 對象:

    在iOS上可以通過以下幾種觸發(fā)器來觸發(fā)本地push:

    1)UNCalendarNotificationTrigger 傳送本地通知的日期和時間;

    2)UNTimeIntervalNotificationTrigger 傳遞本地通知之前必須過期的時間;

    3)UNLocationNotificationTrigger 用戶必須達到的地理位置才能提供本地通知;

    4)UNPushNotificationTrigger 表示通知是從Apple推送通知服務(wù)發(fā)送的對象。

    假如以時間間隔(TimeInterval)來觸發(fā),則設(shè)置觸發(fā)器代碼為:

    推送本地push的代碼為:

    5、在線、離線(遠程)push流程

    5.1 在線push流程

    在線push相對簡單,因為是內(nèi)部實現(xiàn),具體流程如上面所示。

    1)判斷app是否在線:

    此處可以根據(jù)APP自身的后臺策略如上一次與后臺交互的時間等方法來判斷APP是否在線或者離線。認為在線,會發(fā)送在線push,否則,發(fā)送離線push。

    2)在線push有以下幾個特點:

    不需要經(jīng)過蘋果APNs;

    需要自己實現(xiàn)長鏈接;

    代碼在app內(nèi)部實現(xiàn)。

    5.2 離線(遠程)push流程

    主要流程為:

    1)服務(wù)器端將消息先發(fā)送到蘋果的APNs;

    2)由蘋果的APNs將消息推送到客戶的設(shè)備端;

    3)由iOS系統(tǒng)將接收到的消息傳遞給相應(yīng)的App。

    簡而言之離線push是蘋果系統(tǒng)的行為,與app狀態(tài)無關(guān),能夠直接推送到指定手機的指定app。

    在進一步了解離線push前,我們有必要先了解幾個名詞。

    【離線push名詞解釋】:

    (1)名詞解釋之APNs

    APNs:Apple Push Notification service(蘋果推送通知服務(wù))。

    APNs主要用于以下場景:當用戶主動殺掉 APP,或者 APP 進入后臺超過約定時長時,APP會被kill,這樣保障了前臺 APP 的流暢性,也延長了手機的使用時長,獲得了較好的用戶體驗,但是這也意味著,服務(wù)器無法主動和用戶交互(如推送實時消息等),所以蘋果推出了 APNs,允許設(shè)備和服務(wù)器分別與蘋果的推送通知服務(wù)器保持長連接狀態(tài)。

    關(guān)于APNs的更新有以下幾點:

    iOS 8以后,APNs推送的字節(jié)是2k,iOS8以前是256字節(jié);

    iOS 9以后APNs支持HTTP/2協(xié)議棧,優(yōu)化長連接,具有標準的HTTP返回和管道復(fù)用技術(shù);

    iOS 10以后,推送的字節(jié)是4k,APNs可根據(jù)推送消息的唯一標示符查詢某條消息是否被用戶閱讀,可更新某一推送消息,而不用發(fā)重讀的多條消息。

    關(guān)于APNs更全面的介紹可以看官方文檔:點此進入

    (2)名詞解釋之payload

    什么是payload?對于每一條發(fā)送給APNs的推送消息,都包含一個payload,通常是組成了一個JSON的Dictionary,這其中必不可少的是aps屬性,它對應(yīng)的value也是一個Dictionary,包含一些但不限于以下內(nèi)容:標題、副標題、內(nèi)容、附件、category等,如

    (3)名詞解釋之device token

    什么是device token?我們看一下官方的簡介:

    device token: APNs uses device tokens to identify each unique app and device combination. It also uses them to authenticate the routing of remote notifications sent to a device.(device token是APNs用于區(qū)分識別每個iOS設(shè)備和設(shè)備上不同app的一個標識符,還可以用于APNs通過它將推送消息路由到指定設(shè)備上)

    即:device token里包含了device id和bundle id的信息,但是device id和bundle id不會確定唯一的device token。

    但是,這里有個坑,查資料得知,iOS8及之前的iOS系統(tǒng),對于同一部手機,如果卸載后重裝APP的話,device token是不會變的,在token變了以后,老的token,就被認為是無效了,蘋果不會對這部分無效的token推送。但是,對iOS9及以后的iOS系統(tǒng),對于同一部手機,卸載后重裝APP的device token是會發(fā)生變化的,而且老的token不會無效,還可以正常推送,這應(yīng)該是蘋果的一個bug,但是蘋果也沒有修復(fù)這個問題,所以這個需要開發(fā)者自己來解決,否則容易出現(xiàn)一個app收到多個push的問題。

    官方的說法是:

    To protect user privacy, do not use device tokens to identify user devices. Device tokens change when the user updates the operating system and when a device’s data and settings are erased. As a result, apps should always request the current device token at launch time.(即此舉為了保護用戶隱私,device token會在更新系統(tǒng)、擦除設(shè)置重置后變化,在一定時間后會過期)

    【離線push詳細流程】

    知道了以上概念后我們重新來看一下離線(遠程)push的詳細流程:

    1) 首先是應(yīng)用程序注冊消息推送;

    2) iOS跟APNS Server要deviceToken。應(yīng)用程序接受deviceToken;

    3) 應(yīng)用程序?qū)eviceToken發(fā)送給PUSH服務(wù)端程序;

    4) 服務(wù)端程序向APNS服務(wù)發(fā)送消息;

    5) APNS服務(wù)將消息發(fā)送給iPhone應(yīng)用程序。

    值得注意的是,當由于用戶反復(fù)卸載重裝程序(雖然概率很小)等原因?qū)е露鄠€device Token指向同一臺設(shè)備的同一個app,又把多個device Token發(fā)給APNs時,用戶就會收到多條push。蘋果APNs是不會對多個device Token是否指向同一臺設(shè)備的同一個app做校驗的,所以需要后臺來做去重等處理保證用戶不會收到多條push。

    5.3 對離線(遠程)push的響應(yīng)

    1)iOS 7以上對離線(遠程)push時的響應(yīng)

    iOS 7以上關(guān)于接受離線push有兩個函數(shù):

    那么這兩個函數(shù)有什么區(qū)別呢?其實這兩個方法都是用來處理離線push的。

    差別就是,如果app在前臺是收到離線(遠程)push,那么就會調(diào)用:

    相對的,如果在后臺或者殺進程情況下,點擊收到的離線push,那么就會調(diào)用,如果沒有實現(xiàn):

    則會調(diào)用:

    若實現(xiàn)了前者,就只調(diào)用前者。

    2)iOS 10以上對離線(遠程)push的響應(yīng)

    iOS10對push的處理主要增加了兩個方法:

    其中前者是對APP在前臺時收到push時的處理,后者是點擊push進入APP執(zhí)行的函數(shù)。

    用得比較多的是后者,我們可以舉個例子,點擊push進入APP后如何獲取push的消息、角標、標題等內(nèi)容:

    6、iOS 10關(guān)于push的一些新特性

    iOS10新增的UserNotifications框架,主要有了這樣幾方面的更新:

    1)用UserNotifications框架替換了原先與通知相關(guān)的接口,通知文字可分為title、subtitle和body三部分,通知可攜帶附件;

    2)系統(tǒng)在展示通知之前,可以喚起app附帶的service extension,并且允許它改動通知的內(nèi)容;

    3)用戶在對通知右滑查看、下拉或者3d touch的時候,通知會展開,展開后頁面的布局可以由app附帶的content extension來決定。

    6.1 push的多樣性

    iOS10以前的push只有文字,甚至沒有標題。iOS10以后的push更加多樣化,可以有主標題,副標題,甚至還有附件。

    這里以我司的騰訊新聞為例(有標題,內(nèi)容,和附件):

    3D touch點入詳情以后:

    這里我們驚奇的發(fā)現(xiàn),除了可以攜帶圖片這樣的附件、push還能展開詳情以外,進入詳情以后,下面還多了“打開”、“收藏”、“不感興趣”這些選項,這里就涉及到以下iOS10的新特性。

    6.2 push攜帶附件

    因為payload有大小限制,所以如果remote notification想要攜帶附件,那么payload上只能帶上如附件下載地址之類的信息,等通知到達客戶端后由service extension下載附件到本地,然后在初始化UNNotificationAttachment對象時傳入附件在本地的URL。

    初始化UNNotificationAttachment對象時,可以傳入option參數(shù)。這里的option參數(shù)可以強制指定附件的類型,可以選擇是否展示縮略圖,以及縮略圖截取自附件的哪一幀、哪一部分。

    目前iOS10通知只將幾種格式的圖片、音頻和視頻作為附件,附件的大小也有一定限制,具體可以看官方文檔中的限制說明。

    關(guān)于附件的更加詳細的說明,可以參考官方文檔:點此進入

    6.3 攜帶action的通知

    上面提到的“打開”、“收藏”、“不感興趣”這些選項其實就是push攜帶的action,其實從iOS8開始,通知已經(jīng)可以攜帶action了。而在iOS10中,通知的action被放在了更明顯的位置,與action相關(guān)的接口也有了很大變化。

    決定一個通知應(yīng)該有哪些action呢?在payload中,這是由category字段決定的。如果我們希望一個通知能攜帶若干個action,我們就需要將若干個action和一個category綁定起來。通知到達前端后,系統(tǒng)會根據(jù)category的名字來決定要給這個通知展示哪些action:

    怎么得知用戶選了哪個action并做出相應(yīng)操作呢?這需要給UNUserNotificationCenter指定一個delegate:

    然后在delegate的類中實現(xiàn):

    方法:通過response.notification.request.content.categoryIdentifier和response.actionIdentifier就可以得知用戶選擇的action了。

    6.4 改變push內(nèi)容

    這里主要講應(yīng)用的比較多的離線(遠程)push的改變push方法。

    1)改變本地push內(nèi)容:

    本地push,只要request的id一樣,那么就可以更新推送。

    更新的例子:

    此外,還有刪除所有推送等,都在UNUserNotificationCenter.h中實現(xiàn)。

    2)改變離線(遠程)push內(nèi)容:

    目前遠程push只支持更新push內(nèi)容,更新需要通過新的字段apps-collapse-id來作為唯一標示。方法是在HTTP/2 請求頭中使用相同的apns-collapse-id,這樣收到同樣的apns-collapse-id的push時,push內(nèi)容便會更新。

    使用場景:比較容易理解的一個場景就是球賽比分,比如現(xiàn)在是1:0,如果變成1:1的話,只需要刷新原來的新聞,這樣用戶就不會因為同一場比賽收到多條push。

    6.5 兩個extension

    有兩個與push相關(guān)的extension,可能我們會好奇這兩個extension有什么不同,為什么需要兩個?它們分別實現(xiàn)什么功能呢?

    【1)notification service extension】

    給app添加notification service extension后,系統(tǒng)會在收到通知后喚醒它,并允許它修改通知的內(nèi)容,之后再展示這個通知。

    service extension只對remote notification起作用,local notification是無法喚起它的。

    如果想要讓系統(tǒng)喚起service extension的話,payload必須符合這樣幾個條件:

    1)必須增加mutable-content字段并為1,這表示允許客戶端修改這個通知:

    payload(舉例)如下:

    2)這個通知必須展示一個alert,如果只是一個修改badge的通知的話,是不會喚起service extension的;

    3)靜默推送是不能喚起service extension的,所以payload中不能有”content-available” : 1字段。

    所以,通過這個notification service extension,你可以在接收到推送之后、展示推送之前處理一些事情,比如說更新一下推送內(nèi)容,或者在后臺做一些其他事情。

    【2)notification content extension】

    另一項notification content extension用于完全自定義推送展開后的視圖。上面騰訊新聞的展開后的視圖就是通過這個notification content extension實現(xiàn)的。

    依然以騰訊新聞為例子:

    這里Notification Content Extension大展拳腳的地方,在這里可以自定義繪制不同的內(nèi)容,將希望展現(xiàn)給用戶的額外信息可以加載這里。

    下半部分的notification action的實現(xiàn)就是在上面提到的“攜帶action的通知”。

    7、iOS Push的測試要點羅列

    另外注意一點:測試Push的時候,區(qū)分好Appstore證書和開發(fā)證書。兩者不能相互發(fā)Push。

    8、有關(guān)iOS Push的常見疑問匯總

    Q:離線push,支持角標(badge)在本地角標數(shù)值上+1這樣的操作嗎?

    A:不支持。如果是自己實現(xiàn)push服務(wù)的話,需要自己的后臺將角標值badge發(fā)送個APNs服務(wù)器,有些APP使用第三方push SDK除外。

    Q:如果重復(fù)收到離線push,可能是什么情況?

    A:

    1)iOS9之后卸載重裝后生成新的deviceToken,后臺對多個deviceToken都發(fā)送了push

    2)后臺對注銷了的賬號也發(fā)送了push。

    總而言之一般是后臺的邏輯出現(xiàn)了問題,而不是APNs服務(wù)器出現(xiàn)問題。

    Q:直接卸載APP,還能收到離線push嗎?

    A:不會收到。直接卸載APP,雖然后臺不知道APP被卸載了,仍然會對之前的賬號發(fā)送push,但是由于手機上沒有對應(yīng)APP,所以并不會收到push。

    Q:為什么有時候全新安裝APP就立馬有紅點角標?

    A:這是因為卸載該APP時有紅點角標。每個 APP 的角標都是存在 iOS 手機系統(tǒng)里的,開發(fā)無法修改,所以此時卸載前有角標,重新安裝也會有角標。但是,APP 卸載之后超過一天的時間再重裝,那么角標就會被系統(tǒng)清空,屆時也不會有新安裝的 APP 就有角標的情況存在。

    Q:自己Server通過APNs發(fā)的每一條Push,客戶端都會收到么?

    答案是否定的,Push是不可靠的,push通知是fire-and-forget,比如手機關(guān)機,那么自然就收不到,雖然Apple會嘗試幾次。

    Q:Push消息的大小是多少?

    iOS8發(fā)的時間點起,無論那個iOS系統(tǒng),push消息的body大小調(diào)整為2k,注意這里是iOS8的時間點,也就是2014年秋,就目前來說push的限制應(yīng)該是2k不再是256了。

    9、相關(guān)工具推薦

    Knuff離線push工具下載鏈接:https://github.com/KnuffApp/Knuff/releases

    使用方法也比較簡單:

    比如我的payload輸入如下:

    得到的應(yīng)該是有“Knuff測試”文字,和角標數(shù)變?yōu)?99,我們可以看下結(jié)果,與預(yù)料是一致的:

    有了這個工具也更加方便了我們的iOS push的調(diào)試。

    附錄:更多消息推送技術(shù)文章

    iOS的推送服務(wù)APNs詳解:設(shè)計思路、技術(shù)原理及缺陷等

    信鴿團隊原創(chuàng):一起走過 iOS10 上消息推送(APNS)的坑

    Android端消息推送總結(jié):實現(xiàn)原理、心跳保活、遇到的問題等

    掃盲貼:認識MQTT通信協(xié)議

    一個基于MQTT通信協(xié)議的完整Android推送Demo

    IBM技術(shù)經(jīng)理訪談:MQTT協(xié)議的制定歷程、發(fā)展現(xiàn)狀等

    求教android消息推送:GCM、XMPP、MQTT三種方案的優(yōu)劣

    移動端實時消息推送技術(shù)淺析

    掃盲貼:淺談iOS和Android后臺實時消息推送的原理和區(qū)別

    絕對干貨:基于Netty實現(xiàn)海量接入的推送服務(wù)技術(shù)要點

    移動端IM實踐:谷歌消息推送服務(wù)(GCM)研究(來自微信)

    為何微信、QQ這樣的IM工具不使用GCM服務(wù)推送消息?

    極光推送系統(tǒng)大規(guī)模高并發(fā)架構(gòu)的技術(shù)實踐分享

    從HTTP到MQTT:一個基于位置服務(wù)的APP數(shù)據(jù)通信實踐概述

    魅族2500萬長連接的實時消息推送架構(gòu)的技術(shù)實踐分享

    專訪魅族架構(gòu)師:海量長連接的實時消息推送系統(tǒng)的心得體會

    深入的聊聊Android消息推送這件小事

    基于WebSocket實現(xiàn)Hybrid移動應(yīng)用的消息推送實踐(含代碼示例)

    一個基于長連接的安全可擴展的訂閱/推送服務(wù)實現(xiàn)思路

    實踐分享:如何構(gòu)建一套高可用的移動端消息推送系統(tǒng)?

    Go語言構(gòu)建千萬級在線的高并發(fā)消息推送系統(tǒng)實踐(來自360公司)

    騰訊信鴿技術(shù)分享:百億級實時消息推送的實戰(zhàn)經(jīng)驗

    百萬在線的美拍直播彈幕系統(tǒng)的實時推送技術(shù)實踐之路

    京東京麥商家開放平臺的消息推送架構(gòu)演進之路

    了解iOS消息推送一文就夠:史上最全iOS Push技術(shù)詳解

    >> 更多同類文章 ……

    (本文同步發(fā)布于:http://www.52im.net/thread-1762-1-1.html



    作者:Jack Jiang (點擊作者姓名進入Github)
    出處:http://www.52im.net/space-uid-1.html
    交流:歡迎加入即時通訊開發(fā)交流群 215891622
    討論:http://www.52im.net/
    Jack Jiang同時是【原創(chuàng)Java Swing外觀工程BeautyEye】【輕量級移動端即時通訊框架MobileIMSDK】的作者,可前往下載交流。
    本博文 歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處(也可前往 我的52im.net 找到我)。

    Feedback

    # re: 了解iOS消息推送一文就夠:史上最全iOS Push技術(shù)詳解  回復(fù)  更多評論   

    2018-07-27 21:52 by badqiu
    寫的不錯,但可以看下這個。https://m.istockv.com

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導(dǎo)航:
     
    Jack Jiang的 Mail: jb2011@163.com, 聯(lián)系QQ: 413980957, 微信: hellojackjiang
    主站蜘蛛池模板: 伊人久久亚洲综合影院首页| 蜜芽亚洲av无码精品色午夜| 免费一级做a爰片性色毛片| 国产a v无码专区亚洲av| 亚洲最大成人网色| 222www免费视频| 免费人成视频在线观看不卡| 国产午夜亚洲精品不卡电影| 久久黄色免费网站| 四色在线精品免费观看| 国产亚洲一区二区手机在线观看| 国产亚洲精aa在线看| 久久成人a毛片免费观看网站| 亚洲大片在线观看| 日韩精品免费一线在线观看| 成人免费视频网站www| 亚洲一区二区女搞男| 国产亚洲精品第一综合| 亚洲人成无码网站久久99热国产| 中国一级全黄的免费观看| 青青草国产免费久久久下载 | 午夜亚洲av永久无码精品| 亚洲日本一区二区三区| ww在线观视频免费观看w| 青青青青青青久久久免费观看| 国产精品亚洲二区在线| 亚洲国产精品无码久久一线| 国产日韩精品无码区免费专区国产 | 狠狠色婷婷狠狠狠亚洲综合| 自拍偷自拍亚洲精品播放| 欧美a级在线现免费观看| 亚洲国产精品免费视频| 成人免费看片又大又黄| 久久久国产亚洲精品| 国产成人高清亚洲| 嘿嘿嘿视频免费网站在线观看| 免费人成大片在线观看播放| 99久久精品国产亚洲| 又黄又大又爽免费视频| 中文字幕免费在线| 91亚洲国产成人久久精品网址|