【问题标题】:Android O - Single line Notification - like the "Android System - USB charging this device"Android O - 单行通知 - 类似于“Android 系统 - USB 充电此设备”
【发布时间】:2018-11-13 13:36:25
【问题描述】:

我想为我的ForegroundService 持续发送通知,该通知需要尽可能小的空间。我喜欢“Android 系统 - USB 充电此设备”风格,但我找不到任何示例如何实现这一点。

谁能指出我正确的方向?

更新

如果频道被分配了重要性IMPORTANCE_MIN,则为通知提供样式。

看起来没有办法使用内置样式的 Android 来将 IMPORTANCE_MIN 的通知与 ForegroundService 一起使用。

这里是IMPORTANCE_MIN的描述:

最低通知重要性:仅在首屏下方的阴影中显示。这不应该与 Service.startForeground 一起使用,因为前台服务应该是用户关心的东西,因此将其通知标记为最低重要性在语义上没有意义。如果您从 Android 版本 Build.VERSION_CODES.O 开始执行此操作,系统将显示有关您的应用在后台运行的更高优先级的通知。

【问题讨论】:

    标签: android android-notifications android-8.0-oreo


    【解决方案1】:

    要像收费通知一样显示简洁的单行通知,您必须创建优先级为 IMPORTANCE_MIN 的Notification Channel

    @TargetApi(Build.VERSION_CODES.O)
    private static void createFgServiceChannel(Context context) {
       NotificationChannel channel = new NotificationChannel("channel_id", "Channel Name", NotificationManager.IMPORTANCE_MIN);
       NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
       mNotificationManager.createNotificationChannel(channel);
    }
    

    然后像这样创建一个持续的通知:

    public static Notification getServiceNotification(Context context) {
       NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, "channel_id");
       mBuilder.setContentTitle("One line text");
       mBuilder.setSmallIcon(R.drawable.ic_notification);
       mBuilder.setProgress(0, 0, true);
       mBuilder.setOngoing(true);
       return mBuilder.build();
    }
    

    注意

    请注意,我使用IntentService 而不是Service 对其进行了测试,并且它有效。此外,我刚刚检查了将 Thread.sleep() 设置为 15 秒,并且通知显示完美,直到 IntentService 自行停止。

    有一些图片(抱歉有些文字是西班牙语,但我认为这些图片仍然有用):

    如果你向下拖动并打开通知,它会显示如下:

    额外

    如果您注意到 Android 系统显示所有正在使用电池的应用(具有持续服务的应用)的通知,您可以降低此类通知的优先级,它会像充电通知一样显示为单行通知。

    看看这个:

    只需长按此通知,然后选择所有类别:

    并将重要性设置为 LOW:

    下次,这个“电池消耗”通知将显示为充电通知。

    【讨论】:

    • 我认为诀窍应该是 IMPORTANCE_MIN 设置。这是它的描述:“最小通知重要性:只显示在阴影中,在折叠下方。这不应该与 Service.startForeground 一起使用,因为前台服务应该是用户关心的东西,所以它不会产生语义感觉将其通知标记为最低重要性。如果您从 Android 版本Build.VERSION_CODES.O 开始这样做,系统将显示有关您的应用程序在后台运行的更高优先级的通知。这意味着,ForegroundService 可能无法实现
    • 这就是为什么我写了额外的提示,为消耗电池的应用程序设置系统通知的低优先级,但不幸的是,这必须由用户完成,而且大多数情况下可以通过编程方式完成。
    • 在我的情况下它可以工作,因为我做到了,而且我使用了一个非常快的IntentService。抱歉,如果这不是您期望的答案。
    • 我会给你赏金,因为这个答案让我意识到(并且实际上阅读了正确的文档),前台服务可能是不可能的。抱歉@CodeChimp,实际上你的答案已经很接近了,但是 Marc 需要更多的声誉 :)
    • 哇,谢谢@Szobi,很惊讶,因为这是我的第一个赏金 :)
    【解决方案2】:

    您需要将通知优先级设置为 Min,将通知频道重要性设置为 Min,并禁用显示通知频道徽章。

    这是我如何做的一个示例。我还包括创建完整的通知以供参考

    private static final int MYAPP_NOTIFICATION_ID= -793531;
    
    NotificationManager notificationManager = (NotificationManager) context
            .getSystemService(Context.NOTIFICATION_SERVICE);
    
    String CHANNEL_ID = "myapp_ongoing";
    CharSequence name = context.getString(R.string.channel_name_ongoing);
    
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, NotificationManager.IMPORTANCE_MIN);
        channel.setShowBadge(false);
    
        notificationManager.createNotificationChannel(channel);
    }
    
    NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(
            context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_stat_notification_add_reminder)
            .setContentTitle(context.getString(R.string.app_name))
            .setContentText(context.getString(R.string.create_new))
            .setOngoing(true).setWhen(0)
            .setChannelId(CHANNEL_ID)
            .setPriority(NotificationCompat.PRIORITY_MIN);
    
    // Creates an intent for clicking on notification
    Intent resultIntent = new Intent(context, MyActivity.class);
    ...
    
    // The stack builder object will contain an artificial back stack
    // for the
    // started Activity.
    // This ensures that navigating backward from the Activity leads out
    // of
    // your application to the Home screen.
    TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
    // Adds the back stack for the Intent (but not the Intent itself)
    stackBuilder.addParentStack(MyActivity.class);
    // Adds the Intent that starts the Activity to the top of the stack
    stackBuilder.addNextIntent(resultIntent);
    PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0,
            PendingIntent.FLAG_UPDATE_CURRENT);
    mBuilder.setContentIntent(resultPendingIntent);
    
    notificationManager.notify(MYAPP_NOTIFICATION_ID, mBuilder.build());
    

    【讨论】:

    • 感谢@CodeChimp 的回答。我尝试将优先级设置为低。一方面,它没有奏效。通知的样式没有更改为单行一。另一方面,Android 服务的文档明确指出您需要将优先级设置为至少PRIORITY_LOW [developer.android.com/guide/components/services#Foreground]。结果,我的服务很快就被杀死了,优先级设置为 PRIORITY_MIN
    • 我没有使用前台服务,它只会在点击时触发活动。是否 channel.setShowBadge(false);也没有帮助?
    • 我一直在使用setShowBadge(false) 也没有用,很遗憾。我还在试验,但很难相信还没有例子:)
    • 恐怕这就是我回答的极限了。离开这里以防有人不需要前台服务通知但有兴趣看到答案。
    • @Szobi 您使用的是IntentService 还是只是Service?我正在使用前台IntentService,我的单行静默通知效果很好。
    【解决方案3】:

    回答原来的问题:

    Android O 上似乎没有内置方式来获取针对ForegroundService 的单行持续通知。可以尝试添加自定义设计,但由于不同的手机有不同的通知设计,这种解决方案并不是一个好的解决方案。

    有希望,但是 :)

    Android P上,IMPORTANCE_LOWNotificationChannel 中的通知具有PRIORITY_LOW 的优先级压缩为单个甚至是ForegroundService。是啊!!

    【讨论】:

    • PRIORITY_LOW 已弃用,请改用 {@link NotificationChannel#setImportance(int)}。
    • 我也不确定是什么让 android 决定在紧凑视图中显示通知。我想规则很复杂,没有简单的方法来表达你对Android系统的愿望
    【解决方案4】:

    我通过像这样创建一个空的自定义视图来缩小前台服务通知的大小:

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
    
    
    </LinearLayout>
    

    然后像这样创建通知:

    RemoteViews notifiactionCollapsed = new RemoteViews(getPackageName(),R.layout.notification_collapsed);
        Notification notification = new NotificationCompat.Builder(this,CHANNEL_ID)
                .setSmallIcon(R.drawable.eq_icon)
                .setCustomContentView(notifiactionCollapsed)
                .setStyle(new NotificationCompat.DecoratedCustomViewStyle())
                .setShowWhen(false)
                .setContentIntent(pendingIntent)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setOngoing(true)
                .setVisibility(NotificationCompat.VISIBILITY_SECRET)
                .build();
        startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,
                notification);
    

    这有助于降低通知的高度,但我仍然不确定如何隐藏通知图标。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      • 1970-01-01
      • 2013-04-07
      相关资源
      最近更新 更多