Android無許可權彈懸浮窗適配8.0
背景
相信大家在開發的過程中肯定會遇到建立懸浮框需要許可權的問題,如果不申請許可權會出現以下錯誤:
token null is not valid; is your activity running?
或者類似的錯誤,這類的文章在百度上面經常可以檢視到,但是基本上都是停留在Android6.0以下的,文章比較老舊。隨著6.0之後的巨大變化,主要是搞版本之後Google開啟了嚴苛模式,使使用者的隱私更加的難獲取,對某些敏感手機資訊,我們不僅需要在AndroidMainfest.xml配置檔案中申請許可權,還要在程式碼中進行動態許可權的申請,我們今天討論的懸浮框許可權就是其實的一個,今天我分享的這篇文章最高適配到最新的Android8.0,測試的手機包含了國內外的各大廠商的大部分主流手機。Demo最低適配到api 10,最高適配api27。
思路
我們都清楚Android碎片的化的嚴重,但其實也有個大致版本的分割線,為了迎合此文,我們大致把手機大致分為3個區間,其實19,22,16的版本都具有很明顯的變換。
- api<19 ,android 4.4以前的
- api>22,api<26, Android4.4與8.0之間的
- api>=26 最新版本的Android手機
功能
1.喚醒一個懸浮框
2.點選底部虛擬按鈕,懸浮框消失不見。
3.監聽懸浮框的按鈕
技術實現
前提:
- 儘量不在配置檔案中申請許可權。
- 儘量不在當前APP申請動態許可權。
- 如果繞不過去前兩者,則引導使用者開啟許可權。
核心程式碼:
其中最關鍵的是圈中程式碼,對type進行的適配。有興趣的可以下載Demo在研究研究,該篇文章以研究為主。
測試機型
廠商 | 型號 | Android版本號 | 系統 | 配置靜態許可權 | 動態懸浮框開關 | targetSdkVersion | 互動成功 |
---|---|---|---|---|---|---|---|
SAMSUNG | 三星Nexus | 4.3(18) | 4.3 | 有 | 無 | 無 | Y |
SAMSUNG | 三星Note3 | 5.0(21) | 5.0 | 無 | 無 | 無 | Y |
SAMSUNG | 三星 G9300 | 7.0(24) | 7.0 | 無 | 無 | 無 | Y |
MIUI | 小米4 | 6.0.1(23) | MIUI 8.5 | 無 | 無 | 無 | Y |
MIUI | 小米3 | 4.4.4(19) | MIUI 9.2 | 有 | 有 | 無 | Y |
MIUI | 小米 note | 7.0(24) | MIUI 8.7 | 有 | 有 | 無 | Y |
MIUI | 小米 6 | 7.1.1(25) | MIUI 9.2 | 無 | 有 | 無 | Y |
魅族 | MEIZU MX5 | 5.0.0(21) | Flyme 6.2 | 無 | 無 | 無 | Y |
HTC | HTC A9W | 7.0(24) | 7.0 | 無 | 無 | 無 | Y |
Nexus 5 | 5.1.1(22) | 5.1.1 | 無 | 22 | Y | ||
華為 | Nexus 6P | 8.0.0(26) | 8.0.0 | 無 | 無 | 無 | Y |
Pixel XL | 8.0.0(26) | 8.0.0 | 無 | 無 | <=22 | 3秒之後消失 | |
Pixel XL | 8.0.0(26) | 8.0.0 | 有 | 有 | api>22 | Y | |
努比亞 | Nubia 4.0 | 5.1.1(22) | nubia v4.0 | 無 | 無 | Y | |
華為 | 華為 P9 | 7.0.0 | 7.0.0(25) | 有 | 有 | api>22 | Y |
華為 | 華為 Nova 2s | 8.0.0(26) | EMUI 8.0 | 無 | 無 | <=22 | 3秒之後消失 |
華為 | 華為 Nova 2s | 8.0.0(26) | EMUI 8.0 | 有 | 有 | api>22 | Y |
聯想 | Lenovo K920 | 4.4.2(19) | 4.4.2 | 無 | 無 | 無 | Y |
OPPO | colorOs v1.2.0 | 4.3(19) | 4.3 | 有 | 無 | 無 | Y |
OPPO | OPPO R11 | 7.1(25) | 7.1 | 無 | 無 | 無 | Y |
vivo | vivo Y55A | 6.0.1(23) | 6.0.1 | 無 | 有 | 無 | Y |
vivo | vivo X9 | 7.1.1(23) | 7.1.1 | 無 | 有 | 無 | Y |
靜態許可權申請:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
結論:
API Level | 廠商 | targetSdkVersion | 靜態許可權 | 動態許可權 | WindowManager |
---|---|---|---|---|---|
api<19(4.3) | All | - | 需要 | - | TYPE_PHONE |
19<=api<26 | All(小米,vivo除外) | - | 不需要 | 不需要 | TYPE_TOAST |
小米 | - | 需要 | 需要 | TYPE_PHONE |
|
vivo | - | 不需要 | 需要 | TYPE_PHONE |
|
api>=26(8.0) | All | version>=23 | 需要 | 需要 | TYPE_APPLICATION_OVERLAY |
api>=26(8.0) | All | version<23 | 不需要 | 不需要 | TYPE_TOAST |
注:
* 優先使用WindowManager.LayoutParams.TYPE_TOAST,但4.4版本之前無法接收事件也即無法互動, 7.1 版本後源app失去焦點時有個定時器自動隱藏掉這個 Toast Window
- 適配api>=26的,且
targeSdkVersion>=23
不僅需要靜態配置,還需要動態配置懸浮框許可權,type=WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
。如果不在清單中申請靜態配置,無法開啟動態啟動的懸浮框許可權;targeSdkVersion<23
,如果依據不增加任何許可權,懸浮框出現3秒之後自動消失,type=WindowManager.LayoutParams.TYPE_TOAST
,這個不一定,少部分機型是不會消失的,比如華為代工的nexus 6p - MIUI V5的以上的手機根據版本號與機型進行調整。少數是不需要配置許可權的,但是一定需要動態開啟懸浮框許可權,建議都進行靜態配置,並且呼叫配置懸浮框許可權。
- 如果打開了靜態控制權限,19<=api<26 的情況下,則動態申請一定要開啟,
type=WindowManager.LayoutParams.TYPE_PHONE
; - vivo手機需要動態開啟懸浮框許可權。
答疑:
1.為什麼4.4之下使用 TYPE_TOAST
沒有效果,而大於等於4.4就有效果了?
低版本中使用這個引數只能夠進行展示效果,不能被點選,而高版本中在這個引數上面加了一段邏輯,沒錯。。。就可以點選了,可以獲取焦點的邏輯,系統已經幫我們做了。因為系統幫我們加了兩個設定:
2.為什麼在8.0上面會有個3秒自動消失的結果?
因為Google預留這個WindowManager.LayoutParams.TYPE_TOAST本質不是給開發者用的,而是給手機廠商用的,結果沒想到國內懸浮框的需求量巨大,想到了這麼一個後門來繞過敏感許可權的申請,所以在7.1之後就慢慢的廢除了,在7.1版本增加了定時消失的功能,並且該定時沒公開。
3.為什麼小米和vivo都需要動態配置開啟懸浮框許可權?
沒有為什麼,大廠就是會玩,自己強行加上了這個功能。MIUI 5之前是可以無許可權開啟的,高版本後就不行了,但有個別型號是可以不需要開通許可權的,比如小米4W;vivo就更奇葩了,無論有沒有增加許可權,但是一定要手動開啟懸浮框的許可權 。
4.為什麼使用type=WindowManager.LayoutParams.TYPE_PHONE
需要在配置檔案中增加許可權?
這個不一定,除了vivo這個奇葩定製除外,絕大部分都要遵循這個規則。
最後
根據版本迭代趨勢,我還是建議大家遵循Google大法的開發規則,老老實實的申請許可權。(部分圖片來源於網路)
Demo地址是:https://github.com/LiuLei0571/FloatDemo.git,麻煩各位看官給個小星星==