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组合后呢,系统会弹窗提示用户当前是全屏显示,弹框如下:

Android 去除“Viewing full screen”弹窗_第1张图片

大标题是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中有如下函数:

Android 去除“Viewing full screen”弹窗_第2张图片

  • 1、首先看看这个isImmersiveMode参数,系统是如何判断当前是否为沉浸式的呢?

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

Android 去除“Viewing full screen”弹窗_第3张图片

vis就是来判断显示界面设置给systemUiVisibility 的flag的。看看isImmersiveMode:

Android 去除“Viewing full screen”弹窗_第4张图片

也就是如果systemUiVisibility设置了SYSTEM_UI_FLAG_HIDE_NAVIGATION + SYSTEM_UI_FLAG_IMMERSIVE、SYSTEM_UI_FLAG_IMMERSIVE_STICKY中的一个或两个,且存在NavigationBar,那么就是沉浸式模式。

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

Android 去除“Viewing full screen”弹窗_第5张图片

再看看handleShow函数:

Android 去除“Viewing full screen”弹窗_第6张图片

当当当,这个时候那个弹窗就显示出来了。

解决方案

既然我们要解决弹窗显示的问题,那么根据以上显示弹窗的分析,方案就来了。

①mHandler中接收到消息后不做show confirmation的操作;

②弹窗显示后就调用其隐藏的操作;

③不发送显示弹框的消息SHOW到mHandler中。

接下来分析一下这三种方案:

  • ①mHandler中接收到消息后不做show confirmation的操作

因为这个文件是framework层的,所以就是要修改系统源码。而且一旦接收到消息后不做show confirmation的操作,那么系统中的所有应用沉浸式全屏的时候都不会弹出提示框,而非当前的沉浸式全屏引用。这样的需求一般不是我们所需要的,不过当然也是一种方案,这种方案对于看不到系统源码的开发者来说并不友好。修改方案如下:

Android 去除“Viewing full screen”弹窗_第7张图片

  • ②弹窗显示后就调用其隐藏的操作

其实从刚刚的源码分析可以看到,因此弹框,也就是handleHide里做的事。而这个handleHide被执行到,就需要给mHandler发送HIDE消息。But, 发送HIDE消息的就两处:

Android 去除“Viewing full screen”弹窗_第8张图片

Android 去除“Viewing full screen”弹窗_第9张图片

第一处:这个要屏幕沉浸式显示的模式变更后才会执行(即退出沉浸式模式)。

第二处:很明显,这是和VR相关的,我们一般用不到。

那么,我们可以试试不通过发送消息,而是直接执行handleHide里的操作呀!!!

Android 去除“Viewing full screen”弹窗_第10张图片

好的,这个函数是私有的。如果APP想调用,可以通过反射。=-=,这个类好像是不对外的吧,反正反射也没有啥用。。。亲测没成功。。。。

  • ③不发送显示弹框的消息SHOW到mHandler中

终极方法终于来了!!!

在ImmersiveModeConfirmation.java文件中,有且仅有一处发送了SHOW消息:

Android 去除“Viewing full screen”弹窗_第11张图片

没错!!就是这个函数。那么为了不发送SHOW消息,所以就要if条件不满足。

通过分析,这个navBarEmpty条件最容易被APP修改,我们只要让这个值为true就好了。

那么来看看这个参数navBarEmpty的由来:

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

函数updateSystemBarsLw:

Android 去除“Viewing full screen”弹窗_第12张图片

来看看isNavBarEmpty是个什么鬼:

Android 去除“Viewing full screen”弹窗_第13张图片

没错,这要这个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

你可能感兴趣的:(#,其他,沉浸式全屏)