Broadcast Receivers

Элемент для получения уведомлений (событийно-ориентированный)

Теория

Источники широковещательных сообщений

  • Другие приложения

  • Система

  • Наше приложение

broadcast - просто сообщение, заключенное в объект Intent. Трансляция может быть неявной или явной.

Явная и неявная трансляция

Неявная широковещательная трансляция (implicit broadcast) — это такая, которая не предназначена специально для вашего приложения, поэтому она не является эксклюзивной для вашего приложения. Чтобы зарегистрироваться, вам нужно использовать IntentFilter и объявить его в своем манифесте.

Явная трансляция (explicit broadcast) — это то, что предназначено специально для вашего приложения на заранее известном компоненте. Это происходит из-за атрибута target, который содержит имя пакета приложения или имя класса компонента.

Есть три способа отправки широковещательных сообщений

  •  sendOrderedBroadcast - обеспечивает одновременную отправку широковещательных сообщений только одному получателю

  • sendBroadcast - все широковещательные приемники получают сообщение и не зависят друг от друга

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

  • *И еще есть sendStickyBroadcast

Изменения в новых версиях андроида

Следующие пункты относятся к изменениям в широковещательных приемниках, относящихся к каждой версии ОС Android (начиная с 7.0). Для каждой версии были установлены определенные ограничения, а также изменилось поведение. Помните об этих ограничениях, думая об использовании Broadcast Receivers.

  • 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.

Security

На что обратить внимание

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

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

С точки зрения безопасности

Использовать permissions

Если не установлены никакие ограничения (permissions), то любое приложение может получать данные от intent

Злоумышленник может воспользоваться этим следующим образом: - Создаем приложение с тем же именем компонента, что и атакуемого приложения - До запуска легитимного компонента устанавливаем и запускаем наше приложение - Извлекаем информацию из broadcast intent, которая была отправлена компоненту

Отделять локальные широновещательные сообщения от глобальных

Правильно использовать для локальных (в рамкам одного приложения) широковещательных сообщений - LocalBroadcastManager

Обрабатывать правильно интенты

Надо помнить, что в обработчик BroadcastReceiver может прийти null как интент. При неправильной обработке этого события, может произойти DoS приложения.

Примеры

Регистрация через манифест

<receiver Android:name=”receiver” >
    <intent-filter>
        <action Android:name=”com.Myapplciation.Android.mybroadcast” />
    </intent-filter>
</receiver>

Динамическая регистрация

// сначала нужно создать экземпляр вашего широковещательного приемника
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);
}

или так

registerReceiver(new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {...}
}, null);

Last updated