SystemUI 怎样给应用提供禁止下拉状态栏接口?
不积跬步无以至千里
在系统开发的时候常常会遇到某些场景是不让下拉状态栏的,因为上边会有一些控制开关,还有一些通知的跳转,这样就会规避到这个原则,比如开机向导中让你为了一些安全措施必须完成的某些步骤等等.
在这里系统其实已经为你提供了一个Api接口了,如下:
StatusBarManager mStatusBarManager = (StatusBarManager) context.getSystemService(Context.STATUS_BAR_SERVICE);
// Disable statusbar pull-down
mStatusBarManager.disable(StatusBarManager.DISABLE_EXPAND);
不过细心的童鞋点进Api中一看这个接口是@Hide的方法,因此对于一些三方的app是不让用的,这个方法好像反射也不行.那怎么办呢?咱们也不能把这个释放开啊,所以还是寻找其它解决办法.因此其实可以通过它控制的逻辑找出突破口.
其实有兴趣的同学可以看一下我另一篇文章就是对这api的追踪代码,文章链接如下:
https://blog.csdn.net/WDYShowTime/article/details/83782933
其中文章有对这个disable的调用是通过StatusBarManagerService,然后其实根本的控制是想用户通过这个Manager然后通过这个disable等各种操作对SystemUI中的下拉的状态栏进行控制,所以看一下这个控制到SystemUI以后是在目录如下:
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
/**
* State is one or more of the DISABLE constants from StatusBarManager.
*/
@Override
public void disable(int state1, int state2, boolean animate) {
animate &= mStatusBarWindowState != WINDOW_STATE_HIDDEN;
mDisabledUnmodified1 = state1;
mDisabledUnmodified2 = state2;
final int old1 = mDisabled1;
final int diff1 = state1 ^ old1;
mDisabled1 = state1;
...
其中你设置的disable的传递给了mDisabled1这个int值了,其中你会发现其中状态栏的面板会通过在这,目录如下:
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@Override
public boolean onTouchEvent(MotionEvent event) {
// Allow subclasses to implement enable/disable semantics
if (!panelEnabled()) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
Log.v(TAG, String.format("onTouch: all panels disabled, ignoring touch at (%d,%d)",
(int) event.getX(), (int) event.getY()));
}
return false;
}
其实可以看出当panelEnabled这个不可用的时候就return false,这个PanelBar是状态栏的父View,这样面板的下拉就被"消费"了.
其实看一下这个panelEnabled()的逻辑就和上边对应起来了,其实这边panelEnabled最终也是调用的StatusBar中的panelEnabled方法,目录如下:
vendor/mediatek/proprietary/packages/apps/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
public boolean panelsEnabled() {
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS;
}
因此,返回false的时候就拦截了,因此咱们这里可以通过某个值比如SystemProperties或者Settings.system中的数据库,或者某个应用的数据库等,咱们通过某个值来进行一个处理就行了,如下:
public boolean panelsEnabled() {
//[add] start
if (SystemProperties.getBoolean("persist.status.bar.enable", false)) {
return false;
}
// end
return (mDisabled1 & StatusBarManager.DISABLE_EXPAND) == 0 && !ONLY_CORE_APPS;
}
具体的逻辑你可以怎么进行判断你都可以,false的时候就会进行拦截不能下拉了.
重要的事说两边,其中关于上边的api的调用流程文章URL: https://blog.csdn.net/WDYShowTime/article/details/83782933