Android编程实现禁止状态栏下拉的方法详解
本文实例讲述了android编程实现禁止状态栏下拉的方法。分享给大家供大家参考,具体如下:
简介
项目需求app全屏时,要禁止状态栏的下拉,这个应该是一个普遍的需求了吧,但android系统没有直接提供给普通app直接调用的接口。那么我们只能自己想办法增加接口去实现该功能了。
具体实现方法
1. 修改systemui
路径:==/frameworks/base/packages/systemui//src/com/android/systemui/statusbar/phone/phonestatusbar.java==
通过在phonestatusbar.java类中注册一个广播的方式来实现状态栏的禁用和解除,其核心方法就是调用了disable()
方法。disable()是systemui自定义的方法,感兴趣的同学可以去看其具体实现。
下面来看下我们在systemui中的具体实现代码:
@@ -494,6 +494,31 @@ public class phonestatusbar extends basestatusbar implements demomode { } + //add steven zhang by 20160701 + private broadcastreceiver mstatusshowhide = new broadcastreceiver() { + + @override + public void onreceive(final context context, intent intent) { + // todo auto-generated method stub + string action = intent.getaction(); + + if ("com.aura.statusbar.show_or_hide".equals(action)) { + // statusbarmanager.disable_none + // statusbarmanager.disable_expand + final int mode = intent.getintextra("mode", statusbarmanager.disable_none); + if (mnavigationbarview != null) { + mhandler.post(new runnable() { + + @override + public void run() { + + disable(mode); + } + }); + } + } + } + }; //micheal add the broadcast interface for control the wifi sleep mode change begin 20150514 private broadcastreceiver wifisleepmodechangereceiver = new broadcastreceiver(){ @override @@ -519,6 +544,10 @@ public class phonestatusbar extends basestatusbar implements demomode { // ================================================================================ protected phonestatusbarview makestatusbarview() { final context context = mcontext; + // add steven zhang by 20160701 + intentfilter statusfilter = new intentfilter(); + statusfilter.addaction("com.aura.statusbar.show_or_hide"); + context.registerreceiver(mstatusshowhide, statusfilter);
既然显示隐藏的广播我们已经注册好了,那么看下我们在app中的具体调用吧。
@override protected void onresume() { super.onresume(); intent i = new intent("com.aura.statusbar.show_or_hide"); i.putextra("mode", statusbarmanager.disable_expand); sendbroadcast(i); } @override protected void onpause() { super.onpause(); intent i = new intent("com.aura.statusbar.show_or_hide"); i.putextra("mode", statusbarmanager.disable_none); sendbroadcast(i); }
在activity中重写onresume
和onpause
方法实现状态栏的禁用和解除禁用。另:statusbarmanager是一个隐藏类,所以调用的时候可能导入不了包会报错,最简单的方法就是之间用数值替换,下面列出对应关系。
public static final int disable_expand = 0x00010000; public static final int disable_notification_icons = 0x00020000; public static final int disable_notification_alerts = 0x00040000; public static final int disable_notification_ticker = 0x00080000; public static final int disable_system_info = 0x00100000; public static final int disable_home = 0x00200000; public static final int disable_recent = 0x01000000; public static final int disable_back = 0x00400000; public static final int disable_clock = 0x00800000; public static final int disable_search = 0x02000000; public static final int disable_none = 0x00000000; public static final int disable_navigation = view.status_bar_disable_home | view.status_bar_disable_recent; public static final int disable_mask = disable_expand | disable_notification_icons | disable_notification_alerts | disable_notification_ticker | disable_system_info | disable_recent | disable_home | disable_back | disable_clock | disable_search;
所以不能引用statusbarmanager的同学之间使用其数值是一样的。如果有源码的朋友,可以使用系统编译的后framework jar包作为app的lib就可以直接使用statusbarmanager方法了。其路径为/out/target/common/obj/java_libraries/framework_intermediates/classes.jar。将classes.jar改为framework.jar导入工程就ok了。
通过上面的步骤我们知道最关键的就是调用phonestatusbar中disable()
方法,我们这里是以广播的方式实现的,任何有新方法的同学可以脑洞大开,只要能实现调用到disable()就可以禁用状态栏。
2.修改phonewindowmanager
路径:==/frameworks/base/policy/src/com/android/internal/policy/impl/phonewindowmanager.java==
// monitor for system gestures msystemgestures = new systemgesturespointereventlistener(context, new systemgesturespointereventlistener.callbacks() { @override public void onswipefromtop() { if (isgestureisolated()) return; if (mstatusbar != null) { requesttransientbars(mstatusbar); } } @override public void onswipefrombottom() { if (isgestureisolated()) return; if (mnavigationbar != null && mnavigationbaronbottom) { requesttransientbars(mnavigationbar); } } @override public void onswipefromright() { if (isgestureisolated()) return; if (mnavigationbar != null && !mnavigationbaronbottom) { requesttransientbars(mnavigationbar); } } @override public void ondebug() { // no-op } private boolean isgestureisolated() { boolean ret = false; ret = settings.system.getint(mcontext.getcontentresolver(),"status_bar_disabled", 0) == 1; return ret; } });
在systemgesturespointereventlistener.callbacks
的方法中增加一个判断函数isgestureisolated()
用于判断是否支持其对应的手势操作。在这里特别说明一下,在网上找到方法用
private boolean isgestureisolated() { boolean ret = false; windowstate win = mfocusedwindow != null ? mfocusedwindow:mtopfullscreenopaquewindowstate; if (win != null && (win.getsystemuivisibility() & view.system_ui_flag_immersive_gesture_isolated) != 0) ret = true; else ret = false; return ret; }
getsystemuivisibility()
这种方式做判断的时候,获取到的win不一定是当前activity的,有时候是statusbar的,所以这样的效果不是很好,经常会下拉出状态栏,于是就有了
settings.system.getint(mcontext.getcontentresolver(),"status_bar_disabled", 0) == 1;
做判断的方法,用这种方式有一个好处就是非常直接,需要它禁止下拉的时候,就调用
settings.system.putint(getcontentresolver(), "status_bar_disabled", 1);
就ok了,解除禁止的时候调用
settings.system.putint(getcontentresolver(), "status_bar_disabled", 0);
看下activity中的具体调用
@override protected void onresume() { super.onresume(); //禁止下拉 settings.system.putint(getcontentresolver(), "status_bar_disabled", 1); } @override protected void onpause() { super.onpause(); //解除禁止 settings.system.putint(getcontentresolver(), "status_bar_disabled", 0); }
在androidmanifest.xml中声明相应的权限
<uses-permission android:name="android.permission.write_settings" />
网上还有修改phonewindowmanager中的adjustsystemuivisibilitylw方法的,如:
@override public int adjustsystemuivisibilitylw(int visibility){ if (settings.system.getint(mcontext.getcontentresolver(),"status_bar_disabled", 0) == 0) { mstatusbarcontroller.adjustsystemuivisibilitylw(mlastsystemuiflags, visibility); } mnavigationbarcontroller.adjustsystemuivisibilitylw(mlastsystemuiflags, visibility); // reset any bits in mforceclearingstatusbarvisibility that // are now clear. mresettingsystemuiflags &= visibility; // clear any bits in the new visibility that are currently being // force cleared, before reporting it. return visibility & ~mresettingsystemuiflags & ~mforceclearedsystemuiflags; }
在adjustsystemuivisibilitylw增加一个标志的判断,但这种实现的效果也不是很好,还是会出现下拉能拉下来的情况。
综上所叙,修改phonewindowmanager实现禁止下拉的方法还是在systemgesturespointereventlistener.callbacks中增加一个内部方法,这个内部方法使用标志位的形式来判断是否支持状态栏下拉。
3. 使用statusbarmanager中方法
因为statusbarmanager是隐藏方法,所以要在ide中直接使用的话要导入framework jar包,怎么找到framework jar在1. 修改systemui中有说过,这里就不重复了。直接上代码:
1.在androidmanifest.xml中声明相应的权限
<uses-permission android:name="android.permission.status_bar"/> <uses-permission android:name="android.permission.expand_status_bar"/>
网上有文章说要声明
android : shareduserid="android.uid.system"
亲自测试没有加上面这行代码,也是可以使用的。
2. 在activity中的引用
@override protected void onresume() { super.onresume(); statusbarmanager statusbarmanager = (statusbarmanager) getsystemservice(context.status_bar_service); statusbarmanager.disable(statusbarmanager.disable_expand); } @override protected void onpause() { super.onpause(); statusbarmanager statusbarmanager = (statusbarmanager) getsystemservice(context.status_bar_service); statusbarmanager.disable(statusbarmanager.disable_none); }
1.是使用系统签名,编译为系统app
java -jar signapk.jar platform.x509.pem platform.pk8 testdemo.apk testdemonew.apk
testdemonew.apk就是系统签名后的apk,然后push到/system/app/目录下就ok了。关于签名的知识就不多说了,可自行找到相关资料。
下面看下原生系统中电话处理禁止下拉的做法,代码如下:
路径:==/packages/apps/phone/src/com/android/phone/notificationmgr.java==
/** * updates the status bar to reflect the current desired state. */ private void updatestatusbar() { int state = statusbarmanager.disable_none; if (!misexpandedviewenabled) { state |= statusbarmanager.disable_expand; } if (!misnotificationenabled) { state |= statusbarmanager.disable_notification_alerts; } if (!missystembarnavigationenabled) { // disable *all* possible navigation via the system bar. state |= statusbarmanager.disable_home; state |= statusbarmanager.disable_recent; state |= statusbarmanager.disable_back; } if (dbg) log("updatestatusbar: state = 0x" + integer.tohexstring(state)); mstatusbarmanager.disable(state); }
从这个方法中我们知道系统禁用状态栏的方法就是调用statusbarmanager实现的。
更多关于android相关内容感兴趣的读者可查看本站专题:《android开发入门与进阶教程》、《android多媒体操作技巧汇总(音频,视频,录音等)》、《android基本组件用法总结》、《android视图view技巧总结》、《android布局layout技巧总结》及《android控件用法总结》
希望本文所述对大家android程序设计有所帮助。