前言
最近想写一个小应用,看到要模仿的那个应用,状态栏是拉不下来的,就好像锁屏应用不许下拉状态栏一样,
于是百度了好久,都说需要修改源代码,最后还是选择了简单的java实现。
这里说一下:
- statusbar是由StatusBarManager控制的,但是StatusBarManager安卓默认是不能使用的,这里需要曲线救国;
- 没错,救国方案就是java的反射机制!
- StatusBarManager的实现在4.2之后就发生了改变,但网上的文章都是4.2之前的,只能说部分能用,所以我写了这文章,hhh。
这里这里不多说,上代码:
public static final int DISABLE_EXPAND = 0x00010000;
public static final int DISABLE_EXPAND_LOW = 0x00000001;
public static final int DISABLE_NONE = 0x00000000;
private void unBanStatusBar() {
Object service = getSystemService("statusbar");
try {
Class<?> statusBarManager = Class.forName
("android.app.StatusBarManager");
Method expand = statusBarManager.getMethod("disable", int.class);
expand.invoke(service, DISABLE_NONE);
} catch (Exception e) {
e.printStackTrace();
}
}
private void setStatusBarDisable(int disable_status) {
Object service = getSystemService("statusbar");
try {
Class<?> statusBarManager = Class.forName
("android.app.StatusBarManager");
Method expand = statusBarManager.getMethod("disable", int.class);
expand.invoke(service, disable_status);
} catch (Exception e) {
unBanStatusBar();
e.printStackTrace();
}
}
private void banStatusBar() {
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
if (currentApiVersion <= 16) {
setStatusBarDisable(DISABLE_EXPAND_LOW);
} else {
setStatusBarDisable(DISABLE_EXPAND);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
调用时机,banStatusBar方法在onWindowFocusChanged方法调用,即在activity附着在window的时候调用,这个statusbar的disable必须再次设置为none(DISABLE_NONE),因为这个disable方法是全局的,必须没有除去,就算退出应用,状态栏也是不能下拉的,所以我这里选择在onPause方法设置none,代码如下:
public void onWindowFocusChanged(boolean hasFocus) {
banStatusBar();
}
@Override
protected void onPause() {
super.onPause();
unBanStatusBar();
}
在Android 6.0上验证了下,把banStatusBar方法加在onWindowFocusChanged方法中会导致应用退出后,状态栏没有恢复下拉,后面改为加在onResume方法中就不会出现该问题了。
另外验证时添加了System的UID,并使用的系统的平台签名。
这里再贴一个状态栏下拉的方法吧,当记录,也当分享:
private void expandNotify() {
int currentApiVersion = android.os.Build.VERSION.SDK_INT;
try {
Object service = getSystemService("statusbar");
Class<?> statusbarManager = Class
.forName("android.app.StatusBarManager");
Method expand = null;
if (service != null) {
if (currentApiVersion <= 16) {
expand = statusbarManager.getMethod("expand");
expand.setAccessible(true);
expand.invoke(service);
} else {
expand = statusbarManager
.getMethod("expandNotificationsPanel");
}
expand.setAccessible(true);
expand.invoke(service);
}
} catch (Exception e) {
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
最后记得添加权限:
<uses-permission android:name="android.permission.STATUS_BAR"
tools:ignore="ProtectedPermissions" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR"/>
PS:使用的时候Object service = getSystemService(“statusbar”)这句在android studio中字符串statusbar会出现红色波浪线,不用理会,照样能运行的。
有需要可以看看这个:
关于statusBarManager的源代码(安卓4.4) - 下载频道 - CSDN.NET http://download.csdn.net/detail/qq_26819733/9602861
17.09.21更新:
Caused by: java.lang.SecurityException: StatusBarManagerService: Neither user 10290 nor current process has android.permission.STATUS_BAR.
想必大家5.0以上都会遇到这个错误,说明真的不能用反射达到禁止下拉状态栏的效果的,因为当前应用申请不到android.permission.STATUS_BAR这个权限,所以反射也不能解决。下这个结论,当结贴吧。起初想研究这个是因为我当时用安卓4.4的手机,同时刚好有个叫“BT戒手机”的app,当时就想研究一下,当时我写代码的时候是成功的,因为用的手机是安卓4.4的,而我现在我用的是安卓5.1的手机,发现此方法已无用。今晚下载了BT戒手机APP试了试,那个APP也是失效的。