Android - 通知渠道API >= 26不能正常工作

7

我一直在为新的NotificationChannels(API 26及以上版本引入)而努力。

我正在开发一个应用,该应用具有选择四种情况下是否通知的选项:

  1. 声音和振动。
  2. 仅声音。
  3. 仅振动。
  4. 无声音或振动,仅弹出。

无论我选择什么,我的应用程序都会使用声音和振动进行通知。

我的代码是:

NotificationCompat.Builder builder;
    NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        builder = new NotificationCompat.Builder(context, CHANNEL_ID);
        int importance;
        NotificationChannel channel;

        //Boolean for choosing Sound
        if(sound) {
            importance = NotificationManager.IMPORTANCE_DEFAULT;
        } else {
            importance = NotificationManager.IMPORTANCE_LOW;
        }

        channel = new NotificationChannel(CHANNEL_ID, CHANNEL_NAME, importance);
        channel.setDescription(CHANNEL_DESC);

        //Boolean for choosing Vibrate
        if(vibrate) {
            channel.enableVibration(true);
        } else {
            channel.enableVibration(false);
        }

        notificationManager.createNotificationChannel(channel);
    } else {
        builder = new NotificationCompat.Builder(context);
    }

    if(sound && vibrate) {
        //Sound and Vibrate
        builder.setDefaults(Notification.DEFAULT_ALL);
    } else if(sound && !vibrate) {
        //Sound
        builder.setDefaults(Notification.DEFAULT_SOUND);
    } else if(!sound && vibrate) {
        //Vibrate
        builder.setDefaults(Notification.DEFAULT_VIBRATE);
    } else if(!sound && !vibrate) {
        //None
        //Do nothing! just notification with no sound or vibration
    }

    builder.setSmallIcon(R.drawable.ic_logo)
            .setContentTitle(title)
            .setContentText(text)
            .setAutoCancel(true)
            .setOnlyAlertOnce(false)
            .setPriority(Notification.PRIORITY_MAX);

此外,我每次运行应用程序时都会更改CHANNEL_ID,因此每次都会获得新的频道ID,以便进行测试,直到找到解决方案。

当然,对于API小于26的情况,它可以正常工作。

谢谢,大家!

3个回答

8

感谢大家的支持,

我通过创建一个NotificationCompat.BuilderNotificationChannel来解决问题,每种情况都有自己的Builder,当其条件满足时通知相应的Builder

我不知道这是否是最佳实践,如果有任何意见,请随时提出。但现在它已经运行得很好了。

以下是我的代码:

NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        NotificationCompat.Builder builder_all, builder_sound, builder_vibrate, builder_none;
        NotificationChannel channel_all = new NotificationChannel(CHANNEL_ID_ALL, CHANNEL_NAME_ALL, NotificationManager.IMPORTANCE_HIGH);
        channel_all.enableVibration(true);
        notificationManager.createNotificationChannel(channel_all);

        NotificationChannel channel_sound = new NotificationChannel(CHANNEL_ID_SOUND, CHANNEL_NAME_SOUND, NotificationManager.IMPORTANCE_HIGH);
        channel_sound.enableVibration(false);
        notificationManager.createNotificationChannel(channel_sound);

        NotificationChannel channel_vibrate = new NotificationChannel(CHANNEL_ID_VIBRATE, CHANNEL_NAME_VIBRATE, NotificationManager.IMPORTANCE_HIGH);
        channel_vibrate.setSound(null, null);
        channel_vibrate.enableVibration(true);
        notificationManager.createNotificationChannel(channel_vibrate);

        NotificationChannel channel_none = new NotificationChannel(CHANNEL_ID_NONE, CHANNEL_NAME_NONE, NotificationManager.IMPORTANCE_HIGH);
        channel_none.setSound(null, null);
        channel_none.enableVibration(false);
        notificationManager.createNotificationChannel(channel_none);

        //Boolean for Sound or Vibrate are chosen
        if(sound && vibrate) {
            builder_all = new NotificationCompat.Builder(context, CHANNEL_ID_ALL);
            builder_all.setSmallIcon(R.drawable.ic_logo)
                    .setContentTitle(title)
                    .setContentText(text)
                    .setAutoCancel(true)
                    .setOnlyAlertOnce(false);
            switch (transition) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    builder_all.setSmallIcon(R.drawable.ic_entered_white);
                    break;
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    builder_all.setSmallIcon(R.drawable.ic_left_white);
                    break;
            }

            notificationManager.notify(notificationID, builder_all.build());
        } else if(sound && !vibrate) {
            builder_sound = new NotificationCompat.Builder(context, CHANNEL_ID_SOUND);
            builder_sound.setSmallIcon(R.drawable.ic_logo)
                    .setContentTitle(title)
                    .setContentText(text)
                    .setAutoCancel(true)
                    .setOnlyAlertOnce(false);
            switch (transition) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    builder_sound.setSmallIcon(R.drawable.ic_entered_white);
                    break;
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    builder_sound.setSmallIcon(R.drawable.ic_left_white);
                    break;
            }

            notificationManager.notify(notificationID, builder_sound.build());
        } else if(!sound && vibrate) {
            builder_vibrate = new NotificationCompat.Builder(context, CHANNEL_ID_VIBRATE);
            builder_vibrate.setSmallIcon(R.drawable.ic_logo)
                    .setContentTitle(title)
                    .setContentText(text)
                    .setAutoCancel(true)
                    .setOnlyAlertOnce(false);
            switch (transition) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    builder_vibrate.setSmallIcon(R.drawable.ic_entered_white);
                    break;
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    builder_vibrate.setSmallIcon(R.drawable.ic_left_white);
                    break;
            }

            notificationManager.notify(notificationID, builder_vibrate.build());
        } else if(!sound && !vibrate) {
            builder_none = new NotificationCompat.Builder(context, CHANNEL_ID_NONE);
            builder_none.setSmallIcon(R.drawable.ic_logo)
                    .setContentTitle(title)
                    .setContentText(text)
                    .setAutoCancel(true)
                    .setOnlyAlertOnce(false);
            switch (transition) {
                case Geofence.GEOFENCE_TRANSITION_ENTER:
                    builder_none.setSmallIcon(R.drawable.ic_entered_white);
                    break;
                case Geofence.GEOFENCE_TRANSITION_EXIT:
                    builder_none.setSmallIcon(R.drawable.ic_left_white);
                    break;
            }

            notificationManager.notify(notificationID, builder_none.build());
        }
    } else {
        NotificationCompat.Builder builder = new NotificationCompat.Builder(context);

        if(sound && vibrate) {
            //Sound and Vibrate
            builder.setDefaults(Notification.DEFAULT_ALL);
        } else if(sound && !vibrate) {
            //Sound
            builder.setDefaults(Notification.DEFAULT_SOUND);
        } else if(!sound && vibrate) {
            //Vibrate
            builder.setDefaults(Notification.DEFAULT_VIBRATE);
        } else if(!sound && !vibrate) {
            //None
            //Do nothing! just notification with no sound or vibration
        }

        builder.setSmallIcon(R.drawable.ic_logo)
                .setContentTitle(title)
                .setContentText(text)
                .setAutoCancel(true)
                .setOnlyAlertOnce(false)
                .setPriority(Notification.PRIORITY_MAX);

        switch (transition) {
            case Geofence.GEOFENCE_TRANSITION_ENTER:
                builder.setSmallIcon(R.drawable.ic_entered_white);
                break;
            case Geofence.GEOFENCE_TRANSITION_EXIT:
                builder.setSmallIcon(R.drawable.ic_left_white);
                break;
        }

        notificationManager.notify(notificationID, builder.build());
    }

如果这个解决方案对您有用,那么它应该被接受为答案。 - Mohammedsalim Shivani
这不是我的问题。所以我不能做到。只有原帖作者可以接受它。 - Mohammedsalim Shivani
1
需要注意的相关问题是,不要同时使用enableVibration()和setVibrationPattern()来进行错误的实现,请参考这里:https://proandroiddev.com/oreo-notification-feature-a-critical-issue-that-could-restart-your-android-phone-ca122fa4d9cb - Ali Asadi

6

我在文档中找到了这个。也许它会对你有所帮助:

在 Android 8.0(API 级别 26)及以上版本中,通知的重要性由该通知所发布的通知渠道的重要性决定。用户可以在系统设置中更改通知渠道的重要性(图 12)。在 Android 7.1(API 级别 25)及以下版本中,每个通知的重要性由通知的优先级确定。

还有:

Android O 引入了通知渠道,以提供一个统一的系统来帮助用户管理通知。当您针对 Android O 进行开发时,必须实现一个或多个通知渠道以向您的用户显示通知。如果您不针对 Android O 进行开发,则您的应用程序在 Android O 设备上运行时与在 Android 7.0 上的行为相同。

最后:

  • 现在必须将单个通知放入特定的通知渠道中。
  • 用户现在可以关闭每个通知渠道的通知,而不是关闭应用程序的所有通知。
  • 具有活动通知的应用程序在主屏幕/启动器屏幕上的应用程序图标上显示通知“徽章”。
  • 用户现在可以从抽屉中暂停通知。您可以为通知设置自动超时。
  • 某些有关通知行为的 API 已从 Notification 移至 NotificationChannel。例如,对于 Android 8.0 及更高版本,请使用 NotificationChannel.setImportance() 而不是 NotificationCompat.Builder.setPriority()。

谢谢@Arnauld,我会尝试特别处理最后一个问题(现在必须将单独的通知放入特定的频道中),如果这意味着每种通知类型都必须有自己的频道ID。 - Ahmed
可以尝试使用谷歌的这个代码库:https://github.com/googlesamples/android-NotificationChannels/。祝你好运! - Arnauld Alex

0
如果您的声音和振动布尔值来自于您的应用程序设置,请注意意图是您应该从您的应用程序中移除它们并将用户发送到通道设置:
“创建通知通道后,您无法通过编程方式更改通知通道的视觉和听觉行为——只有用户可以从系统设置中更改通道行为。为了让您的用户轻松访问这些通知设置,您应该在应用程序的设置UI中添加一个项目,打开这些系统设置。”

https://developer.android.com/training/notify-user/channels#UpdateChannel


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