Как происходит обмен информацией между приложениями через BroadcastReceiver и Intents в Android
Что проверяют
Знаете ли вы, как broadcast работает в современных версиях Android, а не во времена API 21. Следом спрашивают, почему ресивер из манифеста не получает сообщение от другого приложения и как ограничить круг отправителей.
Как отвечать
Сначала механика, затем ограничения:
- Intent: действие плюс данные в
extras. Явный указывает компонент или пакет (setComponent,setPackage), неявный только action, и система ищет подходящие фильтры; - отправка:
sendBroadcast()рассылает всем подходящим получателям,sendOrderedBroadcast()передаёт по очереди по приоритету, и получатель может прервать цепочку; - получение: ресивер объявляется в манифесте или регистрируется в коде через
registerReceiver().onReceive()выполняется в главном потоке, долгая работа там приводит к ANR, для неё естьgoAsync()или WorkManager; - Android 8.0 (API 26): ресиверы из манифеста больше не получают неявные broadcast, кроме короткого списка системных вроде
BOOT_COMPLETED. Между приложениями отправитель делает интент явным черезsetPackage(), либо получатель регистрирует ресивер в коде; - Android 12 (API 31): у компонента с intent-filter атрибут
android:exportedобязателен; - Android 14 (API 34): при регистрации в коде нужно указать
RECEIVER_EXPORTEDилиRECEIVER_NOT_EXPORTED, иначе будетSecurityException. Удобно черезContextCompat.registerReceiver().
Безопасность: sendBroadcast(intent, permission) и своё разрешение с protectionLevel="signature" оставляют обмен только приложениям с вашей подписью. Большие данные в extras не кладут: у Binder лимит около мегабайта, будет TransactionTooLargeException. Передают URI через FileProvider или ContentProvider.
Где спотыкаются
Советуют LocalBroadcastManager. Он объявлен устаревшим, внутри приложения его заменяют Flow или LiveData, а между приложениями он и не работал.
Не знают ограничений API 26 и 34 и не могут объяснить, почему пример из старой статьи молча не работает.
Берут broadcast для любого обмена. Для запросов с ответом лучше подходят привязанный сервис с AIDL или Messenger и ContentProvider, а broadcast остаётся для событий «что-то произошло».