Ответ
BroadcastReceiver позволяет реагировать на системные или кастомные события. Пример: регистрация ресивера для события ACTION_AIRPLANE_MODE_CHANGED.
1. Объявление в манифесте:
<receiver android:name=".AirplaneModeReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
2. Класс ресивера:
class AirplaneModeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val isEnabled = Settings.Global.getInt(
context.contentResolver,
Settings.Global.AIRPLANE_MODE_ON
) != 0
Toast.makeText(context, "Airplane mode: $isEnabled", Toast.LENGTH_SHORT).show()
}
}
Важно: Для Android 8+ динамическая регистрация предпочтительнее:
val filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
registerReceiver(receiver, filter)
Не забудьте вызвать unregisterReceiver() в onDestroy().
Ответ 18+ 🔞
Э, слушай, смотри, вот тебе BroadcastReceiver — это такая штука, которая сидит и ждёт, пока система не начнёт орать на всё село о каком-нибудь событии. Типа самолётный режим включили или батарея сдохла. Ну, ёпта, как сторожевой пёс, только для интентов.
Вот, допустим, тебе нужно поймать момент, когда юзер включает этот ёперный театр с авиарежимом. Раньше, в старые добрые времена, ты просто прописывал это в манифесте, и всё, блядь, работало. Прямо как волшебство.
1. Объявление в манифесте (старый способ, но для некоторых случаев жив):
<receiver android:name=".AirplaneModeReceiver">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
Видишь? Прямо как объявление: «Слушай, система, у меня тут есть чувак по имени AirplaneModeReceiver, который хочет знать про авиарежим. Шли ему весточку, как что».
2. А сам этот чувак, ресивер, выглядит примерно так:
class AirplaneModeReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val isEnabled = Settings.Global.getInt(
context.contentResolver,
Settings.Global.AIRPLANE_MODE_ON
) != 0
Toast.makeText(context, "Airplane mode: $isEnabled", Toast.LENGTH_SHORT).show()
}
}
Вот он, красавец. Как только событие прилетело, вызывается onReceive. Тут мы лезем в настройки глобальные, смотрим, ноль там или единица, и показываем тост. Проще пареной репы, да?
НО! Вот тут-то и начинается, блядь, самое интересное. Начиная с Android 8 (Oreo), гугл такие: «А давайте-ка усложним им жизнь!». Статическая регистрация в манифесте для большинства системных событий накрылась медным тазом. Теперь, если твоё приложение не на экране, оно нихрена не услышит.
Поэтому теперь модно, круто и правильно регистрировать ресивер динамически, прямо в коде активити или сервиса:
val filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
registerReceiver(receiver, filter)
Сделал это, например, в onCreate() — и ты в теме. Ресивер живёт, пока живёт твой контекст.
И главное, блядь, не забудь! Это как взять в долг — нужно отдать. Если зарегистрировал в onCreate(), то обязательно сними его в onDestroy():
override fun onDestroy() {
super.onDestroy()
unregisterReceiver(receiver)
}
А то будет тебе утечка контекста, и приложение начнёт сосать память как не в себя, а потом просто вылетит с ошибкой. Сам от такого охуевал не раз. В общем, правило простое: что включил — то и выключи. И будет тебе счастье, а не пиздец.