Broadcast receiver android что это
Broadcast (Широковещательные сообщения)
Практическая часть показана в отдельной статье.
Широковещательные сообщения делают приложение более открытым; передавая события, использующие сообщения, вы открываете компоненты своего приложения для сторонних приложений, и сторонние разработчики реагируют на события без необходимости изменять ваше оригинальное приложение. В своём приложении вы можете прослушивать широковещательные сообщения других приложений, заменить или улучшить функциональность собственного (или стороннего) приложения или реагировать на системные изменения и события приложений.
Вы тоже можете организовать отправку широковещательных сообщений, а другие приложения могут обзавестись приёмниками для обработки ваших сообщений.
Приёмник широковещательных сообщений — это компонент для получения внешних событий и реакции на них. Инициализировать передачи могут:
Широковещательные сообщения можно разделить на две группы:
Класс BroadcastReceiver является базовым для класса, в котором должны происходить получение и обработка сообщений, посылаемых клиентским приложением с помощью вызова метода sendBroadcast().
Зарегистрировать экземпляр класса BroadcastReceiver можно динамически в коде или статически в манифесте.
Для статической регистрации в файле манифеста в секции application следует создать секцию receiver и указать класс приёмника. Атрибут android:exported=»true» сообщает получателю, что он может принимать широковещательные сообщения вне области приложения. Внутри секции указывается фильтр намерений в виде строки, чтобы определить, какие сообщения приёмник должен прослушивать.
Если регистрация была сделана через манифест, приложение не обязано работать, чтобы ваш приёмник среагировал на трансляцию намерения. Приложение запустится автоматически, когда подходящие намерение будет транслировано. Система сама сканирует содержимое манифеста всех приложений и делает за нас всю работу. Это хорошее решение, позволяющее экономить ресурсы. Такой подход позволяет создавать приложения, способные реагировать на события даже после завершения или принудительного завершения.
Динамическая регистрация происходит с помощью метода Context.registerReceiver().
Перед этим создаётся класс, расширяющий базовый класс BroadcastReceiver и реализуется метод обратного вызова onReceive() обработчика событий.
Метод onReceive() будет выполнен при получении широковещательного намерения, если полученное намерение соответствует фильтру. Приложения с зарегистрированными приёмниками широковещательных намерений будут запущены автоматически при получении соответствующего намерения. Метод должен быть завершён в течение пяти секунд, иначе появится диалоговое окно о принудительном закрытии.
Когда широковещательное сообщение прибывает для получателя сообщения, Android вызывает его методом onReceive() и передаёт в него объект Intent, содержащий сообщение. Приёмник широковещательных сообщений является активным только во время выполнения этого метода. Процесс, который в настоящее время выполняет BroadcastReceiver, т. е. выполняющийся в настоящее время код в методе обратного вызова onReceive(), как полагает система, является приоритетным процессом и будет сохранён, кроме случаев критического недостатка памяти в системе.
Когда программа возвращается из метода onReceive(), приёмник становится неактивным и система полагает, что работа объекта BroadcastReceiver закончена. Процесс с активным широковещательным получателем защищён от уничтожения системой. Однако процесс, содержащий неактивные компоненты, может быть уничтожен системой в любое время, когда память, которую он потребляет, будет необходима другим процессам.
Это представляет проблему, когда ответ на широковещательное сообщение занимает длительное время. Если метод onReceive() порождает отдельный поток, а затем возвращает управление, то полный процесс, включая и порождённый поток, система Android считает неактивным (если другие компоненты приложения не активны в процессе), и считает этот процесс кандидатом на уничтожение.
В частности, вы не можете отобразить диалог или осуществить связывание со службой внутри экземпляра BroadcastReceiver. Для первого случая необходимо вместо этого использовать методы класса NotificationManager. Во втором случае можно использовать вызов метода Context.startService(), чтобы послать команду для запуска службы.
Решение этой проблемы возможно, если запустить в методе onReceive() отдельную службу вместе с BroadcastReceiver и позволить службе выполнять задание, чтобы сохранить содержание процесса активным в течение всего времени вашей операции.
Также можно зарегистрировать широковещательный приёмник не через манифест, а программно. Приёмник, зарегистрированный таким способом, будет отвечать на поступающие намерения только в том случае, если компонент приложения, которому он принадлежит, выполняется в этот момент.
Это может быть полезным, когда приёмник используется для обновления элементов пользовательского интерфейса внутри активности, запуска служб или уведомления через NotificationManager. В таких случаях вы можете отменять регистрацию широковещательного приёмника, если активность не отображается на экране или находится в неактивном состоянии.
В коде программы можете написать приблизительно такой код (обычно используют метод onResume()):
Для отмены регистрации используется метод unregisterReceiver() в контексте приложения, передавая ему в качестве параметра экземпляр широковещательного приёмника (обычно в методе onPause()):
Для объекта BroadcastReceiver нет никаких возможностей видеть или фиксировать намерения, используемые в методе startActivity(). Аналогично, когда вы передали намерение для запуска активности через объект BroadcastReceiver, вы не сможете найти или запустить требуемую активность. Эти две операции семантически полностью различаются: запуск активности через намерение является приоритетной операцией для системы, изменяющей содержимое экрана устройства, с которым в настоящее время взаимодействует пользователь. Передача широковещательных сообщений для системы является фоновой работой, о которой обычно не знает пользователь и которая, соответственно, имеет более низкий приоритет.
Приёмники системных событий
Android использует широковещательные сообщения для системных событий, таких как уровень зарядки батареи, сетевые подключения, входящие звонки, изменения часового пояса, состояние подключения данных, входящие сообщения SMS или обращения по телефону. Вы можете использовать эти сообщения, чтобы добавлять к вашим собственным проектам новые функциональные возможности, основанные на системных событиях.
Следующий список показывает некоторые из встроенных действий, представленных как константы в классе Intent, которые используются для того, чтобы проследить изменения состояния устройства:
Типы трансляций
Есть три способа отправки трансляций
Если важно, чтобы приёмники получали намерения в определённом порядке или могли влиять на транслируемое намерение, можно использовать метод sendOrderedBroadcast():
С помощью этого метода ваше намерение дойдёт до всех зарегистрированных приёмников, обладающих необходимым доступом (если он был указан), в порядке их приоритета. Приоритет задаётся с помощью атрибута android:priority внутри узла фильтра намерений в манифесте. Чем больше значение, тем выше приоритет.
Производить упорядоченные трансляции с использованием приоритетов рекомендуется только для тех приёмников, которым необходим конкретный порядок приёма сообщений.
Ограничения в Android 8.0 Oreo (API 26)
Часть неявных (implicit) широковещательных сообщений, задаваемых через манифест, запретили. Теперь нужно регистрировать их программно. Существует список исключений, которые будут работать как прежде без ограничений.
В качестве замены для некоторых случаев подойдёт JobScheduler.
Примерами устаревшего способа работы с приёмником является android.net.conn.CONNECTIVITY_CHANGE, ACTION_POWER_CONNECTED и др.
Ограничения в Android 9.0 Pie (API 28)
Стало доступно меньше информации, получаемой при трансляции системы Wi-Fi и Network_State_Changed_Action.
Android Broadcast Receivers для начинающих
Перевод статьи на Медиуме о технологии Broadcast Receivers (широковещательные приемники). Это компоненты андроид, которые отслеживают широковещательные сообщения (broadcast messages) или события (events).
Для чего нужны Broadcast Receivers?
Допустим, у вас есть приложение, которое зависит от постоянного интернет-соединения. Вы хотите, чтобы ваше приложение получало уведомление при изменении интернет-соединения. Как это сделать? Возможным решением будет сервис, который всегда проверяет интернет-соединение. Эта реализация плоха по разным причинам, поэтому мы не будем ее рассматривать. Решением этой проблемы является широковещательный приемник (Broadcast Receiver), который прослушивает изменения, о которых вы сообщаете. Получатель трансляции всегда будет получать уведомления о трансляции, независимо от состояния вашего приложения. Неважно, работает ли ваше приложение в фоновом режиме или вообще не работает.
Теория Broadcast Receivers
Широковещательные приемники — это компоненты в вашем приложении Android, которые прослушивают широковещательные сообщения (или события) из разных точек:
Это означает, что они вызываются, когда происходит определенное действие, которое они запрограммированы на прослушивание, например, трансляция ( broadcast).
Трансляция ( broadcast) — это просто сообщение, заключенное в объект Intent. Трансляция может быть неявной или явной.
Есть два способа объявить приемник:
1.Объявив его в файле AndroidManifest.xml с тегом (также называемый статическим способом):
Вы заметите, что заявленный широковещательный приемник имеет свойство exported = ”true”. Этот атрибут сообщает получателю, что он может принимать широковещательные сообщения вне области приложения.
2. Или динамически путем регистрации экземпляра с помощью registerReceiver (так называемый зарегистрированный контекст):
Реализация Broadcast Receivers
Чтобы создать собственный широковещательный приемник, вы должны сначала расширить родительский класс BroadcastReceiver и переопределить обязательный метод onReceive:
Собрав все вместе, получим:
Метод onReceive выполняется в главном потоке, и поэтому его выполнение должно быть кратким.
Если выполняется долгий процесс, система может завершить процесс после возврата метода. Чтобы обойти это, рассмотрите возможность использования goAsync или планировщиков заданий (scheduling a job). Вы можете прочитать больше об этом в нижней части этой статьи.
Пример динамической регистрации
Чтобы зарегистрировать приемник с контекстом, вам сначала нужно создать экземпляр вашего широковещательного приемника:
Затем вы можете зарегистрировать его в зависимости от конкретного контекста, который вы хотите:
Первый параметр для IntentFilter — это строка, представляющая действие.
Не забудьте отменить регистрацию вашего вещательного приемника, когда он вам больше не нужен
Трансляция события
Смысл трансляции сообщений из вашего приложения заключается в том, чтобы позволить вашему приложению реагировать на события, происходящие внутри него. Подумайте о сценарии, когда в одной части кода пользователь выполняет определенное действие, и из-за этого вы хотите выполнить какую-то другую логику, которая есть в другом месте.
Есть три способа отправки трансляций:
На что обратить внимание
Изменения в новых версиях
Следующие пункты относятся к изменениям в широковещательных приемниках, относящихся к каждой версии ОС Android (начиная с 7.0). Для каждой версии были установлены определенные ограничения, а также изменилось поведение. Помните об этих ограничениях, думая об использовании Broadcast Receivers.
Изменения в Android O — это те, о которых вам нужно знать больше всего. Причина, по которой эти изменения были внесены, заключалась в том, что они приводили к проблемам с производительностью, разрядке аккумулятора и ухудшали работу пользователя. Это произошло из-за того, что многие приложения (даже те, которые в данный момент не запущены) прослушивали общесистемные изменения, и когда это изменение произошло, возник хаос. Представьте, что каждое приложение, зарегистрированное на действия, ожило, чтобы проверить, нужно ли что-то делать из-за трансляции. Примите во внимание что-то вроде состояния Wi-Fi, которое часто меняется, и вы начнете понимать, почему произошли эти изменения.
Альтернативы Broadcast Receivers
Чтобы упростить навигацию по всем этим ограничениям, ниже приводится разбивка других компонентов, которые можно использовать при отсутствии широковещательного приемника. У каждого из них своя ответственность и свой вариант использования, поэтому постарайтесь определить, какой из них отвечает вашим потребностям.
Ссылки на исходники
Если вы хотите из первых рук испытать радость и удивление, которые получают приемники вещания, вы можете перейти по этим ссылкам на репозитории, которые я настроил:
Broadcast (Широковещательные сообщения)
В Android существует понятие широковещательных сообщений, которые можно отправлять или принимать. Оба процесса между собой не связаны и их можно использовать по отдельности.
Передача сообщений
Для начала научимся отправлять сообщения. В одном из уроков мы учились запускать другую активность с помощью намерения Intent. Но намерения можно использовать для отправки сообщений, предназначенные не какому-то отдельному приложению, объекту или компоненту, а всем. И любая программа, оборудованная специальным приёмником, может поймать это сообщение и предпринять свои шаги на основе полученной информации.
Любой человек, имеющий специальный оборудованный радиоприёмник, может принять это сообщение. Так же поступают и программы. Они обзаводятся приёмниками и прослушивают определённый тип сообщений.
Сообщения может создавать сама система, а также ваша программа и чужие программы.
Передача сообщений весьма проста в реализации. В вашем приложении необходимо создать сообщение, которое вы хотите передать. Установите при необходимости поля action, data и category (действие, данные и категорию) вашего сообщения и путь, который позволяет приёмникам широковещательных сообщений точно определять «своё» сообщение. В этом сообщении строка действия ACTION должна быть уникальной, чтобы идентифицировать передаваемое действие. В таких случаях создают строку-идентификатор действия по правилам именования пакетов Java. Например, для обнаружения кота в большом здании:
Далее вы создаёте объект Intent, загружаете в него нужную информацию и вызываете метод sendBroadcast(), передав ему в качестве параметра созданный объект Intent. Дополнительные данные можно использовать в extras как необязательные параметры.
Виртуальный код для обнаружения кота:
В этом примере мы создали намерение с уникальной строкой, передали дополнительные данные (имя кота и его координаты), отправили сообщение. Другое приложение, связанное с картами, может принять сообщение и показать кота на карте.
Существуют также родственные методы sendStickyBroadcast() и sendOrderedBroadcast().
Для старых устройств этого было вполне достаточно, но начиная с Android 3.0, в целях безопасности сообщения будут игнорироваться остановленными приложениями, чтобы они не запускались. Поэтому следует добавлять дополнительный флаг, разрешающий запуск активности.
Мы напишем простой пример, который будет отправлять сообщения и также создадим приёмник для его получения. О приёмнике мы поговорим подробно во второй части урока. А пока получим первое представление о нём.
Создайте новый проект и разместите на экране кнопку с надписью «Отправить сообщение». Присвойте атрибуту onClick название метода, в котором будет происходит отправка широковещательного сообщения.
Запустив пример, вы можете нажать на кнопку и отправлять сообщение. Только ваше сообщение уйдёт в никуда, так как ни одно приложение не оборудовано приёмником для него. Исправим ситуацию и создадим приёмник в своём приложении. Мы будем сами принимать свои же сообщения.
Приёмник представляет собой обычный Java-класс на основе BroadcastReceiver. Вы можете создать вручную класс и наполнить его необходимыми методами. Раньше так и поступали. Но в студии есть готовый шаблон, который поможет немного сэкономить время.
Щёлкаем правой кнопкой мыши на названии пакета и выбираем New | Other | Broadcast Receiver
В диалоговом окне задаём имя приёмника, остальные настройки оставляем без изменений.
Студия создаст изменения в двух местах. Во-первых, будет создан класс MessageReceiver:
Во-вторых, в манифесте будет добавлен новый блок.
В него следует добавить фильтр, по которому он будет ловить сообщения.
Вернёмся в класс приёмника и модифицируем метод onReceive().
Снова запустим пример и ещё раз отправим сообщение. Так как наше приложение теперь оборудовано не только передатчиком, но и приёмником, то оно должно уловить сообщение и показать его нам.
Вы можете создать другое приложение с приёмником, чтобы одно приложение посылало сообщение, а другое принимало.
Приёмники широковещательных сообщений
Вот плавно мы перешли к приёмникам широковещательных сообщений. На самом деле вам не так часто придётся рассылать сообщения, гораздо чаще встречается потребность принимать сообщения. В первую очередь, сообщения от системы. Примерами таких сообщений могут быть:
Приёмник, созданный программно, может работать только в том случае, когда активность вашего приложения активна. Казалось, это является недостатком и нет смысла использовать такой подход. Но всё не так просто. Некоторые системные сообщения могут обрабатываться только приёмниками, созданными программно. И в этом есть свой резон. Например, если ваше приложение не запущено, ему нет смысла принимать сообщения о заряде батареи. Иначе заряд батареи будет расходоваться ещё быстрее при лишней бесполезной работе. Информацию о заряде батареи ваше приложение может получить, когда в этом есть необходимость. Следует сверяться с документацией, какой вид приёмника следует использовать.
При программной регистрации приёмника мы можем также снять регистрацию, когда больше не нуждаемся в нём с помощью метода unregisterBroadcastReceiver().
Периодическое срабатывание каждую минуту
Рассмотрим пример периодического срабатывания приёмника каждую минуту с помощью системного намерения android.intent.action.TIME_TICK. Приёмник будет создан программно. Добавим на экран активности две кнопки для регистрации и отмены регистрации широковещательного сообщения.
Создадим вручную новый класс TimeBroadcastReceiver, наследующий от BroadcastReceiver:
Вы можете создать класс приёмника и через шаблон, как мы это сделали в предыдущем примере. Но в этом случае удалите запись о нём в манифесте, так как нам он не понадобится. Но если вы забудете сделать это, то ничего страшного не произойдёт, так как там не прописаны фильтры.
Откроем код главной активности и зарегистрируем (а также снимем регистрацию) приёмник:
Запускаем проект и нажимаем на первую кнопку, чтобы включить рассылку широковещательного сообщения. Теперь каждую минуту будет срабатывать запуск всплывающего сообщения с текущим временем. Даже если вы переключитесь на другое приложение, то всё равно будете видеть сообщения.
Это один из примеров, когда приёмник следует регистрировать программно. Я видел часто на форумах вопросы, почему не работает данное намерение android.intent.action.TIME_TICK. А не надо было его регистрировать в манифесте.
В нашем примере мы устанавливали и снимали регистрацию через нажатия кнопок. Обычно включают регистрацию в методе onResume(), а снимают регистрацию в методе onPause().
Необходимо помнить, что программная регистрация широковещательного сообщения создаётся в основном потоке приложения и это может послужить источником ошибок, если операции в BroadcastReceiver занимают длительное время. Как вариант, используйте сервисы. Почитайте на эту тему статью (en).
TIME_TICK на Kotlin
Напишем похожий пример на Kotlin. Разместите на экране TextView, в котором будет отображаться время. Код для активности ниже. Обратите внимание, что мы не создаём отдельный класс для BroadcastReceiver, включаем регистрацию в onResume() и снимаем регистрацию в onPause().
Автостарт Activity или Service при загрузке (перезагрузке) девайса
Ещё один полезный пример, который часто используется приложениями.
Если ваше приложение (сервис) должно запускаться сразу после перезагрузки устройства, то используйте намерение android.intent.action.BOOT_COMPLETED:
Мы создали отдельный класс для широковещательного сообщения. Также нужно создать разрешение и зарегистрировать приёмник в манифесте.
Следим за питанием
Нет, речь пойдёт не о правильном питании кота. Имеется в виду питание от электричества. Если ваше устройство отключить от зарядки, то система оповещает об этом событии через широковещательное намерение android.intent.action.ACTION_POWER_DISCONNECTED.
Не станем заводить новый приёмник, а откроем манифест и добавим дополнительный фильтр к приёмнику сообщений от радистки Кэт.
А в классе MessageReceiver добавим код для метода.
Пример нужно проверять на реальном устройстве. Подключите устройство к питанию, а затем выдерните кабель. На экране появится сообщение.
Широковещательные приемники в Xamarin.Android
В этом разделе описывается использование широковещательного приемника.
Обзор широковещательного приемника
Широковещательный приемник — это компонент Android, позволяющий приложению реагировать на сообщения (Android ), которые рассылаются операционной системой Android или приложением. Широковещательные рассылки следуют модели публикации и подписки — это событие вызывает публикацию и получение широковещательной рассылки для тех компонентов, которые заинтересованы в событии.
Android определяет два типа широковещательных рассылок:
Фильтр с намерением используется для регистрации широковещательного приемника, чтобы Android мог правильно маршрутизировать сообщения. Фильтр намерения можно указать во время выполнения (иногда это называется приемником контекста или динамической регистрацией) или его можно статически определить в манифесте Android ( получатель, зарегистрированный манифестом). Xamarin. Android предоставляет атрибут C#, IntentFilterAttribute который будет статически регистрировать фильтр намерения (это будет обсуждаться более подробно далее в этом разделе). Начиная с Android 8,0, приложение не может статически регистрироваться для неявной трансляции.
Основное различие между зарегистрированным манифестом и приемником, зарегистрированным в контексте, заключается в том, что зарегистрированный в контексте получатель будет отвечать только за широковещательные передачи во время выполнения приложения, а получатель, зарегистрированный в манифесте, может отвечать на широковещательные передачи, даже если приложение может не работать.
Существует два набора API-интерфейсов для управления широковещательным приемником и отправки широковещательных пакетов:
Широковещательный приемник может не отображать диалоговые окна, поэтому настоятельно не рекомендуется запускать действие в широковещательном приемнике. Если широковещательный получатель должен уведомить пользователя, он должен опубликовать уведомление.
Невозможно выполнить привязку или запустить службу в широковещательном приемнике.
В этом руководство рассматривается создание широковещательного приемника и его регистрация для получения широковещательных рассылок.
Создание широковещательного приемника
Для создания широковещательного приемника в Xamarin. Android приложение должно создать подкласс BroadcastReceiver класса, сделать его графическим BroadcastReceiverAttribute и переопределить OnReceive метод:
Когда Xamarin. Android компилирует класс, он также обновляет AndroidManifest с помощью метаданных, необходимых для регистрации получателя. Для статически зарегистрированного широковещательного приемника Enabled должно быть задано значение, в true противном случае Android не сможет создать экземпляр получателя.
OnReceive Метод получает ссылку на объект, отправленный в Intent широковещательный приемник. Это дает возможность отправителю цели передавать значения получателю вещания.
Статическая регистрация широковещательного приемника с фильтром намерения
Также можно создать фильтр с намерением, который будет отвечать на пользовательские цели. Рассмотрим следующий пример.
Приложения, предназначенные для Android 8,0 (уровень API 26) или более поздней версии, не могут статически регистрироваться для неявного вещания. Приложения по-прежнему могут статически регистрироваться для явного вещания. Существует небольшой список неявных широковещательных рассылок, которые исключены из этого ограничения. Эти исключения описаны в руководстве по исключениям неявных рассылок в документации по Android. Приложения, заинтересованные в неявных широковещательных рассылках, должны делать это динамически с помощью RegisterReceiver метода. Это описано далее.
Context-Registering широковещательного приемника
Регистрация контекста (также называемая динамической регистрацией) получателя выполняется путем вызова RegisterReceiver метода, и широковещательный приемник должен быть отменен с помощью вызова UnregisterReceiver метода. Чтобы предотвратить утечку ресурсов, важно отменить регистрацию получателя, если он больше не подходит для контекста (действия или службы). Например, служба может транслировать цель для информирования о том, что обновления доступны для отображения пользователю. При запуске действия он регистрируется для этих целей. Когда действие перемещается в фон и больше не отображается для пользователя, оно должно отменить регистрацию получателя, так как пользовательский интерфейс для отображения обновлений больше не отображается. В следующем фрагменте кода приведен пример регистрации и отмены регистрации широковещательного приемника в контексте действия.
В предыдущем примере, когда действие поступает в передний план, оно регистрирует широковещательного приемника, который будет прослушивать пользовательское намерение с помощью OnResume метода Lifecycle. Когда действие перемещается в фоновый режим, метод отменяет OnPause() регистрацию получателя.
Публикация вещания
Вещание можно опубликовать во всех приложениях, установленных на устройстве, создавая объект намерения и отправляют его с помощью SendBroadcast SendOrderedBroadcast метода или.
Методы Context. сендброадкаст — существует несколько реализаций этого метода. Эти методы будут рассылать цель во всю систему. Широковещательные приемники, которые будут принимать намерение в неопределенном порядке. Это обеспечивает большую гибкость, но означает, что другие приложения могут зарегистрироваться и получить цель. Это может представлять потенциальную угрозу безопасности. Приложениям может потребоваться реализовать дополнительные средства безопасности, чтобы предотвратить несанкционированный доступ. Одним из возможных решений является использование, LocalBroadcastManager которое позволяет отправлять сообщения только в пределах частного пространства приложения. Этот фрагмент кода является одним из примеров того, как можно отправить намерение с помощью одного из SendBroadcast методов:
Этот фрагмент кода является еще одним примером отправки вещания с помощью Intent.SetAction метода для указания действия:
Context. сендордередброадкаст — этот метод очень похож на, и разница заключается в том, что цель будет опубликована по одному получателю в порядке, в котором были зарегистрированы получатели.