首页 > 解决方案 > 通知不适用于 Api 27(8.1.0)

问题描述

通知适用于 Oreo 8.0(Api 26) 及以下版本非常好,但不适用于 Oreo 8.1.0。

下面是错误的堆栈跟踪

 android.app.RemoteServiceException: Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=0 contentView=null vibrate=null sound=null defaults=0x0 flags=0x40 color=0x00000000 actions=2 vis=PRIVATE)
                                                                             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1768)
                                                                             at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                             at android.os.Looper.loop(Looper.java:164)
                                                                             at android.app.ActivityThread.main(ActivityThread.java:6494)
                                                                             at java.lang.reflect.Method.invoke(Native Method)
                                                                             at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
                                                                             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

我正在为 Oreo 创建通知频道,但它仍然不适用于 Oreo 8.1.0。我还参考了其他堆栈溢出链接,但不知道为什么会在我的情况下发生此错误。

UpdateAlarmActivity.java

public class UpcomingAlarmReceiver extends BroadcastReceiver {

    public static final String TAG = "UpcomingAlarmReceiver";
    public static final String ACTION_DISMISS_NOW = "com.funswitch.funrooster.action.DISMISS_NOW";
    public static final String ACTION_CANCEL_NOTIFICATION = "com.funswitch.funrooster.action.CANCEL_NOTIFICATION";
    public static final String ACTION_SHOW_SNOOZING = "com.funswitch.funrooster.action.SHOW_SNOOZING";
    public static final String EXTRA_ALARM = "com.funswitch.funrooster.extra.ALARM";
    public static final String CHANNEL_NAME = "CHANNEL_NOTIFICATION";
    String NOTIFICATION_CHANNEL_ID = "io.funswitch.funrooster.Channel";


    @Override
    public void onReceive(final Context context, final Intent intent) {
        final byte[] alarmBytes = intent.getByteArrayExtra(EXTRA_ALARM);
        // Un-marshall the bytes into a parcel and create our Alarm with it.
        final Alarm alarm = ParcelableUtil.unmarshall(alarmBytes, Alarm.CREATOR);
        if (alarm == null) {
            throw new IllegalStateException("No alarm received");
        }
        final long id = alarm.getId();
        final NotificationManager nm = (NotificationManager)
                context.getSystemService(Context.NOTIFICATION_SERVICE);
        final boolean actionShowSnoozing = ACTION_SHOW_SNOOZING.equals(intent.getAction());
        if (intent.getAction() == null || actionShowSnoozing) {
            // Prepare notification
            // http://stackoverflow.com/a/15803726/5055032
            // Notifications aren't updated on the UI thread, so we could have
            // done this in the background. However, no lengthy operations are
            // done here, so doing so is a premature optimization.
            String title;
            String text;
            if (actionShowSnoozing) {
                if (!alarm.isSnoozed()) {
                    throw new IllegalStateException("Can't show snoozing notif. if alarm not snoozed!");
                }
                title = alarm.getLabel().isEmpty() ? context.getString(R.string.alarm) : alarm.getLabel();
                text = context.getString(R.string.title_snoozing_until,
                        formatTime(context, alarm.snoozingUntil()));
            } else {
                // No intent action required for default behavior
                title = context.getString(R.string.upcoming_alarm);
                text = formatTime(context, alarm.ringsAt());
            }
            Intent dismissIntent = new Intent(context, UpcomingAlarmReceiver.class)
                    .setAction(ACTION_DISMISS_NOW)
                    .putExtra(EXTRA_ALARM, ParcelableUtil.marshall(alarm));
            NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
            PendingIntent piDismiss = PendingIntent.getBroadcast(context, (int) id,
                    dismissIntent, PendingIntent.FLAG_CANCEL_CURRENT);
            mBuilder
                    .setSmallIcon(R.drawable.ic_alarm_24dp)
                    .setContentTitle(title)
                    .setContentText(text)
                    .addAction(R.drawable.ic_dismiss_alarm_24dp,
                            context.getString(R.string.dismiss_now), piDismiss);

            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                int importance = NotificationManager.IMPORTANCE_HIGH;
                NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, CHANNEL_NAME, importance);
                notificationChannel.enableLights(true);
                notificationChannel.setLightColor(Color.RED);
                notificationChannel.enableVibration(true);
                notificationChannel.setSound(null, null);
                notificationChannel.setShowBadge(false);
                notificationChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
                assert nm != null;
                mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
                nm.createNotificationChannel(notificationChannel);
            }
            Objects.requireNonNull(nm).notify(TAG, (int) id, mBuilder.build());
        } else if (ACTION_CANCEL_NOTIFICATION.equals(intent.getAction())) {
            Objects.requireNonNull(nm).cancel(TAG, (int) id);
        } else if (ACTION_DISMISS_NOW.equals(intent.getAction())) {
            new AlarmController(context, null).cancelAlarm(alarm, false, true);
        }


    }
}

以上是我的 Java 类,我在其中实现通知的代码。请帮助我或给我一些建议如何解决此错误。

标签: androidpush-notification

解决方案


在 api 级别 27 中,谷歌现在在 api 27 或更高级别中更改了通知方法,您需要创建通知通道来发送通知。

频道是分类所有类型的通知了解更多关于通知频道

检查此通知渠道

**if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
   NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
   String id = "id_product";
   // The user-visible name of the channel.
   CharSequence name = "Product";
   // The user-visible description of the channel.
   String description = "Notifications regarding our products";
   int importance = NotificationManager.IMPORTANCE_MAX;
   NotificationChannel mChannel = new NotificationChannel(id, name, importance);
   // Configure the notification channel.
   mChannel.setDescription(description);
   mChannel.enableLights(true);
   // Sets the notification light color for notifications posted to this
   // channel, if the device supports this feature.
   mChannel.setLightColor(Color.RED);
   notificationManager.createNotificationChannel(mChannel);
}**

推荐阅读