眾所周知,在 iOS 平台上自從 8.0 版本開始,可以為 iOS 開發第三方的輸入法鍵盤了,而這些鍵盤可以被放在 AppStore 銷售了,不過,同時也有著十分嚴格的權限規則。
對此,蘋果為第三方的鍵盤設計了兩種權限,一種是最小的,只有最基本的鍵盤功能的權限、另一種則相對較多,鍵盤獲取了“完全訪問”權限之後基本上就和 安卓 上鍵盤差不多,可以訪問聯繫人、可以聯網等等。
不過,不少鍵盤卻是為了設置功能而不得不向用戶請求這個“完全訪問”權限,因為他們發現,如果不這麼做,作為插件的鍵盤就不能訪問作為宿主的 app 的存儲空間。
在 ios 中,你的鍵盤雖然是以一個 app 的形式來銷售和使用的,但鍵盤實際上是一個“插件”,它由 ios 單獨加載,所以實際上它和你的 app 是“兩個不同的應用”,它們有各自獨立的存儲空間。
這時候如果你要給用戶開發一款不請求完全訪問權限的鍵盤,你就需要在鍵盤裡額外添加一個按鈕,以及一個界面來設置鍵盤屬性。而這個應用 app,則加入一些空洞的新手引導等內容就草草了事。
比如說
比較老牌的雙拼輸入法 SPI 就是這麼做的,它的 app 裡是新手引導和用戶論壇,而設置則在鍵盤上有專門按鍵:
真的就沒有辦法了嗎?
其實是有的,在 ios 開發中有一個叫做 “AppGroup” 的技術,它可以給同一個開發者的不同 app 打組,為這些 app 提供一個公共的存儲空間,這樣的話同一個開發者的不同應用之間就可以交換一些配置或者文件,為用戶提供更好的服務——比如配置信息。
說起來沒什麼特別的
蘋果對第三方鍵盤的 AppGroup 使用一開始是沒有限制的,可以說這是一個 bug ——利用 AppGroup 鍵盤即使不獲取完全訪問權限,也同樣可以將收集的信息傳走,不過在 ios10 之後,他們完善了權限,——鍵盤就只能讀取而不能往 AppGroup 的共享空間寫入內容了。
但好在,我們還是可以做到讓 app 控制鍵盤的。你們已經想到了,只要把配置文件放到共享目錄裡,然後鍵盤主動去讀取就夠了。
那麼怎麼做到一些更新的問題呢?比如我可以檢測文件是否存在,我可以加載配置信息,但是如果一個詞庫,它只是內容變了……
如果每次都從共享空間擼一份回來,會很耗費資源,所以我用了一個“版本號”的機制,每次進行額外的校對就可以了。
這就是為什麼在一開始落格輸入法要求用戶配置完成之後一定要點“返回”,因為這樣才會觸發版本更新,鍵盤才會讀取。
這樣說起來簡單,但做起來就比較複雜——或者說是繁瑣,你需要在 app 和鍵盤里維護統一份序列化和反序列化的工具,這裡我自己則用了一個單件模式來專門管理而不是各自訪問。(注意不能使用延遲加載,這個特性雖然益處無窮,但你這麼做就會導致配置偶爾難以改變,鍵盤的生命週期是不可預測的 ——儘管一般來說是收起鍵盤的五秒後)。
代碼伺侯
這裡我把自己的代碼片段貼出來給大家:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
/** 获取的路径为 app groups 共享路径 - parameter fileName: 文件名 - returns: 共享目录的路径 */ class func get(groupPath fileName: String) ->String { let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.logcg.Input") let fileUrl = url?.appendingPathComponent(fileName) return fileUrl!.path } |
在應用和鍵盤裡都可以使用這個方法來獲取 AppGroup 的路徑,只不過鍵盤是只讀的,而應用這擁有完全的讀寫權限。
其他的就和普通的讀取配置沒什麼區別了,你要注意,你同樣可以給配置寫入,只不過這是無效的——重點是不會有任何的錯誤提示。
1 2 3 4 5 6 7 8 9 10 11 12 |
func getConfig() { let array = NSArray(contentsOfFile: configPath) if array == nil { return } let configDict = array![0] as! Dictionary<String, AnyObject> if let i = configDict["CustomCodeTableVersion"] {customCodeTableVersion = i as! Int} if let e = configDict["EmojiMode"] {emojiMode = e as! Int} if let i = configDict["AssistCodeVersion"] {assistCodeVersion = i as! Int} if let b = configDict["BoomIsLeft"] {boomIsLeft = b as! Bool} if let i = configDict["AssistCodePlan"] {assistCodePlan = i as! Int} if let i = configDict["CodeTableVersion"] {codeTableVersion = i as! Int} } |
總結
其實搜狗也在用這個方法了,畢竟在不開啟完全訪問權限的情況下,搜狗還是可以用應用來對鍵盤進行基本的配置的——你們要注意,在 ios 10 版本之前,鍵盤是可以給共享空間寫入的,我就提這麼一句。
本文由 落格博客 原創撰寫:落格博客 » 落格輸入法 是怎麼實現 app 設置而不需要 完全訪問 權限的?
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/2488.html