欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android编程实现禁止状态栏下拉的方法详解

程序员文章站 2023-12-09 14:22:21
本文实例讲述了android编程实现禁止状态栏下拉的方法。分享给大家供大家参考,具体如下: 简介 项目需求app全屏时,要禁止状态栏的下拉,这个应该是一个普遍的需求了吧...

本文实例讲述了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中重写onresumeonpause方法实现状态栏的禁用和解除禁用。另: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了。

通过上面的步骤我们知道最关键的就是调用phonestatusbardisable()方法,我们这里是以广播的方式实现的,任何有新方法的同学可以脑洞大开,只要能实现调用到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程序设计有所帮助。