Трансляційні приймачі для початківців

Скажімо, у вас є програма, яка залежить від стабільного з’єднання з Інтернетом. Ви хочете, щоб ваша програма отримувала сповіщення, коли з’єднання з Інтернетом змінюється. Як ти це робиш? Можливим рішенням стане послуга, яка завжди перевіряє підключення до Інтернету. Ця реалізація погана з різних причин, тому ми навіть не будемо її розглядати. Рішенням цієї проблеми є широкомовний приймач, який буде прослуховувати зміни, які ви йому скажете. Приймач мовлення завжди отримуватиме повідомлення про трансляцію, незалежно від статусу вашої заявки. Не має значення, працює ваша програма в даний час, у фоновому режимі чи взагалі не працює.

Передумови

Трансляційні приймачі - це компоненти у вашому додатку Android, які прослуховують повідомлення (або події) трансляції з різних торгових точок:

  • З інших додатків
  • З самої системи
  • З вашої заявки

Це означає, що вони викликаються, коли сталася певна дія, яку вони запрограмували слухати (IE, трансляція).

Трансляція - це просто повідомлення, загорнуте всередині об’єкта Intent. Трансляція може бути неявною або явною.

  • Явна трансляція - це та програма, яка не націлена конкретно на вашу програму, тому вона не є виключною для вашої програми. Щоб зареєструватись для одного, вам потрібно скористатися IntentFilter та задекларувати його у своєму маніфесті. Вам потрібно зробити все це, оскільки операційна система Android переглядає всі заявлені фільтри намірів у вашому маніфесті та перевіряє, чи є збіг. Через таку поведінку неявні трансляції не мають атрибута target. Прикладом для неявного мовлення може бути дія вхідного SMS-повідомлення.
  • Явна мовлення є той , який призначений спеціально для вашого застосування на компоненті , який відомий заздалегідь. Це відбувається через атрибут target, який містить ім'я пакета програми або ім'я класу компонента.

Існує два способи оголошення одержувача:

  1. Оголосивши у вашому файлі AndroidManifest.xml тег (також званий статичним)

Ви помітите, що заявлений вище мовний приймач має властивість експортувати = ”true” . Цей атрибут повідомляє приймачу, що він може приймати трансляції поза межами сфери застосування.

2. Або динамічно, реєструючи екземпляр за допомогою registerReceiver (що називається зареєстрованим контекстом)

public abstract Intent registerReceiver (BroadcastReceiver receiver, IntentFilter filter);

Впровадження

Щоб створити власний приймач мовлення, спочатку потрібно розширити батьківський клас BroadcastReceiver і замінити обов’язковий метод onReceive:

public void onReceive(Context context, Intent intent) { //Implement your logic here }

Поєднання всього разом дає:

public class MyBroadcastReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { StringBuilder sb = new StringBuilder(); sb.append("Action: " + intent.getAction() + "\n"); sb.append("URI: " + intent.toUri(Intent.URI_INTENT_SCHEME).toString() + "\n"); String log = sb.toString(); Toast.makeText(context, log, Toast.LENGTH_LONG).show(); } }
MethodМетод onReceive працює на основному потоці, і тому його виконання повинно бути коротким.

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

Приклад динамічної реєстрації

Щоб зареєструвати приймач із контекстом, спочатку потрібно створити екземпляр екземпляра вашого широкомовного приймача:

BroadcastReceiver myBroadcastReceiver = new MyBroadcastReceiver();

Потім ви можете зареєструвати його залежно від конкретного контексту, який ви хочете:

IntentFilter filter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION); filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED); this.registerReceiver(myBroadcastReceiver, filter);

Не забудьте скасувати реєстрацію приймача, коли він вам більше не потрібен

@Override protected void onStop() { super.onStop(); unregisterReceiver(myBroadcastReceiver); }

Трансляція події

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

Існує три способи надсилання передач:

  1. sendOrderedBroadcastметод, обов’язково надсилає трансляції лише одному приймачу одночасно. Кожна трансляція може, у свою чергу, передавати дані до наступної або зупинити розповсюдження трансляції до приймачів, що слідують
  2. SendBroadcast аналогічний методу , описаного вище, але з однією відмінністю. Усі приймачі мовлення отримують повідомлення і не залежать один від одного
  3. Метод LocalBroadcastManager.sendBroadcast надсилає трансляції лише одержувачам, визначеним всередині вашої програми, і не перевищує обсягу вашої програми . Приклад надсилання власної трансляції

//giphy.com/gifs/23gUJhHyWkXEwl7UYV/html5

Поняття та речі, на які слід звернути увагу

  • Не надсилайте конфіденційні дані через неявну трансляцію, оскільки будь-яка програма, яка їх слухає, отримає їх. Ви можете запобігти цьому, вказавши пакет або додавши до трансляції дозвіл
  • Не починайте дії з отриманої трансляції, оскільки не вистачає досвіду користування. Натомість виберіть відображення сповіщення.

Наступні пункти посилаються на зміни в приймачах мовлення, що стосуються кожної версії ОС Android (починаючи з 7.0). Для кожної версії існують певні обмеження, і поведінка також змінюється. Пам’ятайте про ці обмеження, коли думаєте про використання приймача мовлення.

  • 7.0 і вище (рівень API 24) - Дві системні трансляції відключені, Action_New_Picture та Action_New_Video (але вони були повернені в Android O для зареєстрованих приймачів)
  • 8.0 і вище (рівень API 26) - Більшість неявних трансляцій потрібно реєструвати динамічно, а не статично (у вашому маніфесті). Ви можете знайти трансляції, які потрапили до білого списку, за цим посиланням.
  • 9.0 і вище (рівень API 28) - менше інформації, що надходить при трансляції системи Wi-Fi та Network_State_Changed_Action.

Зміни в Android O - це ті, про які вам слід знати найбільше. Причиною цих змін було те, що це призвело до проблем із продуктивністю, вичерпання заряду акумулятора та погіршення роботи користувачів. Це сталося тому, що багато додатків (навіть тих, які в даний час не працюють) слухали загальносистемні зміни, і коли ця зміна сталася, настав хаос. Уявіть, що кожна заявка, зареєстрована на акцію, ожила, щоб перевірити, чи потрібно їй щось робити через трансляцію. Візьміть до уваги щось на зразок стану Wi-Fi, який часто змінюється, і ви почнете розуміти, чому відбулися ці зміни.

Альтернативи широкомовним приймачам

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

  • LocalBroadcastManager - Як я вже згадував вище, це дійсно лише для трансляцій у вашій програмі
  • Планування роботи - завдання можна запустити залежно від отриманого сигналу або тригера, тому ви можете виявити, що трансляцію, яку ви слухали, можна замінити завданням. Крім того,JobScheduler, гарантуватиме, що ваша робота буде закінчена, але вона буде враховувати різні системні фактори (час і умови), щоб визначити, коли вона повинна працювати. Створюючи завдання, ви заміните метод, який називається onStartJob . Цей метод працює на основному потоці, тому переконайтеся, що він закінчує свою роботу за обмежений проміжок часу. Якщо вам потрібно виконати складну логіку, спробуйте розпочати фонове завдання. Крім того, повернене значення для цього методу є логічним значенням, де true означає, що певні дії все ще виконуються, а false означає, що робота виконана

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

  1. Спеціальне мовлення (з декларацією маніфесту)
  2. Реєстрація трансляції (без оголошення такої в маніфесті)
  3. LocalBroadcastManager

Трансляція закінчена.