通知不适用于Api 27(8.1.0)

时间:2018-05-25 12:22:13

标签: android push-notification

通知适用于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。我还引用了其他堆栈溢出link,但没有得到任何线索,为什么在我的情况下发生此错误。

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类,我正在实现Notifications的代码。请帮帮我或给我一些建议如何解决这个错误。

2 个答案:

答案 0 :(得分:1)

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

频道是所有类型的通知的类别了解有关通知频道的更多信息

通知频道

check this

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

答案 1 :(得分:0)

更改NotificationCompat.Builder构造函数:

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);

添加频道ID:

NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)