Разработка
Live Updates в Android 16 — исследуем новые уведомления
Начиная с Android 16, у нас появился новый стиль уведомлений Notification.ProgressStyle, который мы можем использовать для создания уведомлений, ориентированных на отображение прогресса выполнения задач.
Начиная с Android 16, у нас появился новый стиль уведомлений Notification.ProgressStyle, который мы можем использовать для создания уведомлений, ориентированных на отображение прогресса выполнения задач.
В этой статье мы узнаем, как использовать этот новый стиль для предоставления конечным пользователям оперативных обновлений.
Важные сценарии использования, которые мы можем реализовать с помощью этого стиля, следующие
- Райдшаринг
- Доставка еды
- Навигация
- И т.д.
ProgressStyle довольно настраиваемый. Он включает в себя следующие компоненты, которые мы можем использовать для предоставления конечным пользователям возможности получать обновления в режиме реального времени:
- Индикатора прогресса — прогресс бар
- Сегменты — части прогресс бара с длинной и цветом
- Точки — отметки внутри индикатора прогресса с положением и цветом
- Иконки трекера
- Иконки начала и конца для индикатора прогресса
Реализация
В файле build.gradle приложения установите SDK компиляции на Android 16.
android {
// Android 16
compileSdk = 36
defaultConfig {
minSdk = 29
// Android 16
targetSdk = 36
}
}
Убедитесь, что приложение имеет разрешение на публикацию продвигаемых уведомлений. Мы можем использовать метод canPostPromotedNotifications класса NotificationManager, чтобы проверить, имеет ли наше приложение действительный доступ.
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun checkInitialization(context: Context) {
val canPostLiveUpdates = notificationManager.canPostPromotedNotifications()
}
Перенаправьте пользователя в настройки для обновления его разрешений. Если результат последнего шага false, мы можем перенаправить пользователя в настройки для обновления настроек, а затем продолжить.
val intent = Intent(ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT).setData(
"package:${appContext.packageName}".toUri()),
)
(context as Activity).startActivityForResult(intent, PERMISSION_REQUEST_CODE)
Проверьте, можно ли продвигать само уведомление. Мы можем использовать hasPromotableCharacteristics из Notification, чтобы убедиться, что уведомление подходит для оперативного обновления.
val isPromotable = notification.hasPromotableCharacteristics()
Пример Live Update для доставки еды
Давайте создадим канал уведомлений
object LiveUpdatesNotificationManager {
private lateinit var notificationManager: NotificationManager
private lateinit var appContext: Context
const val CHANNEL_ID = "live_updates_16_channel_id"
private const val CHANNEL_NAME = "live_updates_16_channel_name"
private const val NOTIFICATION_ID = 4321
fun createChannel(context: Context, notifManager: NotificationManager) {
notificationManager = notifManager
val channel = NotificationChannel(CHANNEL_ID, CHANNEL_NAME, IMPORTANCE_DEFAULT)
appContext = context
notificationManager.createNotificationChannel(channel)
}
Для нашего случая использования у нас будет следующие пять состояний:
- Заказ размещен или подтвержден
- Готовится
- В пути
- Прибывает
- Доставлен
Для начала давайте начнем с базового уведомления
fun buildBaseNotification(appContext: Context): Notification.Builder {
return Notification.Builder(appContext, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setOngoing(true)
.setColorized(true)
.setColor(Color.GRAY)
}
Нам нужно установить style вProgressStyle, который может обновляться в режиме реального времени.
Итак, давайте создадим Progress style для каждого случая.
Используя базовое уведомление из предыдущего шага, мы будем развивать его.
Шаг 1 — Заказ размещен или подтвержден
fun buildBaseNotification(): Notification.Builder {
return buildBaseNotification(appContext, INITIALIZING)
.setContentTitle("You order is being placed")
.setContentText("Confirming with Spicy7...")
}
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildBaseProgressStyle(): ProgressStyle {
val progressStyle = ProgressStyle()
.setProgressPoints(
listOf(
ProgressStyle.Point(25).setColor(Color.MAGENTA),
ProgressStyle.Point(50).setColor(Color.RED),
ProgressStyle.Point(75).setColor(Color.GREEN)
)
).setProgressSegments(
listOf(
ProgressStyle.Segment(25).setColor(Color.BLUE),
ProgressStyle.Segment(25).setColor(Color.MAGENTA),
ProgressStyle.Segment(25).setColor(Color.LTGRAY),
ProgressStyle.Segment(25).setColor(Color.RED)
)
)
return progressStyle
}
Итак, мы начали с 3 точками и четырьмя сегментами.
Результат:
Шаг 2 — Заказ готовится
Мы обновляем прогресс до 25 и добавляем большой значок к существующему уведомлению.
Заголовок и текст обновлены:
.setContentTitle(“Your order is being prepared”) .setContentText(“Next step will be delivery”)
Мы сохраняем три точки и четыре сегмента.
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildNotification(): Notification.Builder {
return buildBaseNotification(appContext, FOOD_PREPARATION)
.setContentTitle("Your order is being prepared")
.setContentText("Next step will be delivery")
.setLargeIcon(
IconCompat.createWithResource(
appContext, R.drawable.ic_notif_large,
).toIcon(appContext),
)
.setStyle(buildBaseProgressStyle().setProgress(25))
}
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildBaseProgressStyle(): ProgressStyle {
// same like step 1.
}
Результат:
Шаг 3 — Заказ доставляется
Здесь мы устанавливаем прогресс на 50 и устанавливаем иконку доставки.
Заголовок и текст обновлены:
.setContentTitle(“Your order is on its way”) .setContentText(“Enroute to destination”)
Мы показываем один пункт (25) и четыре сегмента
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildNotification(): Notification.Builder {
return buildBaseNotification(appContext, FOOD_ENROUTE)
.setContentTitle("Your order is on its way")
.setContentText("Enroute to destination")
.setStyle(
buildBaseProgressStyle()
.setProgressTrackerIcon(
IconCompat.createWithResource(
appContext, R.drawable.shopping_bag,
).toIcon(appContext),
)
.setProgress(50),
)
.setLargeIcon(
IconCompat.createWithResource(
appContext, R.drawable.ic_notif_large,
).toIcon(appContext),
)
}
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildBaseProgressStyle(): ProgressStyle {
val progressStyle = ProgressStyle()
.setProgressPoints(
listOf(
ProgressStyle.Point(25).setColor(Color.MAGENTA)
)
).setProgressSegments(
listOf(
ProgressStyle.Segment(25).setColor(Color.BLUE),
ProgressStyle.Segment(25).setColor(Color.MAGENTA),
ProgressStyle.Segment(25).setColor(Color.LTGRAY),
ProgressStyle.Segment(25).setColor(Color.RED)
)
)
return progressStyle
}
Результат:
Шаг 4 — Заказ прибывает
Здесь мы устанавливаем прогресс на 75 и устанавливаем иконку прибытия.
Заголовок и текст были обновлены:
.setContentTitle(“Your order is arriving...”) .setContentText(“Enjoy.”)
Мы показываем две точки (25, 50) и четыре сегмента.
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildNotification(): Notification.Builder {
return buildBaseNotification(appContext, FOOD_ARRIVING)
.setContentTitle("Your order is arriving...")
.setContentText("Enjoy ")
.setStyle(
buildBaseProgressStyle(FOOD_ARRIVING)
.setProgressTrackerIcon(
IconCompat.createWithResource(
appContext, R.drawable.local_shipping,
).toIcon(appContext),
)
.setProgress(75),
)
.setLargeIcon(
IconCompat.createWithResource(
appContext, R.drawable.ic_notif_large,
).toIcon(appContext),
)
}
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildBaseProgressStyle(): ProgressStyle {
val progressStyle = ProgressStyle()
.setProgressPoints(
listOf(
ProgressStyle.Point(25).setColor(Color.MAGENTA),
ProgressStyle.Point(50).setColor(Color.RED),
)
).setProgressSegments(
listOf(
ProgressStyle.Segment(25).setColor(Color.BLUE),
ProgressStyle.Segment(25).setColor(Color.MAGENTA),
ProgressStyle.Segment(25).setColor(Color.LTGRAY),
ProgressStyle.Segment(25).setColor(Color.RED)
)
)
return progressStyle
}
Результат:
Шаг 5 — Заказ доставлен
Здесь мы устанавливаем прогресс на 100 и новую иконку.
Заголовок и текст обновлены:
.setContentTitle(“Your order is complete.”) .setContentText(“Thank you for using our app.”)
Мы показываем три точки (25, 50, 75) и четыре сегмента.
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildNotification(): Notification.Builder {
return buildBaseNotification(appContext, ORDER_COMPLETE)
.setContentTitle("Your order is complete.")
.setContentText("Thank you for using our app.")
.setStyle(
buildBaseProgressStyle(ORDER_COMPLETE)
.setProgressTrackerIcon(
IconCompat.createWithResource(
appContext, R.drawable.check_box,
).toIcon(appContext),
)
.setProgress(100),
)
.setLargeIcon(
IconCompat.createWithResource(
appContext, R.drawable.ic_notif_large,
).toIcon(appContext),
)
}
@RequiresApi(Build.VERSION_CODES.BAKLAVA)
fun buildBaseProgressStyle(): ProgressStyle {
val progressStyle = ProgressStyle()
.setProgressPoints(
listOf(
ProgressStyle.Point(25).setColor(Color.MAGENTA),
ProgressStyle.Point(50).setColor(Color.RED),
ProgressStyle.Point(75).setColor(Color.LTGRAY)
)
)
return progressStyle
}
Результат:
Несколько важных моментов:
- Точки в начале и конце не отображаются на индикаторе прогресса
DEFAULT_PROGRESS_MAXравен 100MAX_PROGRESS_POINT_LIMITравен 4- Максимальное значение индикатора прогресса рассчитывается на основе сегментов
Ссылка на официальную документацию: https://developer.android.com/about/versions/16/features/progress-centric-notifications
-
Аналитика магазинов2 недели назад
Мобильный рынок Ближнего Востока: исследование Bidease и Sensor Tower выявляет драйверы роста
-
Интегрированные среды разработки3 недели назад
Chad: The Brainrot IDE — дикая среда разработки с играми и развлечениями
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.45
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.46








