Notifications - это уведомления, которые пользователь видит в верхней части экрана, когда ему приходит новое письмо, сообщение, обновление и т.п. В ближайшие несколько уроков мы подробно разберем, какие возможности предоставлены разработчикам для показа уведомлений.

В этом уроке рассмотрим основы - отображение/обновление/удаление уведомления и обработка нажатия на него.

 

 

Отображение

Код создания простого уведомления выглядит так:

NotificationCompat.Builder builder =
       new NotificationCompat.Builder(this)
               .setSmallIcon(R.mipmap.ic_launcher)
               .setContentTitle("Title")
               .setContentText("Notification text");

Notification notification = builder.build();

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);

Используем билдер, в котором указываем иконку, заголовок и текст для уведомления. Методом build получаем готовое уведомление.

Далее используем NotificationManager и его метод notify, чтобы показать созданное уведомление. Кроме notification, требуется передать id. Это необходимо, чтобы в дальнейшем мы могли использовать этот id для обновления или удаления уведомления.

Конструктор new NotificationCompat.Builder(Context) будет помечен как Deprecated, если вы используете библиотеку appCompat версии 26 и выше. Так получилось потому, что в Android API 26 появился новый конструктор и рекомендуется использовать его. Пока не обращайте внимание на это. В одном из следующих уроков мы рассмотрим использование правильного конструктора.

 

Запустив этот код, мы увидим уведомление

Оно отображает иконку и два текста, которые мы указывали в билдере. Нажатие на него ни к чему не приведет, т.к. мы не реализовали обработчик нажатия. Мы это сделаем чуть позже.

 

 

 

Обновление

Мы отобразили уведомление и теперь хотим его обновить. Для этого нужно просто снова показать уведомление методом notify и использовать при этом тот же id.

Это будет выглядеть так:

NotificationCompat.Builder builder =
       new NotificationCompat.Builder(this)
               .setSmallIcon(android.R.drawable.ic_dialog_email)
               .setContentTitle("Title change")
               .setContentText("Notification text change");

Notification notification = builder.build();

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);

Код полностью аналогичен коду, что мы использовали при отображении уведомления. Только в билдере используем другие тексты и иконку. Самое главное, что в методе notify мы снова используем id = 1. NotificationManager по этому id найдет уведомление, которое мы отобразили чуть раньше и заменит его новым

 

 

 

Несколько уведомлений

Чтобы показать новое уведомление, а не обновить уже существующее, надо использовать другой id в методе notify.

 

Первое уведомление

NotificationCompat.Builder builder =
       new NotificationCompat.Builder(this)
               .setSmallIcon(R.mipmap.ic_launcher)
               .setContentTitle("Title")
               .setContentText("Notification text");

Notification notification = builder.build();

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);

 

Второе уведомление

NotificationCompat.Builder builder =
       new NotificationCompat.Builder(this)
               .setSmallIcon(android.R.drawable.ic_dialog_email)
               .setContentTitle("Title 2")
               .setContentText("Notification text 2");

Notification notification = builder.build();

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(2, notification);

 

Мы использовали разные id в методе notify и получили два разных уведомления

 

 

 

Удаление

Чтобы удалить уведомление, используем NotificationManager и его метод cancel с указанием id уведомления.

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.cancel(1);

 

Либо методом cancelAll можем удалить все уведомления сразу

NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.cancelAll();

 

При удалении уведомления нет необходимости проверять, отображается оно или нет. Если уведомления по каким-то причинам уже нет, то просто ничего не произойдет.

 

 

 

Обработка нажатия

Чтобы выполнить какое-либо действие по нажатию на уведомление, необходимо использовать PendingIntent. PendingIntent - это контейнер для Intent. Этот контейнер может быть использован для последующего запуска вложенного в него Intent.

Мы будем создавать Intent для запуска, например, Activity, упаковывать этот Intent в PendingIntent и передавать PeningIntent в уведомление. По нажатию на уведомление, система достанет из него PedningIntent и использует вложенный в него Intent, чтобы запустить Activity.

 

Давайте посмотрим, как это выглядит на практике:

Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent,
               PendingIntent.FLAG_UPDATE_CURRENT);

Создаем Intent для запуска Activity и упаковываем его в PedningIntent. 

Подробно о PedningIntent и его параметрах вы можете почитать в Уроке 119. Там я подробно рассмотрел различные кейсы на примерах с уведомлением и вызовом BroadcastReceiver.

 

Созданный PendingIntent нам надо будет передать в билдер уведомления. Полный код создания уведомления будет выглядеть так:

// Create PendingIntent
Intent resultIntent = new Intent(this, MainActivity.class);
PendingIntent resultPendingIntent = PendingIntent.getActivity(this, 0, resultIntent,
               PendingIntent.FLAG_UPDATE_CURRENT);

// Create Notification
NotificationCompat.Builder builder =
       new NotificationCompat.Builder(this)
               .setSmallIcon(R.mipmap.ic_launcher)
               .setContentTitle("Title")
               .setContentText("Notification text")
               .setContentIntent(resultPendingIntent);

Notification notification = builder.build();

// Show Notification
NotificationManager notificationManager =
       (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(1, notification);

Передаем PendingIntent в метод setContentIntent билдера уведомления. 

 

 

По нажатию на уведомление откроется MainActivity

 

Обратите внимание, что уведомление не удаляется автоматически после нажатия на него. Чтобы исправить это, можно в билдере уведомления использовать включить параметр autoCancel

setAutoCancel(true)

Уведомление, созданное с этим флагом будет закрываться после нажатия на него.

 

 

Билдер уведомления имеет еще несколько методов, которые могут быть полезны.

 

setNumber - позволяет добавить число в уведомление

 

 

setContentInfo - добавит текст справа

В старых версиях это выглядит так

 

В последних версиях он переехал в верхнюю часть уведомления

 

 

setColor - добавит фоновый цвет к иконке

 

 

setWhen - можно указать свое время для уведомления (время when). По умолчанию when = времени создания уведомления

 

 

setShowWhen - показывать ли время в уведомлении

 

 

setUsesChronometer - вместо статичного времени в уведомлении будет отображаться счетчик (00:00), показывающий сколько прошло от времени when. Может быть полезно для уведомления секундомера или звонка.

 

 

setOngoing - такое уведомление пользователь не сможет закрыть или смахнуть. Оно будет отображаться поверх обычных уведомлений.

 

 

setVibrate, setSound, setLights - настройки вибры, звука и LED индикатора устройства

 

 

setPriority - возможность установить приоритет. Доступные значения от -2 (NotificationCompat.PRIORITY_MIN) до 2 (NotificationCompat.PRIORITY_MAX). Поведение может отличаться на разных версиях Android, но общий смысл одинаков - чем выше приоритет, тем выше вероятность того, что пользователь увидит ваше уведомление.

 

 

setTimeoutAfter - возможность установить таймаут (в мсек), после которого уведомление само удалится. Добавлен в API 26.

 

 

setLargeIcon - возможность задать свою картинку в качестве иконки уведомления.

BitmapFactory.Options options = new BitmapFactory.Options();
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.startandroid, options);

NotificationCompat.Builder builder =
        new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.ic_launcher)
                .setContentTitle("Title")
                .setContentText("Notification text")
                .setLargeIcon(bitmap);

Иконка из setSmallIcon будет видна в статусбаре, когда панель уведомлений не раскрыта.

А само уведомление будет выглядеть так:

 

 

setProgress - возможность отобразить прогрессбар в уведомлении

У метода три параметра:

max - максимальное значение прогрессбара. Укажите 0, если надо скрыть прогрессбар.

progress - текущее значение прогрессбара. Может быть от 0 до max.

indeterminate - если true, то будет показан "бесконечный" прогрессбар

 

Рассмотрим пример:

int max = 100;

// show notification with indeterminate progressbar
builder = new NotificationCompat.Builder(this)
        .setSmallIcon(R.mipmap.ic_launcher)
        .setContentTitle("Some operation")
        .setContentText("Preparing")
        .setProgress(max,0, true);

notificationManager.notify(1, builder.build());


new Thread(new Runnable() {
    @Override
    public void run() {

        try {TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        int progress = 0;

        while (progress < max) {

            try {
                TimeUnit.MILLISECONDS.sleep(300);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            progress += 10;

            // show notification with current progress
            builder.setProgress(max, progress, false)
                    .setContentText(progress + " of " + max);
            notificationManager.notify(1, builder.build());

        }

        // show notification without progressbar
        builder.setProgress(0, 10, false)
                .setContentText("Completed");
        notificationManager.notify(1, builder.build());
    }
}).start();

 

Сначала отображаем бесконечный прогрессбар и текст Preparing. Т.е. делаем вид, что идет подготовка к выполнению операции.  

Затем в отдельном потоке имитируем выполнение операции. Каждые 300 мсек увеличиваем значение progress и обновляем уведомление, чтобы прогрессбар показал текущий прогресс. А также в тексте показываем значение прогресса и максимума.

 

После выполнения операции скрываем прогрессбар и показываем текст Completed.

 

 


Повторюсь, очень рекомендую прочесть и понять Урок 119. В нем я подробно рассматриваю, почему PendingIntent последнего уведомления заменяет PendingIntent предыдущих уведомлений, и как этого можно избежать, используя, например, requestCode.


Присоединяйтесь к нам в Telegram:

- в канале StartAndroid публикуются ссылки на новые статьи с сайта startandroid.ru и интересные материалы с хабра, medium.com и т.п.

- в чатах решаем возникающие вопросы и проблемы по различным темам: Android, Compose, Kotlin, RxJava, Dagger, Тестирование, Performance 

- ну и если просто хочется поговорить с коллегами по разработке, то есть чат Флудильня




Language

Автор сайта

Дмитрий Виноградов

Подробнее можно посмотреть или почитать.

Никакие другие люди не имеют к этому сайту никакого отношения и просто занимаются плагиатом.

Социальные сети

 

В канале я публикую ссылки на интересные и полезные статьи по Android

В чате можно обсудить вопросы и проблемы, возникающие при разработке



Группа ВКонтакте



Поддержка проекта

Яндекс
410011180491924

WebMoney
R248743991365
Z551306702056

Paypal