Android 開發之鎖屏彈窗

發表於2016-08-16

嘗試利用 WindowManager 新增浮窗的方式實現

想在鎖屏上面實現彈窗,第一個想法就是利用 WindowManager 設定 WindowFlag,通過設定 Flag 的顯示優先順序來讓視窗顯示在鎖屏的上面。接下來就是試驗可能相關的 Window Type 屬性,驗證該方案是否可行。

在嘗試各個 Window Type 屬性之前需要明確各個 Type 所需要的許可權,下面是 com.android.internal.policy.impl.PhoneWindowManager.checkAddPermission 的原始碼:

明顯不適合的 TypeTYPE_TOAST, TYPE_INPUT_METHOD, TYPE_WALLPAPER; 可能適合的 TypeTYPE_PHONE, TYPE_PRIORITY_PHONE, TYPE_SYSTEM_ALERT, TYPE_SYSTEM_ERROR, TYPE_SYSTEM_OVERLAY; 其它型別的 Type:需要系統簽名許可權:

而申請該許可權需要系統簽名,所以我們是無法獲取許可權的。

TYPE_PHONE

TYPE_PHONE 型別的視窗可以顯示在其它 APP 的上面,但不能顯示在鎖屏的上面,所以 PASS。

TYPE_PRIORITY_PHONE

TYPE_PRIORITY_PHONE 型別的視窗可以顯示在其它 APP 的上面,但不能顯示在鎖屏的上面,所以 PASS。而且實際的行為和註釋並不相符,該型別的視窗是可以獲取互動事件的,具體原因待查。

TYPE_SYSTEM_ALERT

TYPE_SYSTEM_ALERT 型別的視窗可以顯示在其它 APP 的上面,但不能顯示在鎖屏的上面,所以 PASS。

TYPE_SYSTEM_OVERLAY

TYPE_SYSTEM_OVERLAY 型別的視窗可以顯示在所有其它視窗的上面,包括鎖屏,而且不會影響它下面視窗的互動事件響應,但是該屬性視窗不能獲得焦點,無法進行互動(如果該視窗可以獲取焦點,那麼就可以用來抓取使用者的鎖屏密碼,出於安全考慮,系統是不會允許的),所以只能用來簡單的展示內容,如果需要互動的鎖屏彈窗,那麼該屬性 PASS。

TYPE_SYSTEM_ERROR

在原生 ROM 5.1 下試驗是可以顯示出來的,但根據註釋來看(appear on top of everything they can)不是在所有情況下都可以顯示在鎖屏上面的,而且像 MIUI 和 Flyme 等 ROM 預設是遮蔽浮窗許可權的,考慮到這點,利用 WindowManager 新增浮窗的方式實現鎖屏彈窗的方案基本 PASS。

使用 Activity 的方式實現

首先需要對 Activity 進行如下設定

其中最主要也是必須要設定的就是:FLAG_SHOW_WHEN_LOCKED,顧名思義就是鎖屏下顯示該 Activity。而其它幾個 Flag 包括:解鎖、保持螢幕常亮、點亮螢幕可以根據具體的需求選擇設定。

在 AndroidManifest.xml 中宣告 Activity

同樣該 Activity 也需要在 AndroidManifest.xml 中宣告,宣告時需注意新增 android:excludeFromRecents="true" 屬性,是為了將該 Activity 從最近任務列表中去除,否則使用者會覺得很奇怪。還有因為這個 Activity 會整個蓋在鎖屏上面,而且就算設定成背景透明,鎖屏介面也不會顯示在下面(系統主要是出於安全考慮),所以需要考慮下該 Activity 的背景,這裡為了顯示不要太突兀將主題設為桌布。

啟動 Activity

由於該 Activity 是為了在鎖屏的情況下顯示的,所以啟動 Activity 時不要忘了判斷手機是否處於鎖屏狀態,可以通過下面這種方式判斷鎖屏狀態:

相關文章