1. 程式人生 > >Android 去除“Viewing full screen”彈窗

Android 去除“Viewing full screen”彈窗

這篇文章可結合Android9.0 完全隱藏導航欄、狀態列

Android應用設定沉浸式全屏時,一般會使用到如下的Flag:

View.SYSTEM_UI_FLAG_IMMERSIVE或View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY以及View.SYSTEM_UI_FLAG_HIDE_NAVIGATION。

使用了以上的Flag組合後呢,系統會彈窗提示使用者當前是全屏顯示,彈框如下:

大標題是Viewing full screen,小字部分是Swipe down from the top to exit full screen.”的提示,即從上往下滑動可退出全屏。

這個提示是友好的,但是大多數情況下,這個提示框可能因為擋住了要顯示的內容而不滿足全屏要求。那麼如何去除“Viewing full screen”彈窗呢?要去除這個彈框,就先要從這個彈框出現的位置開始分析。

在/framework/base/servics/core/java/com/server/policy/ImmersiveModeConfirmation.java中有如下函式:

  • 1、首先看看這個isImmersiveMode引數,系統是如何判斷當前是否為沉浸式的呢?

【/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java】的函式updateSystemBarsLw:

vis就是來判斷顯示介面設定給systemUiVisibility 的flag的。看看isImmersiveMode:

也就是如果systemUiVisibility設定了SYSTEM_UI_FLAG_HIDE_NAVIGATION + SYSTEM_UI_FLAG_IMMERSIVE、SYSTEM_UI_FLAG_IMMERSIVE_STICKY中的一個或兩個,且存在NavigationBar,那麼就是沉浸式模式。

  • 2、再看一下mHandler中是如何處理H.SHOW訊息的

再看看handleShow函式:

噹噹噹,這個時候那個彈窗就顯示出來了。

解決方案

既然我們要解決彈窗顯示的問題,那麼根據以上顯示彈窗的分析,方案就來了。

①mHandler中接收到訊息後不做show confirmation的操作;

②彈窗顯示後就呼叫其隱藏的操作;

③不傳送顯示彈框的訊息SHOW到mHandler中。

接下來分析一下這三種方案:

  • ①mHandler中接收到訊息後不做show confirmation的操作

因為這個檔案是framework層的,所以就是要修改系統原始碼。而且一旦接收到訊息後不做show confirmation的操作,那麼系統中的所有應用沉浸式全屏的時候都不會彈出提示框,而非當前的沉浸式全屏引用。這樣的需求一般不是我們所需要的,不過當然也是一種方案,這種方案對於看不到系統原始碼的開發者來說並不友好。修改方案如下:

  • ②彈窗顯示後就呼叫其隱藏的操作

其實從剛剛的原始碼分析可以看到,因此彈框,也就是handleHide裡做的事。而這個handleHide被執行到,就需要給mHandler傳送HIDE訊息。But, 傳送HIDE訊息的就兩處:

第一處:這個要螢幕沉浸式顯示的模式變更後才會執行(即退出沉浸式模式)。

第二處:很明顯,這是和VR相關的,我們一般用不到。

那麼,我們可以試試不通過傳送訊息,而是直接執行handleHide裡的操作呀!!!

好的,這個函式是私有的。如果APP想呼叫,可以通過反射。=-=,這個類好像是不對外的吧,反正反射也沒有啥用。。。親測沒成功。。。。

  • ③不傳送顯示彈框的訊息SHOW到mHandler中

終極方法終於來了!!!

在ImmersiveModeConfirmation.java檔案中,有且僅有一處傳送了SHOW訊息:

沒錯!!就是這個函式。那麼為了不傳送SHOW訊息,所以就要if條件不滿足。

通過分析,這個navBarEmpty條件最容易被APP修改,我們只要讓這個值為true就好了。

那麼來看看這個引數navBarEmpty的由來:

【/frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java】

函式updateSystemBarsLw:

來看看isNavBarEmpty是個什麼鬼:

沒錯,這要這個isNavBarEmpty返回true,就不會show 彈出了。

從這個函式可以看到,只要在應用介面顯示的systemUiVisibility引數中加上這三個FLAG那麼這個函式就會返回true。從而那個Viewing Full Screen的彈窗也不會出現了(親測有用)。

修改如下:

WindowManager.LayoutParams lp = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
lp.systemUiVisibility = View.STATUS_BAR_DISABLE_HOME | View.STATUS_BAR_DISABLE_BACK | View.STATUS_BAR_DISABLE_RECENT |
              View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |View.SYSTEM_UI_FLAG_FULLSCREEN |
              View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
               View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;

這種方法,並不是對所有應用起作用。而僅僅是對自己的沉浸式全屏應用其作用,當應用退出時,這個彈窗還是對其他應用有效的。o(* ̄︶ ̄*)o