У меня есть служба переднего плана, в которой я настроил канал уведомлений, как требуется для Android API 26 и выше, но я не могу динамически устанавливать звук для этого уведомления. Позвольте мне объяснить:
Когда служба запускается, она создает начальное уведомление с помощью startForeground в соответствии с требованиями службы переднего плана. Я пытаюсь выполнить sh, так это повторно использовать это постоянное уведомление, которое уже находится в панели уведомлений, обновляя сообщение, чтобы обеспечить визуальное обновление статуса. Этого я уже могу достичь. В одном конкретном случае я хотел бы также обновить либо канал уведомления, либо канал уведомления, чтобы обеспечить новый звук уведомления и отобразить уведомление для пользователя. Уведомление всегда использует тот же звук, который был изначально установлен при первом запуске службы, и никогда не становится сразу видимым для пользователя, если не сдвинуть панель уведомлений вниз от верхней части экрана.
Кажется, что работает что я создаю отдельный канал уведомлений для этого случая, но тогда у меня есть два разных элемента уведомлений в трее. Другой способ, который, похоже, работает, показан на YouTube @ https://www.youtube.com/watch?v=3Je9ZEAAjfA, где автор использует NotificationManager.deleteNotificationChannel для удаления, затем NotificationManager.createNotificationChannel, однако они сказали, что ОС в конечном итоге удалит мое приложение, если я продолжу повторять создание канала уведомлений для предотвращения спама.
Есть ли способ повторно использовать исходный канал уведомлений, чтобы динамически изменить звук и сделать его видимым?
Я go на конечности и покажите решение, которое я выбрал. Метод createNotificationChannels вызывается во время onCreate, затем createNotification вызывается один раз в onStartCommand, чтобы удовлетворить 5-секундный предел для вызова startForeground. Затем при необходимости я вызываю createNotification, чтобы выбрать, какой из 3 различных каналов отображать, и установить содержимое заголовка / тела. Я бы предпочел динамически настраивать звук.
private int CHANNEL_NOTIFICATION_ID = 666;
public static final String TARGET_MESSAGING_GROUP_ID = "TargetMessagingGroupID";
public static final String TARGET_MESSAGING_GROUP_NAME = "Target Messaging Group";
public static final String WAITING_NEW_TARGET_CHANNEL_ID = "WaitingNewTargetChannelID";
public static final String WAITING_NEW_TARGET_CHANNEL_NAME = "Waiting for New Target Channel";
public static final String NAVIGATING_TO_TARGET_CHANNEL_ID = "NavigatingToTargetChannelID";
public static final String NAVIGATING_TO_TARGET_CHANNEL_NAME = "Navigating To Target Channel";
public static final String TARGET_ARRIVAL_CHANNEL_ID = "TargetArrivalChannelID";
public static final String TARGET_ARRIVAL_CHANNEL_NAME = "Target Arrival Channel";
// --------------------------------------------------------------------
// Method: createNotificationChannels
//
// Purpose: Called once at startup so we have the notification channels
// ready to go when we need them
// --------------------------------------------------------------------
protected void createNotificationChannels()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
// use the same audio attributes for each channel
AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build();
// configure the group
NotificationChannelGroup targetMessagingGroup = new NotificationChannelGroup(TARGET_MESSAGING_GROUP_ID, TARGET_MESSAGING_GROUP_NAME);
// configure the first channel
Uri soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + parentContext.getPackageName() + "/" + R.raw.elevatording);
NotificationChannel waitingNewTargetChannel = new NotificationChannel(WAITING_NEW_TARGET_CHANNEL_ID, WAITING_NEW_TARGET_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT);
waitingNewTargetChannel.setDescription(WAITING_NEW_TARGET_CHANNEL_NAME);
waitingNewTargetChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
waitingNewTargetChannel.setSound(soundUri, audioAttributes); // This is IMPORTANT
waitingNewTargetChannel.enableLights(true);
waitingNewTargetChannel.setLightColor(Color.RED);
waitingNewTargetChannel.enableVibration(false);
waitingNewTargetChannel.setGroup(TARGET_MESSAGING_GROUP_ID);
// configure the second channel
soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + parentContext.getPackageName() + "/" + R.raw.beep);
NotificationChannel navigatingToTargetChannel = new NotificationChannel(NAVIGATING_TO_TARGET_CHANNEL_ID, NAVIGATING_TO_TARGET_CHANNEL_NAME, NotificationManager.IMPORTANCE_LOW);
navigatingToTargetChannel.setDescription(NAVIGATING_TO_TARGET_CHANNEL_NAME);
navigatingToTargetChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
navigatingToTargetChannel.setSound(soundUri, audioAttributes);
navigatingToTargetChannel.enableLights(false);
navigatingToTargetChannel.setLightColor(Color.RED);
navigatingToTargetChannel.enableVibration(false);
navigatingToTargetChannel.setGroup(TARGET_MESSAGING_GROUP_ID);
// configure the third channel
soundUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + parentContext.getPackageName() + "/" + R.raw.purge_siren_loud);
NotificationChannel targetArrivalChannel = new NotificationChannel(TARGET_ARRIVAL_CHANNEL_ID, TARGET_ARRIVAL_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH);
targetArrivalChannel.setDescription(TARGET_ARRIVAL_CHANNEL_NAME);
targetArrivalChannel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
targetArrivalChannel.setSound(soundUri, audioAttributes); // This is IMPORTANT
targetArrivalChannel.enableLights(true);
targetArrivalChannel.setLightColor(Color.RED);
targetArrivalChannel.enableVibration(true);
targetArrivalChannel.setVibrationPattern(new long[]{100, 200, 300, 400, 500, 400, 300, 200, 400});
targetArrivalChannel.setGroup(TARGET_MESSAGING_GROUP_ID);
// finally, register the group and associated channels with the OS
NotificationManager notificationManager = (NotificationManager) getSystemService(NotificationManager.class);
notificationManager.createNotificationChannelGroup(targetMessagingGroup);
notificationManager.createNotificationChannel(waitingNewTargetChannel);
notificationManager.createNotificationChannel(navigatingToTargetChannel);
notificationManager.createNotificationChannel(targetArrivalChannel);
}
}
// --------------------------------------------------------------------
// Method: createNotification
//
// Purpose: Called whenever changing the displayed notification is
// required. Must call this with requestedNotificationType
// of NOTIFY_TYPE_WAITING_FOR_TARGET from onStartCommand
// in order to call startForeground within the 5 second limit
// for a foreground service.
// --------------------------------------------------------------------
protected void createNotification(LocationService.LocationNotifyType requestedNotificationType, Bitmap notificationBitmap, Uri soundUri, String title, String message)
{
Intent notificationIntent = new Intent(parentContext, signalledClass);
PendingIntent pendingIntent = null;
Notification notification = null;
int notification_id = CHANNEL_NOTIFICATION_ID;
switch (requestedNotificationType)
{
default:
{
Log.d("LocationHandler", "Unknown LocationNotifyType, NOT changing notification");
break;
}
case NOTIFY_TYPE_WAITING_FOR_TARGET:
{
pendingIntent = PendingIntent.getActivity(parentContext, 0, notificationIntent, 0);
notification = new NotificationCompat.Builder(parentContext, WAITING_NEW_TARGET_CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(notificationBitmap)
.setPriority(NotificationCompat.PRIORITY_HIGH) // only affects API 25 and below
.setStyle(new NotificationCompat.BigTextStyle().setSummaryText("Waiting").setBigContentTitle(title).bigText(message))
.setContentIntent(pendingIntent)
.setTicker(getText(R.string.ticker_text))
.setAutoCancel(false)
.setOnlyAlertOnce(true)
.setSound(soundUri)
.build();
if (notification != null)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
startForeground(notification_id, notification);
}
else
{
NotificationManagerCompat.from(parentContext).notify(notification_id, notification);
}
}
break;
}
case NOTIFY_TYPE_NAVIGATING:
{
pendingIntent = PendingIntent.getActivity(parentContext, 0, notificationIntent, 0);
notification = new NotificationCompat.Builder(parentContext, NAVIGATING_TO_TARGET_CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(notificationBitmap)
.setPriority(Notification.PRIORITY_HIGH) // only affects API 25 and below
.setStyle(new NotificationCompat.BigTextStyle().setSummaryText("Navigating").setBigContentTitle(title).bigText(message))
.setContentIntent(pendingIntent)
.setTicker(getText(R.string.ticker_text))
.setAutoCancel(false)
.setOnlyAlertOnce(true)
.setSound(soundUri)
.build();
NotificationManagerCompat.from(parentContext).notify(notification_id, notification);
break;
}
case NOTIFY_TYPE_ARRIVAL:
{
notificationIntent.setAction("ArrivalNotification");
notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
notificationIntent.putExtra(AllConstants.APP_WAKEUP_TYPE, AllConstants.APP_WAKEUP_TARGET_ARRIVAL);
pendingIntent = PendingIntent.getActivity(parentContext, notification_id, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
notification = new NotificationCompat.Builder(parentContext, TARGET_ARRIVAL_CHANNEL_ID)
.setContentTitle(title)
.setContentText(message)
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(notificationBitmap)
.setPriority(NotificationCompat.PRIORITY_HIGH) // only affects API 25 and below
.setStyle(new NotificationCompat.BigTextStyle().setSummaryText("Arrival").setBigContentTitle(title).bigText(message))
.setContentIntent(pendingIntent)
.setAutoCancel(false)
.setSound(soundUri)
.setWhen(System.currentTimeMillis())
.build();
NotificationManagerCompat.from(parentContext).notify(notification_id, notification);
break;
}
}
}