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

Android - Notification Channel API >= 26 is not working properly

我一直在努力使用 API 26 及更高版本中引入的新 NotificationChannels

我正在开发一个应用程序,可以选择在四种情况下是否收到通知:

  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 时效果很好。

谢谢大家!

我在文档中找到了这个。可能会对您有所帮助:

On Android 8.0 (API level 26) and above, importance of a notification is determined by the importance of the channel the notification was posted to. Users can change the importance of a notification channel in the system settings (figure 12). On Android 7.1 (API level 25) and below, importance of each notification is determined by the notification's priority.

还有:

Android O introduces notification channels to provide a unified system to help users manage notifications. When you target Android O, you must implement one or more notification channels to display notifications to your users. If you don't target Android O, your apps behave the same as they do on Android 7.0 when running on Android O devices.

最后:

  • Individual notifications must now be put in a specific channel.
  • Users can now turn off notifications per channel, instead of turning off all notifications from an app.
  • Apps with active notifications display a notification "badge" on top of their app icon on the home/launcher screen.
  • Users can now snooze a notification from the drawer. You can set an automatic timeout for a notification.
  • Some APIs regarding notification behaviors were moved from Notification to NotificationChannel. For example, use NotificationChannel.setImportance() instead of NotificationCompat.Builder.setPriority() for Android 8.0 and higher.

谢谢大家,

我设法通过简单地为每个案例创建一个 NotificationCompat.BuilderNotificationChannel 来解决它,并在满足条件时通知每个 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());
    }

如果您的声音和振动布尔值来自您的应用设置,那么请注意,您的意图是您应该从您的应用中删除它们并将用户转至频道设置:

"After you create a notification channel, you cannot change the notification channel's visual and auditory behaviors programmatically—only the user can change the channel behaviors from the system settings. To provide your users easy access to these notification settings, you should add an item in your app's settings UI that opens these system settings."

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