帶你從app入口到對話框到懸浮窗剖析android-UI層級系列一

起源:前幾天一個網友問我,他有個需求在來電的時候彈窗提示信息—使用WindowManager.addView(),但是遇到360之類的系統安全APP也會彈窗提示,會被其他的彈窗蓋住,使用TYPE_SYSTEM_ALERT類型過後,有的手機會有的機器不會,然後我突然想起既然大都是這種方式添加的彈窗,我們能不能獲取到其他APP的彈窗View呢,如果能獲取到,那麼可以將之移除 *_*,哇咔咔咔~太壞了。

經過幾天的資料查找和源碼分析,重點查看了android的窗口管理方面(涉及到的類和接口:ViewManager,WindowManager,WindowManagerImpl,WindowManagerPolicy,WindowManager,WindowManager.LayoutParams,CompatModeWrapper,DecorView,ViewRootImpl,Window,PhoneWindow,PolicyManager,ActivityThread等等還有其他很多),還是找到一些蛛絲馬跡。

當然,這篇文章的重點不在於最終是否能將其他APP的彈窗給刪除掉,而是可以一種學習方式,有所想有所學。從這個思路去探測源碼內部的世界到底怎麼樣~~

好了,接下來開始踏步走...

既然是UI層級,當然就會涉及到覆蓋問題。你想想,從系統啓動到桌面到APP啓動,android的UI變化等等,以及我們APP的layout裏面,一層一層的,android是如何控制的呢?還有你看到的狀態欄StatusBar,狀態欄下滑出現的系統抽屜(notifications欄列表之類的),以及一些沒有實體鍵的手機的虛擬按鍵之類的。

先上幾張圖簡單看一下...



先去吃個飯,回來繼續.....


---------------------------吃完了-----------------------------繼續---------------------------------


接着再介紹一些後續需要涉及到的東西:android窗口類型字段,位於android.view.WindowManager.LayoutParams中,這是一個靜態內部類,繼承自ViewGroup.LayoutParams,用於WindowManager.addView()添加的view佈局。其中有一個字段public int type,這個字段表示的就是當前添加的View是屬於什麼類型的窗口(關於窗口,後續內容會依次提到相關知識)。

<span style="white-space:pre">	</span>public int type;
<span style="white-space:pre">	</span>/**
         * Start of window types that represent normal application windows.
         */
        public static final int FIRST_APPLICATION_WINDOW = 1;
        
        /**
         * Window type: an application window that serves as the "base" window
         * of the overall application; all other application windows will
         * appear on top of it.
         */
        public static final int TYPE_BASE_APPLICATION   = 1;
        
        /**
         * Window type: a normal application window.  The {@link #token} must be
         * an Activity token identifying who the window belongs to.
         */
        public static final int TYPE_APPLICATION        = 2;
    
        /**
         * Window type: special application window that is displayed while the
         * application is starting.  Not for use by applications themselves;
         * this is used by the system to display something until the
         * application can show its own windows.
         */
        public static final int TYPE_APPLICATION_STARTING = 3;
    
        /**
         * End of types of application windows.
         */
        public static final int LAST_APPLICATION_WINDOW = 99;
    
        /**
         * Start of types of sub-windows.  The {@link #token} of these windows
         * must be set to the window they are attached to.  These types of
         * windows are kept next to their attached window in Z-order, and their
         * coordinate space is relative to their attached window.
         */
        public static final int FIRST_SUB_WINDOW        = 1000;
    
        /**
         * Window type: a panel on top of an application window.  These windows
         * appear on top of their attached window.
         */
        public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;
    
        /**
         * Window type: window for showing media (e.g. video).  These windows
         * are displayed behind their attached window.
         */
        public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;
    
        /**
         * Window type: a sub-panel on top of an application window.  These
         * windows are displayed on top their attached window and any
         * {@link #TYPE_APPLICATION_PANEL} panels.
         */
        public static final int TYPE_APPLICATION_SUB_PANEL = FIRST_SUB_WINDOW+2;

        /** Window type: like {@link #TYPE_APPLICATION_PANEL}, but layout
         * of the window happens as that of a top-level window, <em>not</em>
         * as a child of its container.
         */
        public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
        
        /**
         * Window type: window for showing overlays on top of media windows.
         * These windows are displayed between TYPE_APPLICATION_MEDIA and the
         * application window.  They should be translucent to be useful.  This
         * is a big ugly hack so:
         * @hide
         */
        public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4;
    
        /**
         * End of types of sub-windows.
         */
        public static final int LAST_SUB_WINDOW         = 1999;
        
        /**
         * Start of system-specific window types.  These are not normally
         * created by applications.
         */
        public static final int FIRST_SYSTEM_WINDOW     = 2000;
    
        /**
         * Window type: the status bar.  There can be only one status bar
         * window; it is placed at the top of the screen, and all other
         * windows are shifted down so they are below it.
         */
        public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
    
        /**
         * Window type: the search bar.  There can be only one search bar
         * window; it is placed at the top of the screen.
         */
        public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
    
        /**
         * Window type: phone.  These are non-application windows providing
         * user interaction with the phone (in particular incoming calls).
         * These windows are normally placed above all applications, but behind
         * the status bar.
         */
        public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
    
        /**
         * Window type: system window, such as low power alert. These windows
         * are always on top of application windows.
         */
        public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
        
        /**
         * Window type: keyguard window.
         */
        public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
        
        /**
         * Window type: transient notifications.
         */
        public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
        
        /**
         * Window type: system overlay windows, which need to be displayed
         * on top of everything else.  These windows must not take input
         * focus, or they will interfere with the keyguard.
         */
        public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
        
        /**
         * Window type: priority phone UI, which needs to be displayed even if
         * the keyguard is active.  These windows must not take input
         * focus, or they will interfere with the keyguard.
         */
        public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
        
        /**
         * Window type: panel that slides out from the status bar
         */
        public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
    
        /**
         * Window type: dialogs that the keyguard shows
         */
        public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
        
        /**
         * Window type: internal system error windows, appear on top of
         * everything they can.
         */
        public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
        
        /**
         * Window type: internal input methods windows, which appear above
         * the normal UI.  Application windows may be resized or panned to keep
         * the input focus visible while this window is displayed.
         */
        public static final int TYPE_INPUT_METHOD       = FIRST_SYSTEM_WINDOW+11;

        /**
         * Window type: internal input methods dialog windows, which appear above
         * the current input method window.
         */
        public static final int TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12;

        /**
         * Window type: wallpaper window, placed behind any window that wants
         * to sit on top of the wallpaper.
         */
        public static final int TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13;

        /**
         * Window type: panel that slides out from over the status bar
         */
        public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;

        /**
         * Window type: secure system overlay windows, which need to be displayed
         * on top of everything else.  These windows must not take input
         * focus, or they will interfere with the keyguard.
         *
         * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the
         * system itself is allowed to create these overlays.  Applications cannot
         * obtain permission to create secure system overlays.
         * @hide
         */
        public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;

        /**
         * Window type: the drag-and-drop pseudowindow.  There is only one
         * drag layer (at most), and it is placed on top of all other windows.
         * @hide
         */
        public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;

        /**
         * Window type: panel that slides out from under the status bar
         * @hide
         */
        public static final int TYPE_STATUS_BAR_SUB_PANEL = FIRST_SYSTEM_WINDOW+17;

        /**
         * Window type: (mouse) pointer
         * @hide
         */
        public static final int TYPE_POINTER = FIRST_SYSTEM_WINDOW+18;

        /**
         * Window type: Navigation bar (when distinct from status bar)
         * @hide
         */
        public static final int TYPE_NAVIGATION_BAR = FIRST_SYSTEM_WINDOW+19;

        /**
         * Window type: The volume level overlay/dialog shown when the user
         * changes the system volume.
         * @hide
         */
        public static final int TYPE_VOLUME_OVERLAY = FIRST_SYSTEM_WINDOW+20;

        /**
         * Window type: The boot progress dialog, goes on top of everything
         * in the world.
         * @hide
         */
        public static final int TYPE_BOOT_PROGRESS = FIRST_SYSTEM_WINDOW+21;

        /**
         * Window type: Fake window to consume touch events when the navigation
         * bar is hidden.
         * @hide
         */
        public static final int TYPE_HIDDEN_NAV_CONSUMER = FIRST_SYSTEM_WINDOW+22;

        /**
         * End of types of system windows.
         */
        public static final int LAST_SYSTEM_WINDOW      = 2999;


英文註釋都不難,很好理解。比較常用的,也是我們這個文章分析可能要說到的:
TYPE_BASE_APPLICATION[DecorView被添加的時候用的這種類型] 

TYPE_APPLICATION[Dialog被添加的使用用的這種類型]

TYPE_STATUS_BAR [StatusBar狀態欄屬於這個類型]

TYPE_SEARCH_BAR [搜索欄屬於這個類型]

TYPE_PHONE [來電界面用的這個類型,需要說明的是這個類型通常位於其他APP之上但是在statusbar之下]

TYPE_SYSTEM_ALERT [低電量提示屬於這個類型]

TYPE_KEYGUARD [鍵盤屬於這個類型]

TYPE_TOAST[Toast提示屬於這個類型]

TYPE_SYSTEM_DIALOG[這個類型和TYPE_STATUS_BAR_PANEL的描述差不多,英文差沒區分出來]

TYPE_SYSTEM_ERROR[這個類型描述說的是系統錯誤對話框,我認爲程序crash的對話框應該屬於這個類型]

TYPE_STATUS_BAR_PANEL[這個類型和TYPE_STATUS_Dialog的描述差不多,英文差沒區分出來,我覺得這個更像是狀態欄下拉滑出來的面板用的類型,啊啊啊啊啊啊啊啊]

大概就說這麼多,接下來作個流程梳理。

本人水平有限,或多或少都肯定存在部分不準確的地方,若有發現請指出,我好修改。

聯繫方式:

QQ:190951132請備註“CSDN博客建議”

email:[email protected]


隨風碼磚自由式方向~~

追逐雷和閃電的力量~~~~~


補充:這裏看到一個更詳細的屬性分析,http://blog.csdn.net/wang_shaner/article/details/8596380 感謝作者!~





發佈了31 篇原創文章 · 獲贊 13 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章