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

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

1、SDK的方法數組

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

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

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

 

2、交互的方法網絡

其實,現時在微信中添加應用這個功能仍是略無聊,只是增長了一個相似快捷方式的東西而已。固然之後發展了,這個功能確定大有做爲,包括相似新浪微博SDK的SSO也是使用了URLScheme。在應用中跳轉到其餘應用,方法很簡單,被打開的應用先設置後本身的URLScheme,例如微信開發

而後只要用相似app

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

「wxd930ea5d5a258f4f」爲上面URLScheme,「test」改成參數,固然沒有參數都是能夠正常打開的。還有撥號、郵件等系統默認的URLScheme,能夠本身搜索。至於第三方應用的URLScheme,則能夠在應用目錄下的「XXX.app」的「Info.plist」的「CFBundleURLTypes」中找到。函數

 

3、檢測應用的方法測試

查了一下檢測已安裝應用的方法(可參考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 UIPasteboard *paste = [UIPasteboard pasteboardWithName:@"hello" create:YES];
2 paste.persistent = YES;

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

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

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

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

 

總結:

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

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

 二、就是一旦被知道Pasteboard的name,就可以知道用戶曾經安裝過哪些應用,同時再經過遍歷URLScheme知道現時還存在的應用。固然name確實存在被反彙編泄露出來的可能(下一步能夠研究一下這個),利用微信這個特性或許能獲知用戶更多的私隱。固然遍歷測試URLScheme的方法其實每個廠商都能作,只要積累一個足夠大的「URLScheme庫」也就能夠了,但效率不及直接利用微信要快。同時,有一些應用確實不使用URLScheme的,就沒法經過這種方法獲取了。顯然,微信利用這種方法着實能統計用戶的安裝應用行爲,手法至關高明,要是將來不少應用都使用了微信SDK的話,它統計的數據就會更爲準確。因此微信SDK有意封裝了這些方法,僅但願本身能獲知這些信息。

 

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

 

- (id)getRegisterPasteboardName;

 

這基本能夠證實個人結論大致是正確的,至於Pasteboard的name我還須要繼續研究。

轉載請註明Pinka-cnblogs。

相關文章
相關標籤/搜索