關於微信檢測SDK應用的原理淺析(iOS)

前言:

    今天研究微信分享SDK,對iOS SDK 如何往微信客戶端傳遞圖片對象(Scheme URL只支持純文本)感到好奇,遂google了一下,發現其中的原理,留意文章關鍵字“UIPasteboard”。另外微信反過來檢測已安裝包含微信SDK的應用,檢測方法也很巧妙,也用了“”UIPasteboard。

最後BS了一下 “來往” 的開發者,微信SDK的key還是用demo的,害得我調試SDK時,跳轉到“來往”去了。


轉自:http://www.cnblogs.com/ipinka/p/3230280.html

微信作爲一個開放平臺,各方面都是做得比較好的,推出了SDK之後,微信與使用了SDK的應用便能進行更多交互。但在iOS平臺上,應用間交換數據還是相對麻煩的,那麼微信爲什麼能直接在應用檢測到其他使用了SDK的應用呢?基於這個疑問,我用了一個下午研究其原理。(當前微信版本4.5.0.54

一、SDK的方法

我之前也沒使用過微信的SDK,不過下載後,查看發現SDK接口有這麼一段

複製代碼
1 /*! @brief WXApi的成員函數,在微信終端程序中註冊第三方應用。
2  *
3  * 需要在每次啓動第三方應用程序時調用。第一次調用後,會在微信的可用應用列表中出現。
4  * @param appid 微信開發者ID
5  * @return 成功返回YES,失敗返回NO。
6  */
7 +(BOOL) registerApp:(NSString *) appid;
複製代碼

換句話來說,如果下載包含SDK的應用後,不打開應用或應用不調用註冊方法,微信是無法檢測應用的。但事實上,這段註釋還不完整(原理會在下文解釋),第一次在本機安裝的應用,不打開確實無法讓微信檢測。同時,如果應用刪除了,微信也會及時在可添加的列表中刪除這個應用。但是,如果在本機安裝過一次並打開過這個應用,無論以後刪除後再安裝,不重新打開,微信一樣可以檢測到這個應用。

 

二、交互的方法

其實,現時在微信中添加應用這個功能還是略無聊,只是增加了一個類似快捷方式的東西而已。當然以後發展了,這個功能肯定大有作爲,包括類似新浪微博SDK的SSO也是使用了URLScheme。在應用中跳轉到其他應用,方法很簡單,被打開的應用先設置後自己的URLScheme,例如

然後只要用類似

1 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"wxd930ea5d5a258f4f://test"]];

“wxd930ea5d5a258f4f”爲上面URLScheme,“test”改爲參數,當然沒有參數都是可以正常打開的。還有撥號、郵件等系統默認的URLScheme,可以自己搜索。至於第三方應用的URLScheme,則可以在應用目錄下的“XXX.app”的“Info.plist”的“CFBundleURLTypes”中找到。

 

三、檢測應用的方法

查了一下檢測已安裝應用的方法(可參考http://tangqiaoboy.blog.163.com/blog/static/116114258201172975359440),不外乎就這幾種方法,顯然最可靠的就是UIApplication的方法

1 - (BOOL)canOpenURL:(NSURL *)url

這也是網上大多數人認爲微信檢測應用所採用的方案,但顯然這還不完整。首先,檢測時需要知道檢測對象的URLScheme,難道微信要遍歷每一個可能的URLScheme來進行檢測??這效率肯定相當低下,越來越多人使用微信平臺的SDK,那麼將來遍歷URLScheme的成本也太大了吧。於是我有一種猜想,微信SDK都能像OpenUDID一樣生成一個UDID,然後打開包含SDK的應用時,就同時將UDID和應用的信息上傳到服務器,然後每次登陸微信都利用UDID查詢已安裝的應用信息。

似乎也可以實現,但是我測試後發現,即使不聯網,微信依然能檢測到已安裝的應用。上面的猜想直接被推翻了。

後來我想起了OpenUDID的原理(可參考http://blog.csdn.net/lusonglin121/article/details/9466495),其中有利用到UIPasteboard的地方

1 UIPasteboard* slotPB = [UIPasteboard pasteboardWithName:availableSlotPBid create:YES]; 

UIPasteboard是創建自定義的設備剪貼板,可以用於應用間的數據交換,而且支持文字、圖片、URL和顏色。最重要的是,剪貼板的數據大小似乎不限制大小(我查到的資料沒有提及數據大小的問題,具體的原理我以後會繼續研究,如有錯漏請包涵),還有能使用數組儲存和重啓後的持久化。

 

說了這麼久,思路其實已經很清晰了,我現在就來總結一下微信實現檢測的整個流程:

1、安裝微信,打開微信,這很重要,因爲需要微信來創建剪貼板

1 UIPasteboard *paste = [UIPasteboard pasteboardWithName:@"hello" create:YES];
2 paste.persistent = YES;

如類似代碼,persistent的屬性一定要設置爲YES,否則應用一退出,剪貼板就被清空了。這個文檔說得很清楚的,系統的剪貼板是默認YES,自行創建的默認NO。還有剪貼板的內容如果被持久化,則應用退出後、重啓後,內容一直都在,除非應用被刪除。事實上,一旦微信被刪除(僅刪除Document和Library是不影響檢測應用的),重新安裝後,打開微信也無法檢測已安裝應用了。因爲剪貼板被清空了,除非再次打開那些使用SDK的應用。這也證明了,微信確實是使用了剪貼板的方法。

2、使用SDK的應用打開後,將自己的Key、URLScheme和圖標等,圖標就在mainBundle那裏,添加到微信的剪貼板。

3、再次打開微信,微信通過遍歷剪貼板的內容,就能輕鬆列出用戶本機上使用了SDK的應用名字和圖標,點擊添加也是可以立即打開。不過此處有一些地方需要注意,應用的描述介紹是需要在線加載的,所以不連接網絡,第一次列出的應用介紹會變成空白。同時,圖標也會在線加載,替換原來從剪貼板中拿來的圖標。

4、基本所有步驟都完成了,剩下只是每次添加應用前再檢查一下是否有效即可。

 

總結:

這樣就能完整解釋了微信檢查應用功能的種種現象了,不過,其實有需要改進的地方:

1、應用刪除後,下次打開微信遍歷完成後,並未將剪貼板中的對應記錄刪除。其實這種做法會有出現一種情況,就是用戶安裝了大量包含SDK的應用後,都打開了幾次後就刪除。但冗餘的記錄仍在剪貼板,那麼遍歷的速度會受到很大的影響。這裏需要一些優化的策略,如定期清理、達到一定數量就清理等(或者微信已經做了我不知道,但是,我發現每次點擊“+”的按鈕,確實有輕微卡頓)。

 2、就是一旦被知道Pasteboard的name,就能夠知道用戶曾經安裝過哪些應用,同時再通過遍歷URLScheme知道現時還存在的應用。當然name確實存在被反彙編泄露出來的可能(下一步可以研究一下這個),利用微信這個特性或許能獲知用戶更多的私隱。當然遍歷測試URLScheme的方法其實每一個廠商都能做,只要積累一個足夠大的“URLScheme庫”也就可以了,但效率不及直接利用微信要快。同時,有一些應用確實不使用URLScheme的,就無法通過這種方法獲取了。顯然,微信利用這種方法着實能統計用戶的安裝應用行爲,手法相當高明,要是未來很多應用都使用了微信SDK的話,它統計的數據就會更爲準確。所以微信SDK有意封裝了這些方法,僅希望自己能獲知這些信息。

 

通過分析微信的這種實現方法,希望也能爲大家拓展一下編程的思路,歡迎交流。我承認這次的分析還是不夠嚴謹,但微信檢測應用的功能確實可以通過這種方法來實現,如果以後還有時間,我會考慮再深入研究。後續更新,我已經在微信客戶端發現了這個接口

 

- (id)getRegisterPasteboardName;

 

這基本可以證明我的結論大體是正確的,至於Pasteboard的name我還需要繼續研究。

轉載請註明Pinka-cnblogs。




發佈了148 篇原創文章 · 獲贊 22 · 訪問量 55萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章