只在状态栏显示小图标而不显示通知

22

我想在系统的状态栏中一直显示一个小图标,而不在系统的通知托盘中显示通知本身。

我尝试使用自定义布局layout,并将根元素的可见性设置为View.GONEView.INVISIBLE,但是对于这两个选项,系统都会忽略它。

我还尝试设置根元素的高度,但系统也会忽略这一点。

以下是我的代码:

R.layout.custom_notification:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/custom_notification"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:background="@drawable/notif_background"
    android:orientation="horizontal"
    android:baselineAligned="false"/>

并显示 Notification 的代码:

 NotificationManager nm = (NotificationManager) ctx.getSystemService(Context.NOTIFICATION_SERVICE);
 NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(ctx);
 mBuilder
         .setSmallIcon(drawableId)
         .setAutoCancel(false)
         .setOngoing(true)
         .setPriority(Notification.PRIORITY_MAX);
 Intent resultIntent = new Intent(ctx, SettingsActivity.class);
 PendingIntent resultPendingIntent = PendingIntent.getActivity(ctx, 0, resultIntent, 0);
 mBuilder.setContentIntent(resultPendingIntent);
 int layout =  R.layout.custom_notification ;
 RemoteViews contentView = new RemoteViews(ctx.getPackageName(), layout);
 contentView.setViewVisibility(R.id.custom_notification, View.INVISIBLE);
 mBuilder.setContent(contentView);
 nm.notify(NOTIFICATION_ID, mBuilder.build());

我很清楚,为了实现我的目标,我需要非正式的解决方案。而且我也知道UX指南强烈建议不要这样做。所以你写这个作为答案是没有意义的。


您想在应用程序启动时设置这个小图标并保持它的常驻吗? - M. Wiśnicki
据我所知,如果没有在通知区域中设置永久通知,你所寻找的功能是不可能实现的。这只能通过自定义 Android 系统来实现,因此对你来说并没有什么用处。 - Tazz
@mwisnicki 是的,完全正确。它已经运行得很好了,我只是在寻找一种方法来摆脱托盘中的通知,并仅显示小图标。 - yshahak
1
@Tazz 我非常清楚这不是一件容易解决的事情,因为我已经寻找绕过这个限制的方法超过半年了。 - yshahak
3
@yshahak,你不能使用通知来实现此功能,因为它们并非设计用于此目的。唯一想到的解决方案是在屏幕上绘制一个图标并将其放置在通知栏区域,然后使用NotificationListener计算接收到的通知数量(你需要获得用户的权限),以便将你的图标移到正确位置,否则它会重叠在其他图标上。你还需要获得用户的允许来在屏幕上绘制内容。请参考以下链接了解如何在其他应用程序上叠加视图:https://dev59.com/HGIj5IYBdhLWcg3wPzDH - Tazz
显示剩余4条评论
5个回答

10

在没有显示相关通知的情况下,显示一个图标并不是一个好主意。根据开发者文档,状态栏通知需要满足以下所有条件:

  • 状态栏图标(你感兴趣的部分)
  • 扩展视图的标题和扩展消息(除非你定义了自定义的扩展视图)
  • PendingIntent,在通知被点击以显示相关信息时触发。

因此,如果你不想破坏用户体验,强烈建议遵循UX指南。

逻辑上:状态栏有两个部分 - 用户(通知)和系统(其他)。如果系统允许将某些东西放到系统部分 - 那么就会有太多无用的图标(由其他应用程序发布),而且可能会破坏所有使用经验的一致性。

找到了一个回答,提供了访问默认闹钟状态栏图标的方法,在这里。在Root手机后,您可以这样做。YouTube上有一些技巧可以做到这一点,一些在同一主题上的答案建议使用通知来显示图标,但将通知文本放空,以便用户只能看到图标,但这仍然不是一种方法。

这是系统状态栏实现的代码,其中描述了左右图标(即系统图标),也许你可以从中得到一些线索。关于此的解答在这里


谢谢,我非常清楚你所写的关于遵循用户体验准则的必要性。如果我没有一个充分的理由来做这件事,我也不会寻求解决方案。我已经在开发这个应用程序上工作了超过6个月。无论如何,我并不寻求需要对手机进行root的解决方案。同时,将空的通知放在托盘上也不是我要找的解决方案。 - yshahak
是的,我知道,所以我在最后一句话中添加了“但这并不是一个好方法。”我认为应该用粗体标出来.. :) @yshahak - TapanHP
再次感谢您。我仔细阅读了您所提到的问题和答案,虽然很有趣,但并不是我需要的方向,因为我的应用程序不是“系统应用程序”,我也无法访问源代码。 - yshahak
根据我的知识,我已经尽力了。有一些应用程序可以自定义状态栏,你应该去找找它们。也许你可以得到正确的方向线索。 - TapanHP

6

我建议不要在通常的Google Play应用程序中使用它。原因如下:

  1. 如果您发现一个可以帮助显示不可见通知的错误,它似乎什么也没做。这个错误只能在特定Android版本的特定设备上工作。记住:使用公开API设置您的常规代码正确执行在大多数设备中非常非常困难。隐藏API并不能在所有设备上运行。

    1. 源代码中没有这样的行为:http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/5.1.1_r1/android/app/NotificationManager.java#NotificationManager.notify%28int%2Candroid.app.Notification%29。您找不到任何这样的行为。

    2. 对于可预测的行为,请使用Android的*Compat类。也就是说,仅使用NotificationCompat类进行通知!只有使用包装器才能帮助您的应用程序显示通知。

    3. 这是非常丑陋的UI/UX。

    4. 通知的工作流程极大地依赖于Android版本。


1
你可以使用 InputMethodService.showStatusIcon() 来实现此功能。但我建议您显示普通通知,并向用户解释您的应用程序当前正在执行的操作。

1
我有一个不想要托盘通知的理由,基本上是因为小图标需要一直呆在那里(就像系统电池图标一样)。 - yshahak
你能解释一下如何使用 InputMethodService.showStatusIcon() 吗?因为很明显我现在与 InputMethodService 没有关系。 - yshahak

0

虽然晚了,但也许对其他人有用。

在我的情况下,只需在主自定义布局中使用高度为0dp即可,例如:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="fill_parent" android:layout_height="0dp">

这里不能使用wrap_content。


0

你可以使用RemoteViews来隐藏标题和文本

R.id.notification_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:layout_alignParentLeft="true"
        android:layout_marginRight="10dp"
        android:layout_marginLeft="7dp"
        android:src="@drawable/icon_battery" />
</RelativeLayout>

在MainActivity中:
RemoteViews contentView = new RemoteViews(getPackageName(), R.layout.notification_layout);
Context application = getApplicationContext();

Intent resultIntent = new Intent(application, MainActivity.class);
resultIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent resultPendingIntent = PendingIntent.getActivity(application, 0, resultIntent, 0);
NotificationManager nmgr = (NotificationManager) application.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(application)
            .setSmallIcon(R.drawable.icon_battery);

mBuilder.setContent(contentView);
Notification mNotification = mBuilder.build();

//  mNotification.flags |= FLAG_NO_CLEAR;
nmgr.notify(0, mNotification);

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