简体   繁体   English

Android - 通知渠道API> = 26无法正常运行

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

I've been struggling with the new NotificationChannels which is introduced in API 26 and up. 我一直在努力使用API​​ 26及更高版本中引入的新NotificationChannels

I'm developing an app with an option to choose whether to be notified in four cases: 我正在开发一个应用程序,可以选择是否在四种情况下收到通知:

  1. Sound and Vibrate. 声音和振动。
  2. Sound only. 只有声音。
  3. Vibrate only. 仅振动。
  4. No sound or vibrate, just a pop-up. 没有声音或振动,只是一个弹出窗口。

In all cases, my app notify with sound and vibrate whatever I choose. 在所有情况下,我的应用程序通过声音通知并振动我选择的任何内容。

My code is: 我的代码是:

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);

Also, I change CHANNEL_ID every time I run the app, so it gets a fresh Channel ID every time just for testing until I find a solution. 此外,我每次运行应用程序时都会更改CHANNEL_ID ,因此每次测试时都会获得一个新的通道ID,直到我找到解决方案。

Of course, it works fine with API less than 26. 当然,它在API小于26时工作正常。

Thank you, guys! 感谢大伙们!

Thank you all guys, 谢谢大家,

I managed to solve it by simply creating a NotificationCompat.Builder and NotificationChannel for each and every case, and notify each Builder when its condition is met. 我设法通过为每个案例创建一个NotificationCompat.BuilderNotificationChannel来解决它,并在满足条件时通知每个Builder

I don't know if this is the best practice, but I'll try to optimize the code later, if anyone has an opinion on that feel free. 我不知道这是不是最好的做法,但是如果有人对此有任何意见,我会尝试稍后优化代码。 But it worked so fine now. 但它现在工作得很好。

Here's my code: 这是我的代码:

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());
    }

i found this in the documentation. 我在文档中找到了这个。 May be it will help you : 可能它会帮助你:

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. 在Android 8.0(API级别26)及更高版本上,通知的重要性取决于通知发布到的频道的重要性。 Users can change the importance of a notification channel in the system settings (figure 12). 用户可以在系统设置中更改通知通道的重要性(图12)。 On Android 7.1 (API level 25) and below, importance of each notification is determined by the notification's priority. 在Android 7.1(API级别25)及以下,每个通知的重要性由通知的优先级决定。

And also : 并且 :

Android O introduces notification channels to provide a unified system to help users manage notifications. Android O引入了通知渠道,以提供统一的系统来帮助用户管理通知。 When you target Android O, you must implement one or more notification channels to display notifications to your users. 当您定位Android O时,您必须实施一个或多个通知渠道以向您的用户显示通知。 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. 如果您没有定位Android O,则在Android O设备上运行时,您的应用与Android 7.0上的应用行为相同。

And finally : 最后:

  • 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. 有些通知行为的API已从Notification转移到NotificationChannel。 For example, use NotificationChannel.setImportance() instead of NotificationCompat.Builder.setPriority() for Android 8.0 and higher. 例如,对于Android 8.0及更高版本,请使用NotificationChannel.setImportance()而不是NotificationCompat.Builder.setPriority()。

If your sound and vibrate bools come from your app settings, then note that the intention is you should remove those from your app and send the user to the channel settings instead: 如果您的声音和振动声音来自您的应用设置,请注意您应该从应用中删除这些并将用户转到频道设置:

"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." “在您创建通知渠道后,您无法以编程方式更改通知渠道的视觉和听觉行为 - 只有用户可以从系统设置更改渠道行为。要让您的用户轻松访问这些通知设置,您应该添加一个项目用于打开这些系统设置的应用程序设置UI。“

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM