標籤:開始 狀態 yguard word err 查看 通過 forward alt
很多人都知道如何去實現一個簡單的浮窗,但是卻很少有人去深入的研究背後的流程機制,由於項目中浮窗互動比較複雜,遇到了些坑查看了很多資料,故總結浮窗涉及到的知識點:
- 視窗層級關係(浮窗是如何“浮”的)?
- 浮窗有哪些限制,如何越過使用者授權實現浮窗功能?
- 視窗與使用者輸入系統(Activity是如何接收到touch事件?)。
本章我們來研究第一個問題:浮窗為何會浮。 浮窗之所以叫浮窗,是因為它能懸浮於應用或者桌面視窗之上,能脫離Activity而存在。為了研究其中區別,我們先來看看我們最熟悉的Activity是怎麼顯示出來的。
Activity是怎麼顯示出來的?
要弄清這個問題答案,我們先從Activity的setContentView()這個方法的源碼開始找起,在Activity中看到setCententView的源碼:
public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initWindowDecorActionBar(); }
getWindow是返回返回Activity的mWindow變數,指向一個Window的對象,Window是一個抽象類別,這裡返回的是PhoneWindow對象(PhoneWindow是Window的子類),PhoneWindow中有一個DecorView對象,decorView成員,這是一個FrameLayout,setContentView的子布局最終會添加到decorView中,這個decorView就是當前視窗的根視圖,這個根視圖是如何最終被繪製出來的?在ActivityThread中有這樣一段代碼:
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION; l.softInputMode |= forwardBit; if (a.mVisibleFromClient) { a.mWindowAdded = true; wm.addView(decor, l); }
這個decorView,最終會被WindowManager.addView添加到繪製系統中,並類型是WindowManager.LayoutParams.TYPE_BASE_APPLICATION,這個參數決定了要繪製的視窗的z軸層次,為了避免思維棧過深,這裡就不貼出詳細的源碼跟蹤過程了,直接給結論。
先來看看Activity和window的關係:
再來window和View的關係:
Activity視窗顯示過程:
說Activity是怎麼顯示出來的,其實是說Activity管理的View是怎麼顯示出來的。最後再來總結一下:
一、Activity通過setContentView設定的視圖是添加到PhoneWindow的根視圖decor中。
二、Window是一個抽象的概念,Window關了了一個View(根視圖),最終被WindowManager管理的還是一個View(根視圖)和它的LayoutParams,視圖繪製重新整理都是通過WindowManager(WindowManagerGlobal)與WindowManagerServiceIPC互動調用底層繪製的。
三、Activity是四大組件中唯一和表單緊密聯絡的組件(這是為什麼會有初學者把Activity直接理解為繪製介面的原因),所有掌管的視圖只不過是一種window和Dialog、Toast、牆紙所掌管的Window類型不一樣。
浮窗為什麼會“浮”?
上面講到Activity的顯示過程其實已經揭示了通用介面的顯示過程,浮窗的顯示過程更為簡單:
做過浮窗的同學應該都明白了,為啥浮窗能脫離Activity而顯示,本質上我們是把一個View交給WindowManager來管理了,LayoutParams.type類型決定了這個View顯示視窗的類型,不同類型顯示的視窗層次(z軸)是不一樣的。大方面來講可以分為應用視窗(APPLICATION_WINDOW)、子視窗(SUB_WINDOW)、系統視窗(SYSTEM_WINDOW)三種類型,應用視窗z軸範圍是1~99,子視窗的範圍是1001~1999,系統視窗是(2000~2999),所以要實現浮動視窗我們只能在系統視窗範圍中實現。
| 類型 |
常量範圍 |
子類 |
常量值 |
說明 |
例子 |
| APPLICATION_WINDOW |
1~99 |
TYPE_BASE_APPLICATION |
1 |
|
|
| |
|
TYPE_APPLICATION |
2 |
應用視窗 |
大部分的應用程式視窗 |
| |
|
TYPE_APPLICATION_STARTING |
3 |
應用程式的Activity顯示之前由系統顯示的視窗 |
|
| |
|
LAST_APPLICATION_WINDOW |
99 |
|
|
| SUB_WINDOW |
1000~1999 |
FIRST_SUB_WINDOW |
1000 |
|
|
| |
|
TYPE_APPLICATION_PANEL |
1000 |
顯示在母視窗之上,遮擋其下面的應用視窗。 |
|
| |
|
TYPE_APPLICATION_MEDIA |
1001 |
顯示在母視窗之下,如果應用視窗不挖洞,即不可見。 |
SurfaceView,在小視窗顯示時設為MEDIA, 全螢幕顯示時設為PANEL |
| |
|
TYPE_APPLICATION_SUB_PANEL |
1002 |
|
|
| |
|
TYPE_APPLICATION_ATTACHED_DIALOG |
1003 |
|
|
| |
|
TYPE_APPLICATION_MEIDA_OVERLAY |
1004 |
用於兩個SurfaceView的合成,如果設為MEDIA,則上面的SurfaceView 擋住下面的SurfaceView |
|
| SYSTEM_WINDOW |
2000~2999 |
TYPE_STATUS_BAR |
2000 |
頂部的狀態列 |
|
| |
|
TYPE_SEARCH_BAR |
2001 |
搜尋視窗,系統中只能有一個搜尋視窗 |
|
| |
|
TYPE_PHONE |
2002 |
電話視窗 |
|
| |
|
TYPE_SYSTEM_ALERT |
2003 |
警告視窗,在所有其他視窗之上顯示 |
電量不足提醒視窗 |
| |
|
TYPE_KEYGUARD |
2004 |
鎖定畫面 |
|
| |
|
TYPE_TOAST |
2005 |
短時的文字提醒小視窗 |
|
| |
|
TYPE_SYSTEM_OVERLAY |
2006 |
沒有焦點的浮動視窗 |
|
| |
|
TYPE_PRIORITY_PHONE |
2007 |
緊急電話視窗,可以顯示在屏保之上 |
|
| |
|
TYPE_SYSTEM_DIALOG |
2008 |
系統資訊快顯視窗 |
比如SIM插上後彈出的電訊廠商資訊視窗 |
| |
|
TYPE_KEYGUARD_DIALOG |
2009 |
跟KeyGuard綁定的彈出對話方塊 |
鎖屏時的滑動解鎖視窗 |
| |
|
TYPE_SYSTEM_ERROR |
2010 |
系統錯誤提示視窗 |
ANR 視窗 |
| |
|
TYPE_INPUT_METHOD |
2011 |
IME視窗,會擠占當前應用的空間 |
|
| |
|
TYPE_INPUT_METHOD_DIALOG |
2012 |
彈出的IME視窗,不會擠占當前應用視窗空間,在其之上顯示 |
|
| |
|
TYPE_WALLPAPER |
2013 |
牆紙 |
|
| |
|
TYPE_STATUS_BAR_PANEL |
2014 |
從狀態條下拉的視窗 |
|
| |
|
TYPE_SECURE_SYSTEM_OVERLAY |
2015 |
只有系統使用者可以建立的OVERLAY視窗 |
|
| |
|
TYPE_DRAG |
2016 |
浮動的可拖動視窗 |
360安全衛士的浮動精靈 |
| |
|
TYPE_STATUS_BAR_PANEL |
2017 |
|
|
| |
|
TYPE_POINTER |
2018 |
游標 |
|
| |
|
TYPE_NAVIGATION_BAR |
2019 |
|
|
| |
|
TYPE_VOLUME_OVERLAY |
2020 |
音量大小視窗 |
|
| |
|
TYPE_BOOT_PROGRESS |
2021 |
啟動進度,在所有視窗之上 |
|
| |
|
TYPE_HIDDEN_NAV_CONSUMER |
2022 |
隱藏的導覽列 |
|
| |
|
TYPE_DREAM |
2023 |
屏保動畫 |
|
| |
|
TYPE_NAVIGATION_BAR_PANEL |
2024 |
Navigation bar 彈出的視窗 |
比如說應用收集欄 |
| |
|
TYPE_UNIVERSAL_BACKGROUND |
2025 |
|
|
| |
|
TYPE_DISPLAY_OVERLAY |
2026 |
用於類比第二顯示裝置 |
|
| |
|
TYPE_MAGNIFICATION |
2027 |
用於放大局部 |
|
| |
|
TYPE_RECENTS_OVERLAY |
2028 |
當前應用視窗,多使用者情況下只顯示在使用者節目 |
Android 浮窗開發之視窗層級