「Android研習社」不使用Activity如何添加一個View

WindowManger詳解

更新java

直播回放已上傳B站,請戳連接食用:www.bilibili.com/video/av747…android

社羣正式開放git

Android研習社-技術交流羣,已經正式對外開放了,加wx:s419505080s,拉你進羣github

總體方案

在Service中經過WindowManger添加View的方式來把UI界面顯示出來bash

業務場景

具體場景app

  • IQOO手機,遊戲輔助

這種場景可否使用Activity方式來作ide

使用activity會對下層window產生阻塞,而使用WindowManager添加view的方式則不會阻塞佈局

WindowManger簡介

WindowManger是普通App進程用來與系統服務(WindowMangerService)通訊的一個接口。 獲取WindowManger實例對象的方法是使用Context.getSystemService(Context.WINDOW_SERVICE優化

如何使用

  1. 添加權限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
複製代碼
  1. 手動引導開啓顯示在其餘應用上層spa

  2. 獲取WindowManger並添加View

WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); //獲取系統服務
windowManager.addView(myView, p);
複製代碼
  1. 不使用時移除View

WindowManager使用詳解

WindowManger

  1. 添加View :addView()

    注意 同一個window,只能添加一個View,添加多個View會報出如下異常

Caused by: java.lang.IllegalStateException: View android.widget.RelativeLayout{b3a2c6a V.E...... ......I. 0,0-0,0 #7f070081 app:id/rl_root} has already been added to the window manager.
複製代碼
  1. 移除View : remoview()

因爲同一個View只能添加一個View,因此,要想在已添加View的Window中再添加View,必須先移除已添加的View

  1. 更新佈局屬性 :updateViewLayout(view,params)

經過對第二個參數WindowManger.LayoutParams的屬性設置後,調用本方法纔會使這些屬性生效

WindowManger.LayoutParms

WindowManger.LayoutParms 實際上是ViewGrop.LayoutParms的子類對象,因此View設置LayoutParams時能夠直接設置

  1. 控制是否能夠響應觸摸事件

    layoutParams.type

    • FLAG_NOT_TOUCHABLE
    • FLAG_NOT_TOUCH_MODAL
  2. 控制window的顯示層級

    layoutParams.type

    • TYPE_TOAST(Andorid 5.0及如下系統版本可規避權限問題)
    • TYPE_APPLICATION_WINOW (應用層Winow等級)
    • TYPE_PRIORTY_PHONE (系統層Window等級)
  3. 控制view的顯示範圍

    layoutParams.flags

    • FLAG_FULLSCREEN
    • FLAG_LAYOUT_IN_SCREEN
  4. 控制view的顯示位置
    • layoutParams.width
    • layoutParams.height

示例項目

github.com/happyburgla…

還要注意哪些問題?

  1. 使用單獨進程,避免影響主業務功能
  2. 提高進程優先級,避免被Kill
    • 使用前臺服務
    • 1像素保活
    • 綁定系統服務

    提示:可經過oom_adj查看某個進程的進程等級

  3. 要對服務被Kill後的重啓邏輯進行處理

源碼淺析

因爲時間關係,這裏咱們只對相關源碼進行一個簡單的介紹,先來看下相關的類

WindowManger這個類,其實只是一個接口,用來溝通普通應用進程和系統服務WindowMangerservice

咱們在上面的使用中也看到了,獲取WindowManger這個類的實例對象,是經過Context.getSystemServer(Context.WINDOW_SERICE)獲取的

經過上面的UML類圖咱們也能夠看到,其實WindowManger是一個接口,而它的真正的實例對象是WindowMangerImpl這個類

WindowMangerImpl又把具體的添加View的工做封裝到了WindowManagerGlobal中來操做,這個類中又涉及到了另一個重要的類--Display,這個類主要是封裝了一些顯示相關的信息,好比window的邏輯寬顯示數據(logical displays)和物理顯示數據(physical displays)

什麼是logical displays

源碼中對此解釋是,邏輯顯示不必定表明特定的物理顯示設備,例如內置屏幕或外接顯示器。 邏輯上的內容根據設備的不一樣,顯示屏能夠顯示在一個或多個物理顯示屏上

什麼是physical displays

就是Android設備屏幕的真實的Displays數據,好比你的手機是4K的屏幕(physical displays),可是廠商爲了進行一些優化工做(好比省電?)能夠把顯示尺寸(logical displays)設置爲1920* 1080

相關文章
相關標籤/搜索