那些年年,被蘋果 Ban
掉的 API
楊維中 a.k.a zonble

zonble@gmail.com
Agenda
• iOS 5 - iOS 7

• iOS 9

• iOS 9 - iOS 11

• 現在
你⽤用什什麼 App
透露露了了你是誰
你的⼿手機有哪些 App?
• 亞洲萬⾥里里通:你常搭⾶飛機

• Booking.com、Hotel.com:你常旅⾏行行

• 雙北北公⾞車車 App:你是台北北⼈人

• Dcard:你是⼤大學⽣生

• BabyHi、萌寶⽇日記:你有⼩小孩

• Grindr:你是同志
透過知道你有哪些 App
• 「精確⾏行行銷」:廣告/⾏行行銷公司可以鎖定你

• …犯罪集團也可以鎖定你

• …本國或外國的情治機關也可以鎖定你
透過知道你有哪些 App
• 知道你可能⽐比較有錢,常出國,住台北北,還有⼩小孩…

• …我們可以對你投放台北北的⾼高級托兒所的網路路廣告

• …也可以綁架你的⼩小孩
故事⼀一
UDID
iOS 5 - iOS 7
UIDevice -uniqueIdentifier
• 在同⼀一台⼿手機上,每個 App 都可以取得相同的裝置 ID

• 不不同 App 各⾃自上傳 UDID 到同⼀一台 server,server 端就可
以知道同⼀一台裝置⽤用了了哪些 app

• 也可以⽐比對不不同網路路服務中不不同的帳號是不不是同⼀一個⼈人

• Deprecated in iOS 5

• 在 iOS 6 之後完全不不能呼叫
官⽅方的 UUID 替代品:
IDFV & IDFA
• IDFV: UIDevice -identifierForVendor

• iOS 5

• 系統中,相同 Bundle ID 的 prefix 的 App(例例如都是)
com.kkbox.*),可以取得相同的 IDFV,限制只有屬於同
⼀一個開發商的 App 之間可以辨識⽤用⼾戶

• 如果所有相同 prefix 的 App 都被移除後,重新安裝⼀一次你
的 App,IDFV 會改變
官⽅方的 UUID 替代品:
IDFV & IDFA
• IDFA:
ASIdentifierManager -
advertisingIdentifier

• 在上架時要特別勾選有⽤用
到 IDFA

• 讓廣告商可以追蹤⽤用⼾戶

• ⽤用⼾戶可以在設定中關閉提
供 IDFA,就無法取得 IDFA
禁⽤用 UDID 的衝擊
• 有些 App 是拿 UDID 當做本地資料料加密的 Key

• 把 UDID 換成 IDFV 之後,就解不不開了了…

• 有些 App 的商業模式是只能在有限數數量量的裝置上使⽤用,並
且拿 UDID 判斷裝在幾台 iOS 裝置上

• App 刪掉重裝,IDFV 會改變,會誤判當做多⼀一台裝置,
然後就會接到⽤用⼾戶雪⽚片般的客訴…

• ⽽而且⼤大家還是很想跨 App 追蹤
那時候蘋果也出過包
•某⼀一個星期,問 IDFV,居然也只會回
傳⼀一堆 0…
⼤大家在找的替代品
•網路路卡卡號 MAC Address

•UIPasteboard
網路路卡卡號
• iOS 7 之後,⼀一律律回傳
02:00:00:00:00:00
UIPasteboard
• 剪貼版。在不不同 App 間做複製、貼上的 API

• ⼀一般我們只會使⽤用 Singleton 物件 UIPasteboard.general 做
複製貼上

• 但是可以⽤用 + pasteboardWithName: create: 建⽴立⾃自⼰己的剪
貼版,另⼀一個 App 可以從中取得資料料

• 在這裡產⽣生⼀一組字串串,就變成可以跨 App 的 ID

• 重開機也不不會被清掉
OpenUDID
UIPasteboard
• iOS 6 之後,只有屬於同⼀一個 App Group 的 App,才可以
共⽤用⾃自⼰己創⽴立名稱的 UIPasteboard

• + pasteboardWithName: create: 傳⼊入的 name 必須是 App
Group 的名稱
總之,蘋果要求只能是在同⼀一
個 App Group 裡頭的 App/
Extension,才可以共享資料料
但是你就會遇到明明就同⼀一家公司
的 App,沒辦法放進 App Group…
• 同⼀一個集團底下有多家公司,不不同公司為了了財務獨⽴立,不不
想讓不不同公司的 IAP 資料料混在⼀一起,所以就是要⽤用另外⼀一
個 Developer Program 上架…

• ⼀一家⼤大公司的 App 發包給多家外包廠商做,該公司只提供
App Store 的 Provision Profile,平常開發階段要各⾃自的外
包公司⽤用⾃自⼰己的 Developer Program 做 Code Sign,但是
⼜又要求在開發階段就能測試跨 App 的資料料共⽤用…(最後兩
家公司⼜又⼀一起去買⼀一個新的個⼈人開發帳號,以及寫了了很複
雜的 entitlement 設定)
怎樣解決 IDFV 會改變的問題?
• 把⼀一組 ID 寫進 Keychain 裡頭。Keychain 裡頭的資料料不不會
因為刪除 App ⽽而改變。

• 以前⽤用 UUID 加密資料料怎麼辦?

• 在 iOS 5/6 的年年代,我們⼀一路路 fallback…

• 如果還可以拿到 UUID,代表可能以前有⽤用過 UDID 加
密,把 UUID 先寫到 Keychain 以後留留著⽤用

• 如果拿不不到,Keychain 沒東⻄西,就⾃自⼰己產⽣生⼀一組
NSUUID,寫進 Keychain 裡

• 以後都⽤用 Keychain 裡頭存的這把 key
故事⼆二
canOpenURL:
iOS 9
Custom URL Scheme
• 在 Info.plist 中設定

• 執⾏行行 fb:// 開頭的 URL,可以叫出 Facebook

• 執⾏行行 line:// 開頭的 URL,可以叫出 LINE 做指定的事情

• 執⾏行行 kkbox:// 開頭的 URL,可以叫出 KKBOX
UIApplication

-canOpenURL:
• 詢問系統是否有辦法開啟某個 URL

• 如果能開啟 fb:// 代表你有裝 Facebook

• 如果能開啟 line://,代表你有裝 LINE…
WWDC 2015
canOpenURL:
• 只能夠在 Info.plist 設定五⼗十組
LSApplicationQueriesSchemes

• 其他⼀一律律回傳不不允許詢問
Universal Links
• 如果你要另外⼀一個 App 做事,就呼叫另外⼀一個 App 對應的
網⾴頁的 https:// URL

• 系統可以判斷是否有對應到這個 https:// URL 的 App,然後
開啟 App,如果沒有對應的 App,就開啟對應的網⾴頁

• 在蘋果後台勾選 Associated Domain,產⽣生新的
entitlement,然後在網站上放置 apple-app-site-association
檔案

• 所以每個做 App 的⼈人就得同時做個網站,創造就業機會
Universal Links 也很兩光
• 在從 App Store 上安裝新 App 的時候,iOS 才會去你的網
站上下載 apple-app-site-association,開始讓你的 App 開
始⽀支援 Universal Links

• 如果⽤用⼾戶是升級安裝…好像就不不會去抓

• ⽽而且每次也都不不⾒見見得會下載成功
值此同時
• 要使⽤用⽤用⼾戶的地點、相機、相本、⿆麥克⾵風、通訊錄錄、⾏行行事
曆曆、藍芽…都要額外在 Info.plist 中說明你的 App 為何搖使
⽤用這些權限

• iBeacon 也沒成功:猜想因為 iBeacon 是⾮非常精確,鎖定
⽤用⼾戶位置的室內定位。要掃描 iBeacon,就會跳出權限提
示,也讓⼈人降低使⽤用意願

• 蘋果想要求所有的 App 都強制使⽤用 https,但並沒有成功
故事三:
Safari View Controller
iOS 9-iOS 11
Safari View Controller
• ⼀一個 Cookie/Session、帳號密碼都可以與 Safari 共⽤用的
View Controller

• 如果在 App 中使⽤用 UIWebView 或 WKWebView,顯示⼀一
些 Web 內容,由於 Cookie/Session 不不⼀一樣,所以看到的
網⾴頁也跟 Safari 看到的不不⼀一樣

• 只能要求指定開啟某個 URL,沒有接收 Web 事件的
delegate method
Safari View Controller
• 我們於是可以⽤用 Safari View Controller 偵測裝了了哪些 App

• App A ⽤用 Safari View Controller 開啟某個特定網⾴頁,帶
上特定代表某服務的某帳號 GET 參參數數,⾴頁⾯面根據這個
GET 參參數數產⽣生 Cookie

• App B 後來來也做了了⼀一樣的事情,所以那個⾴頁⾯面就會知道
A、B 兩個 App 都在同⼀一個⾴頁⾯面留留下過 Cookie

• ⾴頁⾯面就可以反查出同⼀一個⽤用⼾戶同時⽤用過 A、B 兩個 App
Safari View Controller
• 我們還可以偷偷使⽤用 Safari View Controller 塞 Cookie

• iOS 9:Safari View Controller 的 frame 是 CGRectZero,
把 View 的位置放在 super view 之外,都會幫你載⼊入網⾴頁

• iOS 10:你可以把 Safari View Controller 設成只有⼀一個
pixel 的寬⾼高
Safari View Controller
• iOS 11 停⽌止 App 之間共⽤用 Session

• 如果要⽤用 Safari View Controller 做 OAuth 驗證時,需要呼
叫 SFAuthenticationSession,才能夠暫時拿到屬於某個網
站的 Cookie/Session
兩個 Private API
• LSApplicationWorkSpace:可以查詢系統中所有的 App
Bundle ID

• MBAppManager:可以查詢符合某個 Bundle ID 的 App 是
否存在
Dead in iOS 11
現在
還有什什麼⽅方式
可以知道你裝了了/⽤用了了哪些 App?
現在
• 你還是可以知道⽤用⼾戶裝了了哪些你/你的公司的其他 App

• 如果⽤用⼾戶⽤用了了 Facebook 登⼊入,那 Facebook 也還是會知
道你⽤用了了哪些 App

• 如果你⽤用了了 1Password 儲存密碼,⽽而且還寫了了是哪個 App
的密碼,其實 1Password 也知道你⽤用了了哪些 App
藍⽛牙穿戴裝置
• ⼀一些藍芽穿戴裝置可以接收⼿手機傳來來的通知訊息

• 也就是說,這些裝置可以知道收到了了來來⾃自哪些 App 的通知
語⾳音輸⼊入法
• 有些 iOS 第三⽅方鍵盤提供「語⾳音輸⼊入」功能

• 從鍵盤按下「語⾳音輸⼊入」之後,會將 container app 帶到前景,
讓⽤用⼾戶在 container app 錄錄⾳音之後,再將原本的 app 帶回前景,
輸⼊入語⾳音辨識的內容

• 也就是,這些鍵盤知道⽤用⼾戶是從哪個 app 轉過來來的,就可以蒐集
⽤用⼾戶在⼿手機上使⽤用哪些 app

• https://github.com/zonble/EvilKeyboard

• 不不過輸⼊入法其實可以從你打了了什什麼字偷⾛走更更多東⻄西…
結論
• 好的⽤用⼾戶體驗應該是⽤用⼾戶清楚知道你對他們做了了什什麼,⽽而
不不是偷偷蒐集、濫⽤用⽤用⼾戶資料料,把⽤用⼾戶蒙在⿎鼓裡,還⼝口⼝口
聲聲說「不不要打擾客⼾戶」

• 把商業模式建⽴立在不不當蒐集個資上,不不但是跟蘋果對抗,
也完全違反⽤用⼾戶的期待

• 永遠不不要覺得你蒐集的資料料不不會外洩。唯⼀一有可能不不會外
洩資料料的可能,就是⼀一開始就不不要蒐集
App 三法則
• App 不不可以傷害⼈人類類

• App 不不可以因為懶惰不不作為,導致⼈人類類受到傷害

• 在不不違背前兩點下,App 不不可以傷害⾃自⼰己
以上

那些年被蘋果 Ban 掉的 API