Notifications. Канали

В Android Oreo (API 26) з'явилася можливість створювати канали для сповіщень. У цьому уроці розберемося, як це робити і навіщо це потрібно.

Для кожної програми користувач може налаштувати сповіщення. Для цього треба зайти в налаштування системи, там вибрати Apps, знайти в списку і відкрити потрібний застосунок і вибрати розділ Notifications.

За замовчуванням налаштування виглядають так:

Налаштувань небагато, і вони торкнуться всіх повідомлень від цієї програми.

Канали дають змогу розширити ці налаштування і застосовувати їх вибірково. Розробник застосунку створює канал і вказує його ID під час створення повідомлень. Користувач у системних налаштуваннях програми бачить цей канал і може налаштувати його: важливість, звук, вібру тощо. У підсумку всі сповіщення, які належать цьому каналу, відображатимуться з цими налаштуваннями.

Тобто створюючи канал, розробник дає користувачеві можливість налаштувати поведінку певної групи повідомлень.

Давайте створимо канал:

NotificationManager notificationManager =
       (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
 
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
   NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "My channel",
           NotificationManager.IMPORTANCE_HIGH);
   channel.setDescription("My channel description");
   channel.enableLights(true);
   channel.setLightColor(Color.RED);
   channel.enableVibration(false);
   notificationManager.createNotificationChannel(channel);
}

Канали актуальні тільки для Android Oreo і вище, тому використовується перевірка версії Android. Далі я не буду включати цю перевірку в приклади, щоб не захаращувати код.

У конструкторі NotificationChannel вказуємо ID, ім'я та важливість. Далі вказуємо інші дані та налаштування. За назвою методів усе зрозуміло.

Методом createNotificationChannel створюємо канал.

Тепер Notifications налаштування застосунку мають такий вигляд:

З'явилися два канали: дефолтний і наш створений My channel. Налаштування дефолтного будуть використані для повідомлень, для яких не було вказано канал.

Відкриємо налаштування My channel:

Зверніть увагу, що пункт Vibrate вимкнений. Ми явно вказали це під час створення каналу, використовуючи метод enableVibration(false).

Тепер під час створення сповіщень ви можете вказати ID каналу, і сповіщення буде відображено відповідно до налаштувань цього каналу.

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

ID каналу вказується в конструкторі білдера повідомлення. І тепер цей конструктор не буде закреслено як Deprecated, якщо ви використовуєте бібліотеку appCompat версії 26 і вище.

У який момент створювати канал? Можна під час старту програми. Навіть якщо канал уже був раніше створений, то просто нічого не станеться. Але судячи з того, що користувач не може видаляти канали, я думаю, можна використати якийсь прапор, який ми встановимо в true після першого створення каналів, і надалі він буде говорити нам про те, що канали вже створені.

Група

Розглянемо приклад поштового додатка. Припустимо, що він уміє працювати не тільки з поштою, а й з календарем. Тобто він може нам надсилати повідомлення двох типів: листи і події.

Відповідно, ми можемо створити два канали - один для повідомлень про листи, інший - для подій. У результаті, користувач сам зможе налаштувати під себе окремо повідомлення про листи й окремо про події. Це зручно.

Але наш застосунок підтримує кілька облікових записів. І під кожен обліковий запис нам необхідно створювати два канали для повідомлень.

При створенні 4-х каналів налаштування будуть виглядати так:

Можна це поліпшити, використовуючи групи. Група - це просто спосіб візуально розділити канали в налаштуваннях.

Створюється група так:

NotificationManager notificationManager =
       (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.createNotificationChannelGroup(
       new NotificationChannelGroup(GROUP_ID, "Group 1"));

У конструкторі вказуємо ID та ім'я.

Далі, при створенні каналу використовуємо метод setGroup, щоб вказати, якій групі буде належати канал.

NotificationChannel channel = new NotificationChannel(...);
// ...
channel.setGroup(GROUP_ID);
notificationManager.createNotificationChannel(channel);

Таким чином, для кожного облікового запису нашого застосунку ми можемо створити групу і вказати її під час створення каналів повідомлень цього облікового запису:

User A (group)
    Mail (channel)
    Events (channel)
User B (group)
    Mail (channel)
    Events (channel)

Тепер налаштування мають кращий вигляд: Канали згруповані за обліковими записами.

Отримання інформації про канал

У будь-який момент після створення каналу, ви можете отримати інформацію про нього.

NotificationChannel channel = notificationManager.getNotificationChannel(CHANNEL_ID);

Метод getNotificationChannel поверне вам об'єкт NotificationChannel або null, якщо канал із зазначеним ID не було знайдено. Використовуючи різні get-методи каналу, ви зможете дізнатися, як користувач налаштував ваш канал. Але ви не зможете переналаштувати його, set-методи просто не працюватимуть.

Єдине, що ви можете змінити - це ім'я каналу і його опис (description). Для цього необхідно просто перестворити канал із новими параметрами і тим самим ID.

Якщо ви рахували налаштування каналу і з якихось причин вирішили, що користувач не правий, то ви можете попросити його змінити налаштування.

Наприклад, якщо користувач вимкнув відображення повідомлень для каналу, відкриваємо налаштування цього каналу.

NotificationChannel channel = notificationManager.getNotificationChannel(CHANNEL_ID);
 
if (channel.getImportance() == NotificationManager.IMPORTANCE_NONE) {
   Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
   intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId());
   intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
   startActivity(intent);
}

Якщо getImportance дорівнює IMPORTANCE_NONE, це означає, що канал був вимкнений користувачем. Створюємо Intent із зазначенням ID каналу та package додатка і запускаємо Activity.

Зрозуміло, у реальному застосунку треба діяти не так незграбно, а спершу поцікавитися думкою користувача і пояснити, чому ви хочете, щоб він змінив налаштування каналу.

Видалення каналу

Щоб видалити канал, використовуйте метод deleteNotificationChannel

notificationManager.deleteNotificationChannel(CHANNEL_ID);

Технічно ви, звичайно, можете використовувати видалення, а потім створення каналу, щоб відновити ваші налаштування. Але так робити не рекомендується. До того ж у налаштуваннях, у самому низу, користувач бачитиме, скільки каналів було видалено.

І він зрозуміє, що ви просто перестворюєте канал і скидаєте його налаштування.

Importance vs Priority

Якщо ви пам'ятаєте, при створенні повідомлення, ми можемо в білдері вказати пріоритет. Починаючи з Android Oreo пріоритети сповіщень були оголошені застарілими і замінені параметром каналу - важливість.