如何在Android中以编程方式打开/关闭通知?

34

我已经到处搜索了,但在SDK或Google上找不到如何做到这一点的任何信息。我知道通过按按钮(LauncherPro、ADW等)可以实现,所以这是可能的。

谢谢。


getSystemService("statusbar") 返回一个对象吗? - Robby Pond
是的,它可以。但我无法将其映射到StatusBarManager,因为它不是公共API的一部分。所以,现在我只将其作为“Object”类型。我该怎么做才能让它可用? - user496854
7个回答

50
您可以通过广播一个ACTION_CLOSE_SYSTEM_DIALOGS意图来以编程方式关闭通知抽屉。
这将导致“临时系统对话框”被解除。根据文档:
“临时系统对话框的一些示例是通知窗口遮蔽和最近任务对话框。”
这不需要任何权限,自Android 1.0以来显然已经可用。
以下代码适用于我在运行Android 5.0的Nexus 4上。
Intent closeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
context.sendBroadcast(closeIntent);

这应该是被接受的答案。被接受的答案中的解决方案对我没有起作用。 - 0ne_Up
通过 adbadb shell am broadcast -a android.intent.action.CLOSE_SYSTEM_DIALOGS - jonleighton
1
打开通知抽屉怎么样? - android developer
5
该功能已被弃用,无法在Android 12中运行。 - behelit
很遗憾,在Android 12中无法再使用了:https://developer.android.com/about/versions/12/behavior-changes-all - blackapps
有人知道如何在Android 12或更高版本中实现吗?(文档也不是很清楚) - Amine Harbaoui

27

Ashwin的答案 对于4.2.2以下版本的Android(即17版本以下)有效。在4.2.2中,“expand”方法已更改为“expandNotificationsPanel”。如果您不使用该方法名称用于4.2.2及以上版本,则会收到Null Pointer Exception。因此,代码应该是:

Object sbservice = getSystemService( "statusbar" );
Class<?> statusbarManager = Class.forName( "android.app.StatusBarManager" );
Method showsb;
if (Build.VERSION.SDK_INT >= 17) {
    showsb = statusbarManager.getMethod("expandNotificationsPanel");
}
else {
    showsb = statusbarManager.getMethod("expand");
}
showsb.invoke( sbservice );

需要在AndroidManifest中添加适当的权限。

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />

显然,这不是API的一部分,因此未来不能保证其可用性,很多人会建议不要这样做。


1
哦,还有在4.2.2版本中,您可以使用"expandSettingsPanel"方法直接显示新的设置面板和开关,该功能从4.2.2版本开始提供。 - Jonathan
我遇到了InvocationTargetException。 - Kirill Kulakov
我不得不在测试项目中添加权限。 - Kirill Kulakov
我必须在Android 4.3上调用collapsePanels。以下是源代码:https://android.googlesource.com/platform/frameworks/base.git/+/android-4.2.2_r1/services/java/com/android/server/StatusBarManagerService.java - Maragues
3
这似乎在搭载Lollipop或更高版本的三星设备上无法正常工作。我错了吗? - guy.gc
显示剩余3条评论

15

是的,您可以将此代码添加到您希望执行的任何位置

Object sbservice = getSystemService( "statusbar" );
Class<?> statusbarManager = Class.forName( "android.app.StatusBarManager" );
Method showsb = statusbarManager.getMethod( "expand" );
showsb.invoke( sbservice );

并添加该权限

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />

有没有办法让过渡更快? - vault

4

很遗憾,目前还没有官方的API(在这里提出了请求,请考虑给它点赞),但现在您可以使用我从所有答案中归纳总结出来的代码:

// based on https://gist.github.com/XinyueZ/7bad2c02be425b350b7f 
// requires permission: "android.permission.EXPAND_STATUS_BAR"
@SuppressLint("WrongConstant", "PrivateApi")
fun setExpandNotificationDrawer(context: Context, expand: Boolean) {
    try {
        val statusBarService = context.getSystemService("statusbar")
        val methodName =
                if (expand)
                    if (Build.VERSION.SDK_INT >= 17) "expandNotificationsPanel" else "expand"
                else
                    if (Build.VERSION.SDK_INT >= 17) "collapsePanels" else "collapse"
        val statusBarManager: Class<*> = Class.forName("android.app.StatusBarManager")
        val method: Method = statusBarManager.getMethod(methodName)
        method.invoke(statusBarService)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

编辑:同时还有 adb 命令,这可能是另一种替代方法(摘自 这里):

折叠:

adb shell service call statusbar 2

扩展:

adb shell service call statusbar 1

4
我该如何在Android中以编程方式打开/关闭通知?
使用Android SDK无法实现您想要的功能。
我知道通过按钮按下(LauncherPro、ADW等)可以完成所有“自定义启动器”,但所有这些“自定义启动器”都绕过了SDK,使用了@Yoni Samlan在另一个回答中提出的技术变体。不属于SDK的内容可能会被设备制造商删除,在未来版本中由核心Android团队替换,等等。
我认为您想要的应该通过SDK实现;否则,它确实限制了替代主屏幕实现。但是,您和我想要的并不那么重要。

有没有什么“hacky”的方法可以关闭通知?例如,当启动意图时是否可以设置任何标志以强制关闭通知栏?或者类似的其他东西? - user496854
我不知道有没有这样的事情。 - CommonsWare
@com,还没有办法做到这一点吗? - whoabackoff
@whoabackoff:目前Android SDK中仍没有相关内容。 - CommonsWare


-3
这是来自Android的Launcher的showNotifications方法:
private void showNotifications() {
    final StatusBarManager statusBar = (StatusBarManager) getSystemService(STATUS_BAR_SERVICE);
    if (statusBar != null) {
        statusBar.expand();
    }
}

(正如Robby所指出的那样,它是“状态栏”系统服务。)

这不是Android SDK的一部分。 - CommonsWare
2
这不起作用是因为公共API中没有StatusBarManager类。 - user496854
是的。CommonsWare 是对的;我只是在浏览源代码而不是相关的 SDK,抱歉。 - Yoni Samlan
这可能已经过时了,但Fede的UberMusic可以做到这一点!实际上有两个权限STATUS_BAR和EXPAND_STATUS_BAR可能会有用。 - Tom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接