Вещательный приемник Android что это такое

Обновлено: 31.01.2023

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

Трансляции

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

Как правило, трансляции – это компоненты обмена сообщениями, которые используются для обмена сообщениями между приложениями при возникновении интересующих вас событий. Существует два типа трансляций:

  • Системные трансляции доставляются системой.
  • Пользовательские трансляции доставляются вашим приложением.

Системные трансляции

Системная широковещательная рассылка – это сообщение, которое система Android отправляет при возникновении системного события. Системные широковещательные сообщения завернуты в объекты Intent. Поле действия объекта намерения содержит сведения о событии, такие как android.intent.action.HEADSET_PLUG , которое отправляется при подключении или отключении проводной гарнитуры. Намерение также может содержать дополнительные данные о событии в своем дополнительном поле, например логическое дополнительное значение, указывающее, подключена или отключена гарнитура.

  • При загрузке устройства система передает системное намерение с действием ACTION_BOOT_COMPLETED .
  • Когда устройство отключено от внешнего источника питания, система отправляет системное намерение с полем действия ACTION_POWER_DISCONNECTED .

Системные трансляции не предназначены для конкретных получателей. Заинтересованные приложения должны зарегистрировать компонент, чтобы «прослушивать» эти события. Этот прослушивающий компонент называется широковещательным приемником.

По мере развития системы Android в нее вносятся значительные изменения для повышения производительности системы. Например, начиная с Android 7.0 системные широковещательные действия ACTION_NEW_PICTURE и ACTION_NEW_VIDEO не поддерживаются. Приложения больше не могут получать сообщения об этих действиях, независимо от целевой версии SDK на устройстве. Это связано с тем, что камеры устройства часто делают снимки и записывают видео, поэтому отправка системной трансляции каждый раз, когда происходит одно из этих действий, приведет к чрезмерной нагрузке на память и аккумулятор устройства.

Чтобы получить полный список широковещательных действий, которые система может отправлять для определенной версии SDK, проверьте файл broadcast_actions.txt в папке SDK по следующему пути: Android/sdk/platforms/android-xx. /data, где xx — версия SDK.

Пользовательские трансляции

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

Чтобы создать пользовательскую трансляцию, определите пользовательское действие Intent.

Примечание. Когда вы указываете действие для Intent , используйте уникальное имя пакета (например, com.example.myproject ), чтобы убедиться, что ваше намерение не конфликтует с намерением, которое транслируется из другого приложения или из система Android.

Существует три способа доставки персонализированной трансляции:

  • Для обычной трансляции передайте намерение в sendBroadcast() .
  • Для упорядоченной трансляции передайте намерение в sendOrderedBroadcast() .
  • Для локальной трансляции передайте намерение LocalBroadcastManager.sendBroadcast() .

Обычные, заказные и локальные трансляции более подробно описаны ниже.

Обычные трансляции

Метод sendBroadcast() отправляет широковещательные сообщения всем зарегистрированным получателям одновременно в неопределенном порядке. Это называется обычной трансляцией. Обычная широковещательная рассылка является наиболее эффективным способом отправки широковещательной рассылки. При обычной рассылке получатели не могут распространять результаты между собой и не могут отменить рассылку.

Следующий метод отправляет обычную широковещательную рассылку всем заинтересованным получателям широковещательной рассылки:

Заказные трансляции

Чтобы отправить широковещательную рассылку одному получателю за раз, используйте метод sendOrderedBroadcast():

  • Атрибут android:priority, указанный в фильтре намерений, определяет порядок отправки широковещательной рассылки.
  • Если присутствует более одного получателя с одинаковым приоритетом, порядок отправки является случайным.
  • Намерение распространяется от одного получателя к другому.
  • Во время своего хода получатель может обновить Intent или отменить трансляцию. (Если получатель отменяет трансляцию, намерение не может распространяться дальше.)

Например, следующий метод отправляет упорядоченную широковещательную рассылку всем заинтересованным получателям широковещательной рассылки:

Местные трансляции

Если вам не нужно отправлять широковещательные сообщения в другое приложение, используйте метод LocalBroadcastManager.sendBroadcast(), который отправляет широковещательные сообщения получателям в вашем приложении. Этот метод эффективен, так как не требует взаимодействия между процессами. Кроме того, использование локальных трансляций защищает ваше приложение от некоторых проблем с безопасностью.

Чтобы отправить локальную рассылку:

  1. Чтобы получить экземпляр LocalBroadcastManager , вызовите getInstance() и передайте его в контексте приложения.
  2. Вызовите sendBroadcast() для экземпляра. Передайте намерение, которое вы хотите транслировать.

Вещательные приемники

Приемники широковещательных сообщений — это компоненты приложения, которые могут регистрироваться для системных событий или событий приложения. Когда происходит событие, зарегистрированные приемники вещания уведомляются через Intent. Например, если вы внедряете мультимедийное приложение и хотите знать, когда пользователь подключает или отключает гарнитуру, зарегистрируйтесь для действия намерения ACTION_HEADSET_PLUG.

Используйте широковещательные приемники, чтобы отвечать на сообщения, отправленные из приложений или из системы Android. Чтобы создать широковещательный приемник:

  1. Определите подкласс класса BroadcastReceiver и реализуйте метод onReceive().
  2. Зарегистрируйте широковещательный приемник статически или динамически.

Эти шаги описаны ниже.

Подкласс BroadcastReceiver

Чтобы создать широковещательный приемник, определите подкласс класса BroadcastReceiver. В этот подкласс доставляются объекты Intent, если они соответствуют фильтрам Intent, для которых вы регистрируетесь.

В вашем подклассе:

  • Реализуйте метод onReceive(), который вызывается, когда объект BroadcastReceiver получает широковещательную рассылку Intent.
  • Внутри onReceive() включите любую другую логику, необходимую вашему приемнику вещания.

Пример: создание широковещательного приемника

В этом примере класс myReceiver является подклассом BroadcastReceiver . Если входящее широковещательное намерение имеет действие ACTION_SHOW_TOAST, класс myReceiver показывает всплывающее сообщение:

Метод onReceive() вызывается, когда ваше приложение получает зарегистрированное широковещательное намерение. Метод onReceive() выполняется в основном потоке, если в методе registerReceiver() явно не запрашивается запуск в другом потоке.

Тайм-аут метода onReceive() составляет 10 секунд. Через 10 секунд система Android считает, что ваш приемник заблокирован, и система может показать пользователю ошибку «приложение не отвечает». По этой причине не следует реализовывать длительные операции в onReceive() .

Важно: не используйте асинхронные операции для запуска длительной операции в реализации onReceive(), поскольку после возврата кода из onReceive() система считает, что компонент BroadcastReceiver завершен. Если onReceive() запустит асинхронную операцию, система остановит процесс BroadcastReceiver до того, как асинхронная операция сможет завершиться.

  • Не пытайтесь показать диалог из BroadcastReceiver . Вместо этого отобразите уведомление с помощью NotificationManager API.
  • Не пытайтесь выполнить привязку к службе из BroadcastReceiver . Вместо этого используйте Context.startService() для отправки команды службе.

Если вам нужно выполнить длительную операцию внутри BroadcastReceiver, используйте WorkManager для планирования задания. Когда вы планируете задачу с помощью WorkManager , задача гарантированно будет запущена. WorkManager выбирает подходящий способ выполнения вашей задачи на основе таких факторов, как уровень API устройства и состояние приложения.

Зарегистрируйте свой вещательный приемник и установите фильтры намерений

Существует два типа широковещательных приемников:

  • Статические приемники, которые вы регистрируете в файле манифеста Android.
  • Динамические приемники, которые вы регистрируете с помощью контекста.

Статические приемники

Статические приемники также называются приемниками, объявленными в манифесте. Чтобы зарегистрировать статический приемник, включите в элемент в файле AndroidManifest.xml следующие атрибуты:

Значением этого атрибута является полностью классифицированное имя подкласса BroadcastReceiver, включая имя пакета. Чтобы использовать имя пакета, указанное в манифесте, поставьте точку перед именем подкласса, например .AlarmReceiver .

Если для этого логического значения установлено значение false , другие приложения не могут отправлять широковещательные сообщения на ваш приемник. Этот атрибут важен для безопасности.

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

В следующем фрагменте кода показана статическая регистрация широковещательного приемника, который прослушивает пользовательское широковещательное намерение с действием " ACTION_SHOW_TOAST ":

  • Имя получателя — это имя подкласса BroadcastReceiver (. AlarmReceiver ).
  • Приемник не экспортируется, а это означает, что никакие другие приложения не могут доставлять трансляции в это приложение.
  • Фильтр намерений проверяет, включают ли входящие намерения действие с именем ACTION_SHOW_TOAST , которое является настраиваемым действием намерения, определенным в приложении.

Примечание. Для Android 8.0 (уровень API 26) и более поздних версий статические приемники не могут принимать большинство неявных широковещательных передач. (Неявные широковещательные рассылки — это широковещательные рассылки, которые не нацелены конкретно на ваше приложение.) Даже если вы зарегистрируетесь для этих широковещательных передач в манифесте, система Android не будет доставлять их вашему приложению. Однако вы по-прежнему можете использовать динамический приемник для регистрации на эти трансляции.

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

Фильтры намерений

Фильтр намерений определяет типы намерений, которые может получать компонент. Когда система получает намерение как широковещательную рассылку, она ищет получателей широковещательной рассылки на основе значений, указанных в фильтрах намерений получателей.

Это прослушивает системную широковещательную рассылку, отправляемую при загрузке устройства. Фильтру соответствуют только объекты Intent с действием BOOT_COMPLETED:

Если фильтры намерений не указаны, приемник широковещательной рассылки можно активировать только с явным намерением широковещательной рассылки, в котором компонент указывается по имени. (Это похоже на то, как явные намерения используются для запуска действий по именам их классов.)

Дополнительные сведения об использовании фильтров намерений см. в разделе Разрешение намерений руководства по намерениям.

Динамические приемники

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

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

Чтобы использовать контекст для динамической регистрации получателя:

Создайте IntentFilter и добавьте действия Intent, которые вы хотите, чтобы ваше приложение прослушивало. К одному и тому же объекту IntentFilter можно добавить несколько действий.

Когда питание устройства подключено или отключено, система Android передает действия намерения Intent.ACTION_POWER_CONNECTED и Intent.ACTION_POWER_DISCONNECTED.

Зарегистрируйте получателя, вызвав метод registerReceiver() в контексте. Передайте объект BroadcastReceiver и объект IntentFilter.

В этом примере контекст Activity ( this ) используется для регистрации получателя. Таким образом, приложение будет получать трансляцию, пока активна активность.

Местные трансляции

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

Чтобы зарегистрировать приемник для местных трансляций:

  1. Получите экземпляр LocalBroadcastManager, вызвав метод getInstance().
  2. Вызвать registerReceiver() , передав приемник и объект IntentFilter.

Отменить регистрацию получателя

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

Чтобы отменить регистрацию обычного широковещательного приемника:

Вызовите unregisterReceiver() и передайте свой объект BroadcastReceiver:

Чтобы отменить регистрацию локального вещательного приемника:

Получить экземпляр LocalBroadcastManager .

Вызовите LocalBroadcastManager.unregisterReceiver() и передайте свой объект BroadcastReceiver:

Вызов этих методов unregisterReceiver() зависит от желаемого жизненного цикла вашего объекта BroadcastReceiver:

Иногда приемник нужен только тогда, когда видны ваши действия, например, чтобы отключить сетевую функцию, когда сеть недоступна. В этих случаях зарегистрируйте получателя в onResume() и отмените регистрацию получателя в onPause() .

Ограничение трансляций

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

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

Есть два важных шага, чтобы заставить BroadcastReceiver работать с широковещательными намерениями системы —

Создание широковещательного приемника.

Регистрация широковещательного приемника

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

Создание широковещательного приемника

Приемник широковещательной рассылки реализован как подкласс класса BroadcastReceiver и переопределяет метод onReceive(), где каждое сообщение принимается как параметр объекта Intent.

Регистрация широковещательного приемника

Приложение прослушивает определенные намерения трансляции, регистрируя приемник трансляции в файле AndroidManifest.xml. Представьте, что мы собираемся зарегистрировать MyReceiver для системного события ACTION_BOOT_COMPLETED, которое запускается системой после того, как система Android завершит процесс загрузки.

broadcast

Вещательный приемник

Теперь всякий раз, когда ваше Android-устройство загружается, оно будет перехватываться BroadcastReceiver MyReceiver и будет выполняться реализованная логика внутри onReceive().

Существует несколько событий, генерируемых системой, определенных как окончательные статические поля в классе Intent. В следующей таблице перечислены несколько важных системных событий.

android.intent.action.BATTERY_CHANGED

Закрепленная трансляция, содержащая информацию о состоянии зарядки, уровне заряда и другую информацию о батарее.

android.intent.action.BATTERY_LOW

Указывает на низкий уровень заряда батареи на устройстве.

android.intent.action.BATTERY_OKAY

Указывает на то, что батарея теперь в порядке после того, как она разряжена.

android.intent.action.BOOT_COMPLETED

Это передается один раз после завершения загрузки системы.

android.intent.action.BUG_REPORT

Показать активность для сообщения об ошибке.

android.intent.action.CALL

Выполнить звонок кому-то, указанному в данных.

android.intent.action.CALL_BUTTON

Пользователь нажал кнопку "вызов", чтобы перейти к номеронабирателю или другому подходящему пользовательскому интерфейсу для выполнения вызова.

android.intent.action.DATE_CHANGED

Дата изменилась.

android.intent.action.REBOOT

Перезагрузите устройство.

Трансляция пользовательских намерений

Если вы хотите, чтобы ваше приложение само генерировало и отправляло пользовательские намерения, вам придется создавать и отправлять эти намерения с помощью метода sendBroadcast() внутри вашего класса активности. Если вы используете метод sendStickyBroadcast(Intent), Intent является фиксированным, то есть Intent, который вы отправляете, остается после завершения трансляции.

Это намерение com.tutorialspoint.CUSTOM_INTENT также можно зарегистрировать таким же образом, как мы зарегистрировали намерение, сгенерированное системой.

Пример

В этом примере показано, как создать BroadcastReceiver для перехвата пользовательского намерения. Как только вы познакомитесь с пользовательскими намерениями, вы сможете запрограммировать свое приложение на перехват намерений, сгенерированных системой. Итак, давайте выполним следующие шаги, чтобы изменить приложение Android, которое мы создали в главе Hello World Example

Шаг Описание
1 Вы будете использовать Android Studio для создания приложения Android и назовите его Мое приложение в пакете com .example.tutorialspoint7.myapplication, как описано в главе Hello World Example.
2 Измените файл основного действия MainActivity.java, чтобы добавить метод broadcastIntent().
3 Создайте новый файл Java с именем MyReceiver.java в пакете com.example.tutorialspoint7.myapplication для определите BroadcastReceiver.
4 Приложение может обрабатывать одно или несколько пользовательских и системных намерений без каких-либо ограничений. Каждое намерение, которое вы хотите перехватить, должно быть зарегистрировано в вашем AndroidManifest.xml с помощью тега
5 Изменить содержимое res/layout по умолчанию /activity_main.xml, чтобы включить кнопку для трансляции намерений.
6 Нет необходимости чтобы изменить строковый файл, Android Studio позаботится о файле string.xml.
7 Запустите приложение для запуска эмулятора Android и проверки результатов внесенных в приложение изменений.

Ниже приведено содержимое измененного файла основного действия MainActivity.java. Этот файл может включать каждый из основных методов жизненного цикла. Мы добавили метод broadcastIntent() для трансляции пользовательского намерения.

Ниже приведено содержимое MyReceiver.java:

Далее будет изменено содержимое файла AndroidManifest.xml. Здесь мы добавили тег для включения нашего сервиса:

Далее будет содержимое файла res/layout/activity_main.xml, в котором будет кнопка для трансляции нашего пользовательского намерения –

Значок запуска Eclipse

Давайте попробуем запустить наш модифицированный Hello World! приложение, которое мы только что изменили. Я предполагаю, что вы создали свой AVD во время настройки среды. Чтобы запустить приложение из студии Android, откройте один из файлов действий вашего проекта и щелкните значок «Выполнить» на панели инструментов. Android Studio устанавливает приложение на ваш AVD и запускает его, и если все в порядке с вашей настройкой и приложением, оно отобразит следующее окно эмулятора —

Демонстрационная трансляция Android

Теперь, чтобы транслировать наше пользовательское намерение, давайте нажмем кнопку Broadcast Intent, это будет транслировать наше пользовательское намерение "com.tutorialspoint.CUSTOM_INTENT", которое будет перехвачено нашим зарегистрированным BroadcastReceiver, т.е. MyReceiver, и в соответствии с наша реализованная логика, тост появится в нижней части симулятора следующим образом —

Android Broadcast Intent

Вы можете попробовать реализовать другой BroadcastReceiver для перехвата генерируемых системой намерений, таких как загрузка системы, изменение даты, низкий заряд батареи и т. д.

Android Broadcast Receivers for Beginners

Допустим, у вас есть приложение, для работы которого требуется стабильное подключение к Интернету. Вы хотите, чтобы ваше приложение получало уведомления при изменении подключения к Интернету. Как вы это делаете?

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

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

Фон

Приемники широковещательных сообщений — это компоненты вашего приложения для Android, которые прослушивают широковещательные сообщения (или события) из разных источников:

  • Из других приложений
  • Из самой системы
  • Из вашего приложения

Это означает, что они вызываются, когда происходит определенное действие, которое они запрограммировали прослушивать (т.е. трансляция).

Рассылка — это просто сообщение, заключенное в объект Intent. Широковещательная рассылка может быть неявной или явной.

  • Неявная широковещательная рассылка – это трансляция, которая не нацелена конкретно на ваше приложение, поэтому она не является эксклюзивной для вашего приложения. Чтобы зарегистрироваться для него, вам нужно использовать IntentFilter и объявить его в своем манифесте. Вам нужно сделать все это, потому что операционная система Android просматривает все заявленные фильтры намерений в вашем манифесте и проверяет, есть ли совпадения. Из-за этого поведения неявные широковещательные рассылки не имеют целевого атрибута. Примером неявной трансляции может быть действие входящего SMS-сообщения.
  • явная широковещательная рассылка — это рассылка, предназначенная специально для вашего приложения на известном заранее компоненте. Это происходит из-за целевого атрибута, который содержит имя пакета приложения или имя класса компонента.

Есть два способа объявить получателя:

  1. Объявляя его в файле AndroidManifest.xml с помощью тега (также называемого статическим)

Вы заметите, что объявленный выше широковещательный приемник имеет свойство exported="true".Этот атрибут сообщает получателю, что он может получать широковещательные сообщения из-за пределов области приложения.

<р>2. Или динамически путем регистрации экземпляра с помощью registerReceiver (так называемая регистрация контекста)

Как реализовать широковещательный приемник в Android

Чтобы создать собственный широковещательный приемник, необходимо сначала расширить родительский класс BroadcastReceiver и переопределить обязательный метод onReceive:

Соединив все вместе, мы получим:

⚠️ Метод onReceive выполняется в основном потоке, поэтому его выполнение должно быть кратким.

Если выполняется длительный процесс, система может завершить процесс после возврата из метода. Чтобы обойти это, рассмотрите возможность использования goAsync или планирования задания. Подробнее о планировании задания можно прочитать в конце этой статьи.

Пример динамической регистрации

Чтобы зарегистрировать приемник с контекстом, вам сначала нужно создать экземпляр вашего широковещательного приемника:

Затем вы можете зарегистрировать его в зависимости от желаемого контекста:

Не забудьте отменить регистрацию вещательного приемника, когда он вам больше не нужен:

Как транслировать событие на Android

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

Подумайте о сценарии, в котором в одной части кода пользователь выполняет определенное действие, и из-за этого вы хотите выполнить другую логику в другом месте.

Есть три способа отправки трансляций:

  1. Метод sendOrderedBroadcast обеспечивает отправку широковещательных сообщений только одному получателю за раз. Каждая широковещательная рассылка может, в свою очередь, передавать данные следующей за ней или останавливать распространение широковещательной рассылки к последующим получателям.
  2. Способ sendBroadcast аналогичен упомянутому выше методу с одним отличием. Все широковещательные приемники получают сообщение и не зависят друг от друга
  3. Метод LocalBroadcastManager.sendBroadcast отправляет широковещательные сообщения только получателям, определенным внутри вашего приложения, и не выходит за рамки вашего приложения.

Подводные камни и вещи, на которые следует обратить внимание

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

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

  • 7.0 и более поздние версии (уровень API 24) — два системных вещания были отключены, Action_New_Picture и Action_New_Video (но они были возвращены в Android O для зарегистрированных получателей)< /li>
  • 8.0 и более поздние версии (уровень API 26). Большинство неявных трансляций необходимо регистрировать динамически, а не статически (в манифесте). Вы можете найти трансляции, которые были внесены в белый список, по этой ссылке.
  • 9.0 и выше (уровень API 28)– Меньше информации, получаемой при широковещании системы Wi-Fi и Network_State_Changed_Action.

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

Альтернативы широковещательным приемникам

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

  • LocalBroadcastManager. Как я упоминал выше, это действительно только для широковещательных передач внутри вашего приложения.
  • Планирование задания. Задание может запускаться в зависимости от полученного сигнала или триггера, поэтому вы можете обнаружить, что трансляция, которую вы слушали, может быть заменена работа. Кроме того, JobScheduler гарантирует, что ваша работа будет завершена, но он будет учитывать различные системные факторы (время и условия), чтобы определить, когда она должна выполняться.При создании задания вы переопределяете метод с именем onStartJob. Этот метод работает в основном потоке, поэтому убедитесь, что он завершает свою работу за ограниченное время. Если вам нужно выполнить сложную логику, рассмотрите возможность запуска фоновой задачи. Кроме того, возвращаемое значение для этого метода является логическим, где true означает, что определенные действия все еще выполняются, а false означает, что задание выполнено.

Если вы хотите на собственном опыте испытать радость и удивление от широковещательных приемников, вы можете перейти по этим ссылкам на репозитории, которые я установил:

< бр />

Теперь доступна новая версия этого курса, обновленная с учетом передового опыта для последних версий платформы Android и Android Studio. Новый курс доступен в разделе «Основы Android-разработчика» (версия 2) или в справочнике по новым концепциям.

Этот курс устарел, и вскоре его содержимое будет удалено с этого сайта. Пожалуйста, обновите свои ссылки.

Содержание:

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

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

Трансляция намерений

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

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

  • Намерения широковещательной рассылки доставляются с помощью sendBroadcast() или связанного метода, в то время как намерения других типов используют startActivity() для запуска действий. Когда вы транслируете намерение, вы никогда не находите и не начинаете действие. Точно так же получатель широковещательной рассылки не может увидеть или зафиксировать намерения, используемые с startActivity() .
  • Намерение широковещательной рассылки — это фоновая операция, о которой пользователь обычно не знает. С другой стороны, запуск действия с намерением — это операция переднего плана, которая изменяет то, с чем пользователь взаимодействует в данный момент.

Существует два типа широковещательных намерений: те, которые предоставляются системой (системные широковещательные намерения), и те, которые доставляет ваше приложение (настраиваемые широковещательные намерения).

Системные широковещательные намерения

Система отправляет системное широковещательное намерение, когда происходит системное событие, которое может заинтересовать ваше приложение. Например:

  • При загрузке устройства система отправляет широковещательное намерение системы ACTION_BOOT_COMPLETED. Это намерение содержит постоянное значение «android.intent.action.BOOT_COMPLETED».
  • Когда устройство подключено к внешнему источнику питания, система отправляет ACTION_POWER_CONNECTED, который содержит постоянное значение «android.intent.action.ACTION_POWER_CONNECTED». Когда устройство отключено от внешнего источника питания, система отправляет ACTION_POWER_DISCONNECTED .
  • Когда на устройстве заканчивается память, система отправляет ACTION_DEVICE_STORAGE_LOW . Это намерение содержит постоянное значение "android.intent.action.DEVICE_STORAGE_LOW" .

ACTION_DEVICE_STORAGE_LOW — это фиксированная широковещательная рассылка, что означает, что значение широковещательной рассылки хранится в кеше. Если вам нужно знать, обрабатывает ли ваш широковещательный приемник значение, находящееся в кеше (закрепленное), или значение, которое транслируется в настоящий момент, используйте isInitialStickyBroadcast() .

Подробнее об общих системных широковещательных рассылках см. в справочнике по намерениям.

Чтобы получать системные широковещательные намерения, необходимо создать широковещательный приемник.

Пользовательские намерения трансляции

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

Чтобы создать пользовательское намерение трансляции, создайте действие пользовательского намерения. Чтобы доставить пользовательскую трансляцию другим приложениям, передайте намерение в sendBroadcast() , sendOrderedBroadcast() или sendStickyBroadcast() . (Подробнее об этих методах см. в справочной документации по контексту.)

Например, следующий метод создает намерение и передает его всем заинтересованным получателям широковещательной рассылки:

Примечание. Когда вы указываете действие для намерения, используйте свое уникальное имя пакета ( com.example.myproject в примере), чтобы убедиться, что ваше намерение не конфликтует с намерением, которое транслируется из другого приложения или из система.

Вещательные приемники

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

Используйте широковещательные приемники, чтобы отвечать на сообщения, которые транслируются из других приложений или из системы. Чтобы создать широковещательный приемник:

    Определите подкласс класса BroadcastReceiver и реализуйте метод onReceive().

Зарегистрируйте широковещательный приемник либо динамически в Java, либо статически в файле манифеста вашего приложения.

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

Эти шаги описаны ниже.

Определить подкласс BroadcastReceiver

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

В вашем определении подкласса:

  • Реализуйте требуемый метод onReceive().
  • Включите любую другую логику, необходимую вашему вещательному приемнику.

Пример: создание широковещательного приемника

В этом примере подкласс AlarmReceiver класса BroadcastReceiver показывает всплывающее сообщение, если намерение входящей рассылки имеет действие ACTION_SHOW_TOAST :

Примечание. Не используйте асинхронные операции в реализации onReceive(), поскольку после возврата кода из onReceive() система считает объект BroadcastReceiver завершенным. Если бы onReceive() запускал асинхронную операцию, система уничтожила бы процесс BroadcastReceiver до того, как асинхронная операция успела завершиться.

Если вам нужна длительная операция, не требующая пользовательского интерфейса, используйте службу, запускаемую из широковещательного приемника. В частности:

  • Вы не можете отобразить диалог из BroadcastReceiver . Вместо этого используйте API NotificationManager.
  • Вы не можете привязаться к службе из BroadcastReceiver . Вместо этого используйте Context.startService() для отправки команды службе.

Регистрация вещательного приемника и настройка фильтров намерений

Есть два способа зарегистрировать широковещательный приемник: статически в манифесте или динамически в вашей активности.

Статическая регистрация

Чтобы зарегистрировать широковещательный приемник статически, добавьте элемент в файл AndroidManifest.xml. Внутри элемента:

  • Используйте путь к подклассу BroadcastReceiver в качестве атрибута android:name.
  • Чтобы другие приложения не могли отправлять широковещательные сообщения на ваш приемник, установите для необязательного атрибута android:exported значение false . Это важное правило безопасности.
  • Чтобы указать типы намерений, которые прослушивает компонент, используйте вложенный элемент.

Пример: статическая регистрация и фильтр намерений для пользовательского намерения трансляции

Следующий фрагмент кода является примером статической регистрации для приемника широковещательной рассылки, который прослушивает пользовательское намерение широковещательной рассылки с " ACTION_SHOW_TOAST " в имени своего действия:

  • Имя приемника – это имя модуля плюс имя подкласса BroadcastReceiver, определенного выше ( AlarmReceiver ).
  • Приемник не экспортируется, а это означает, что никакие другие приложения не могут доставлять трансляции в это приложение.
  • Получатель включает фильтр намерений, который проверяет, включают ли входящие намерения действие с именем ACTION_SHOW_TOAST .

Фильтры намерений

Когда система получает неявное намерение начать действие, она ищет наилучшее действие для этого намерения, сравнивая его с фильтрами намерений по трем аспектам:

  • Действие. Соответствует ли действие, указанное в намерении, одному из названий, перечисленных в фильтре? В приведенном выше примере фильтру соответствуют только намерения с ACTION_SHOW_TOAST в названии действия.
  • Данные. Соответствуют ли данные в намерении одному из типов, перечисленных в фильтре?
  • Категория. Каждая ли категория в намерении соответствует названию, указанному в фильтре?

Пример: фильтр намерений для системного широковещательного намерения

В этом примере показан фильтр намерений для приемника, который ожидает завершения загрузки устройства:

Чтобы узнать больше об использовании фильтров намерений для выбора намерений, см. раздел "Разрешение намерений" руководства по намерениям.

Если фильтры намерений не указаны, приемник широковещательной рассылки может быть активирован только с явным намерением широковещательной рассылки, в котором компонент именуется по имени. (Это похоже на то, как вы запускаете действия по имени их класса с явными намерениями.)

Если вы используете статическую регистрацию для своего широковещательного приемника, система Android создает новый процесс для запуска вашего широковещательного приемника, если никакие процессы, связанные с вашим приложением, не запущены. Это означает, что получатель ответит, даже если ваше приложение не запущено.

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

Вы также можете динамически зарегистрировать широковещательный приемник, что привяжет его работу к жизненному циклу вашей деятельности. Чтобы динамически зарегистрировать приемник, вызовите registerReceiver() и передайте объект BroadcastReceiver и фильтр намерений. Например:

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

Вам также необходимо отменить регистрацию приемника, вызвав unregisterReceiver() и передав свой объект BroadcastReceiver. Например:

То, где вы вызываете эти методы, зависит от желаемого жизненного цикла вашего объекта BroadcastReceiver:

  • Если приемник нужен только тогда, когда ваша активность видна (например, чтобы отключить сетевую функцию, когда сеть недоступна), зарегистрируйте приемник в onResume() . Отмените регистрацию получателя в onPause() .
  • Вы также можете использовать пары методов onStart() / onStop() или onCreate()/onDestoy(), если они больше подходят для вашего случая использования.

Правила безопасности

При использовании широковещательных намерений и широковещательных приемников информация пересылается между приложениями, что создает угрозу безопасности. Чтобы избежать этих рисков, вы можете использовать LocalBroadcastManager (описано ниже) или следовать этим рекомендациям:

  • Убедитесь, что имена действий намерения и другие строки находятся в принадлежащем вам пространстве имен, иначе вы можете непреднамеренно конфликтовать с другими приложениями. Пространство имен намерений является глобальным.
  • При использовании registerReceiver() любое приложение может отправлять широковещательные сообщения этому зарегистрированному получателю. Чтобы контролировать, кто может отправлять на него трансляции, используйте разрешения, описанные ниже.
  • При статической регистрации широковещательного приемника любое другое приложение может отправлять на него широковещательные сообщения независимо от указанных вами фильтров. Чтобы другие пользователи не могли отправлять ему сообщения, сделайте его недоступным для них с помощью android:exported="false" .
  • При использовании sendBroadcast() или связанных с ним методов любое другое приложение может получать ваши трансляции. Чтобы контролировать, кто может получать такие трансляции, используйте разрешения, описанные ниже.

Как отправитель, так и получатель трансляции могут применять права доступа:

Чтобы применить разрешение при отправке широковещательной рассылки, укажите ненулевой аргумент разрешения для sendBroadcast() .

Только получатели, которым было предоставлено это разрешение (запросив его с помощью тега в своем AndroidManifest.xml), могут получать трансляцию.

Чтобы применить разрешение при получении трансляции, предоставьте ненулевое разрешение при регистрации приемника либо при вызове registerReceiver(), либо в статическом теге в файле AndroidManifest.xml.

Только вещатели, получившие это разрешение (запросив его с помощью тега в своем файле AndroidManifest.xml), смогут отправить намерение получателю. Получатель должен запросить разрешение в манифесте независимо от того, зарегистрирован ли отправитель статически или динамически.

LocalBroadcastManager

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

Отправка локальных трансляций

Чтобы отправить широковещательную рассылку с помощью LocalBroadcastManager:

  1. Получите экземпляр LocalBroadcastManager, вызвав getInstance() и передав контекст приложения.
  2. Вызовите sendBroadcast() для экземпляра, передав намерение, которое вы хотите транслировать.

Регистрация ресивера для местных трансляций

Чтобы зарегистрировать ресивер для приема только местных трансляций:

  1. Получите экземпляр LocalBroadcastManager, вызвав getInstance() и передав контекст приложения.
  2. Вызвать registerReceiver() , передав приемник и фильтр намерений, как если бы вы использовали обычный широковещательный приемник. Вы должны регистрировать локальные получатели динамически, поскольку статическая регистрация в манифесте недоступна.

Чтобы отменить регистрацию широковещательного приемника:

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

Соответствующие упражнения и практическая документация находятся в разделе Основы разработчика Android: практические занятия.

Читайте также: