原文連結:http://blog.csdn.net/hherima/article/details/50827363
【僅用於技術交流,未經允許禁止轉載】
通常APP-Server使用http協議,告訴APP需要的展示內容圖片,文字。這是一種最為常見的協議了。另外一種用戶端內協議,比如新聞APP,點擊一個焦點新聞,APP跳到相應的頻道或專題。不難發現:前者是Server->APP通訊,主要是內容類型的,後者是APP<—>APP內通訊,主要是命令、動作類型的。
如何更好的處理APP內通訊,這裡有必要先介紹一下iOS平台處理序間通訊。 處理序間通訊
以iOS平台為例,處理序間通訊IPC,可以通過自訂URL Schema,然後APP實現-(BOOL) application:(UIApplication *) openURL:(NSURL *) sourceApplication:(NSString *) annotation:(id) 方法,可以處理一些命令和參數。其中sourceApplication即調用者的bundleIdentifier。比如下面這條URL,會調起twitter用戶端,並拉起發送推文的介面。
URL Scheme完美解決了同一個作業系統中,調用APP和傳輸訊息和命令的問題。URL Schema機制,給開發人員提供了很好的思路,可以解決APP內通訊問題。CPMessage應運而生。 什麼是CPMessage
CPMessage(Cross Platform Message跨平台訊息)可以當做伺服器/用戶端(讓用戶端處理一些命令),或者用戶端內部通訊的橋樑。通訊的發起者可能是伺服器、Push、使用者操作、HTML5或者是別的APP。用戶端根據具體命令和相應參數,執行相應動作。總之,CPMessage思路源於iOS平台的URL Schema機制。 CPMessage的機制
為了確保多平台的一致性,使用協議名稱CPM作為開頭,只是傳遞通訊協定的方式不同。在iOS上,向用戶端通訊的方式是scheme+protocol,例如:
cpm://message.cmd?messageID=MsgID&urls=EncodedURLStrings&uid=uid&ex1=ex1&ex2=ex2&ex3=ex3。
下面將各部分標註一下:
一般來說:命令名稱都是message.cmd,經常改變的是messageID(下面詳細介紹)。參數列表中,messageID表明是那種動作,比如,開啟一個webview、開啟新的頁面、還是調起登入框等。參數列表後面是一些輔助參數。下面的表格給出了一些樣本。
參數 |
用途 |
格式 |
樣本 |
MessageID |
用來指定用戶端做出的響應 |
string |
1.1 |
url |
需跳轉的網址 |
string |
www.baidu.com |
ex1 |
額外參數 |
string |
“03” |
另外,如果ex1、ex2和ex3不夠用。還可以使用more參數。比如:more = {"title":"helloworld","name":"jack"};more參數格式為json格式。方便用戶端解析欄位。
MessageID
MessageID根據可分為mainID和subID,比如MessageID=2.1。那麼mainID是2,subID是1。一般來說mainID是操作類型的區分,比如:
mainID=1表示開啟頁面。
mainID=2是傳遞資料。
mainID=3 是開啟其他sdk等等。
subID則是一些操作的細分類型,比如:開啟那個頁面等等。
APP都是跨平台的,至少有iPhone,Android用戶端,那麼URL Schema頭部將是不同的。舉例:Server給的H頁面中,某個連結是個CPM訊息,URL Scheme配合CPM的使用,如下格式:
myapp://cpm://xxxxxx。作業系統層級會讀取到“myapp://”從而拉起用戶端,用戶端內部讀取到“cpm://” CPMessage的使用 開發人員如何應用CPMessage到自己的APP中呢?你需要做三件事:
第一,提前註冊一些UIViewController和方法,封裝成一個個CPMessageItem。
第二,當CPMessage過來的時候,將其解析成CPMessageCommand,其中CPMessageCommand包含了參數。
第三,使用一個CPMManager類,將command 和 item對應到某一個UIViewController,並使用NSInvocation,調用之前註冊好的方法。
那麼,回到剛才一開始的問題,我們假設MessageID = 1.1 即跳轉頻道,ex1即頻道的index。那麼,Server將下面的URL訊息,封裝到焦點新聞裡
cpm://message.cmd?messageID=1.1&ex1=03
用戶端TabViewController註冊一個調轉頻道的method -(void) switchToChannel:(int)index,執行CPMManager,TabViewController 執行switchToChannel方法。可以很優雅的解決新聞APP,調轉到任意頻道的問題。 CPMManager的UML圖+流程圖
CPMManger 的幾個關鍵函數
prepareProcessor 事先註冊好一些類和類方法
handleUrl:接收url,帶有cpm schema的url
onCPMIsComing:參數是CPMCommand
handleCPM:參數CPMCommand。最終通過[NSInvocation invoke]實現回調。 CPMManger的實現
這裡只列出部分代碼,即CPMManger的關鍵代碼:
[objc] view plain copy //向CPMParse註冊的回呼函數。 - (void)onCPMIsComing:(NSNotification *)noti { NSDictionary *userInfo = noti.userInfo; if ([userInfo isKindOfClass:[NSDictionary class]]) { CPMCommand *command = [userInfo objectForKey:kCPMessageParserNotificaitonCommandKey];// if ([command isKindOfClass:[CPMCommand class]]) { [self handleCPM:command]; } } } //真正處理CPMessage的地方。通過NSInvocation將message命令和UIViewController關聯起來 - (void)handleCPM:(CPMCommand *)message { [self prepareProcessors]; CPMItem *item = (CPMItem *)[self.processors objectForKey:NSStringFromCPMessageCommand(message)]; if (nil == item) { return; } [item getInfoFromCPMessageCommand:message]; UIViewController *visibleCtrl = [self.assit topViewController]; Class receiverClass = NSClassFromString(item.className); if (item.classMethod != nil) { [self performClassSelector:item.classMethod onTarget:receiverClass withArgs:item.classArgs]; [item clearInfoFromCPMessageCommand