通知适用于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的代码。请帮帮我或给我一些建议如何解决这个错误。
答案 0 :(得分:1)
在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);
}**
答案 1 :(得分:0)
更改NotificationCompat.Builder构造函数:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
添加频道ID:
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)