隱式 Intent 已經(jīng)不是你以為的 Intent 了
一、前言
如果你的 App 內(nèi),有使用到隱式 Intent 去與其他 App 交互。例如,分享一個鏈接,當你的系統(tǒng)升級到 Android M(Api level 23) 之后,你就需要小心了,它可能并不能按照你的意愿去執(zhí)行你想執(zhí)行的任務。
舉個例子,你想分享一個鏈接,而每次都想讓用戶主動去選擇一個,但是有時候這個操作并不能如愿,如果用戶主動指定了某個 App 打開這個 鏈接,你的 App 將直接使用用戶指定的 App 打開這個鏈接(其實是有例外情況的,后面說)。
二、Android M 改變了什么
一般我們想要分享一個鏈接出去,直接使用 隱式 Intent 即可。
在 Android M 之下,它會調(diào)起系統(tǒng)內(nèi),所有符合的 App 供用戶選擇一個合適的去打開。
可以看到,默認會彈出一個選擇器,讓用戶選擇一個 App 來處理。這沒什么好說的,是一個常規(guī)的操作,應該幾乎所有的 Android 開發(fā)人員,都是不陌生的。
除了這個系統(tǒng)的選擇器,我們也是可以在代碼中,去查詢到符合 Intent 過濾要求的 App 的。需要使用 PackagemManager.queryIntentActivitys() 方法來進行查詢,上面的 demo 中,也通過 Log 打印出了它的輸出。
看輸出,和我們選擇器中的是一致的。
但是,這一切在 Android M 就開始改變了。
Android M 推出了 App Links 是的概念,系統(tǒng)將通過你的配置的網(wǎng)址進行身份驗證,如果通過驗證,你需要打開的鏈接,將直接使用你的 App 來打開,而不是直接跳轉(zhuǎn)到一個瀏覽器,這個過程是不會向用戶詢問的。但是 App Links 依托于 Google 的服務,所以國內(nèi)開發(fā)者應該享受不到它的便利。
但是處理通過網(wǎng)站的服務器來進行身份驗證之外,還可以在設置頁面中,對默認的程序進行設定。
路徑是:系統(tǒng)設置 → 應用 → 應用程序 → 默認打開
例如這里打開了 Google + 這款 App 的默認打開頁面。
可以在『打開支持的鏈接』中,選擇是否默認打開使用它來完成打開鏈接的操作。
一旦選擇了『在此應用中打開』,在去運行上面的程序,你將直接使用 Google+ 打開你的鏈接,而用戶將失去選擇的權(quán)利,除非用戶將這里重新設置為『每次都詢問』。
三、例外情況
實際上,這也是存在例外的情況的。
3.1 過濾會先校驗 domain
下面是一個標準的 URL 格式:
scheme://host.domain:port/path
這種隱式 Intent ,優(yōu)先考慮能與 domain 匹配的 App,這是系統(tǒng)內(nèi)部的一個優(yōu)先級策略。
例如,現(xiàn)在在我的系統(tǒng)中,有一款 HiitTime 的 App,它設定了一個 m.hiittime.com 的鏈接支持。
再修改前面提供的 Demo,只是把鏈接指向了它。
這樣的情況下,哪怕我們也將 Google+ 設置為『在此應用內(nèi)打開』,它最終也是允許用戶去選擇 HttiTime 這個 App 來處理的。
3.2 系統(tǒng) App 優(yōu)先級高
前面 HiitTime 的例子可以看到,實際上我是沒有指定 Chrome 來處理的,但是選擇器中,實際上是會有 Chrome 的選擇的,這個我暫時沒有發(fā)現(xiàn)可以去掉它的辦法。
而在 Chrome 的默認開打的選擇頁面中,也是無法操作的,我只能理解為它對系統(tǒng) App 做了特殊的保護處理。
四、辟謠
之前看到有人說可以在對 Intent 的 Uri 只設定 scheme ,例如,’http://‘ 然后后面什么都不跟,這樣系統(tǒng)就會列出所有的瀏覽器供你選擇,然后我們就可以在選擇列表中,手動指定打開的 App ,這樣就可以很好的打開它了。
但是實測,這樣是行不通的,當設置了 Google+ 『在此應用內(nèi)打開』的情況下,依然會直接使用 Google+ 來完成我們的操作,所以這個操作是不成立的。
但是也提供了另外的一個思路,我們實際上是可以通過 PackageManager 拿到系統(tǒng)中安裝的 App 的,而通常我們需要分享打開的 App 就那么多,所以我們可以以窮舉的方式,篩選出需要的 App ,自己來定義這個選擇器,然后指定對 Intent 指定 PackageName 就可以完成對指定 App 的分享,而繞過『在此應用內(nèi)打開』的設定。
這只是一個思路,沒有實際實驗,但是應該可行。
五、小結(jié)
如果你的 App 內(nèi),有這種隱式的操作,就應該檢查一下是否在這樣的情況下,依然能完成我們?nèi)缙诘墓δ堋?/p>
【本文為51CTO專欄作者“張旸”的原創(chuàng)稿件,轉(zhuǎn)載請通過微信公眾號聯(lián)系作者獲取授權(quán)】