안드로이드에서 Broadcast Receiver는 앱 구성 요소 중 하나로, 다른 앱이나 시스템에서 발생한 브로드캐스트 메시지를 수신하는 역할을 합니다.
브로드캐스트 메시지는 시스템에서 발생하는 다양한 이벤트를 의미하며, 예를 들어 배터리 부족, 네트워크 상태 변경, 앱 설치/제거 등의 이벤트가 포함됩니다. 이러한 이벤트는 시스템이나 다른 앱에서 발생할 수 있으며, Broadcast Receiver는 이러한 이벤트를 수신하여 적절한 처리를 할 수 있습니다.
Broadcast Receiver는 안드로이드의 시스템 브로드캐스트를 수신하는 것 외에도, 개발자가 정의한 앱에서 발생시키는 브로드캐스트 메시지도 수신할 수 있습니다. 이를 통해 앱 내에서 이벤트를 처리하거나, 다른 앱에 메시지를 전달하는 등의 다양한 작업을 수행할 수 있습니다.
Android 4대 컴포넌트 중 Broadcast Recevier만 동적으로 등록할 수 있습니다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<application
...>
<receiver
android:name=".LocaleChangeReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.LOCALE_CHANGED" />
</intent-filter>
</receiver>
...
</application>
</manifest>
class LocaleChangeReceiver : BroadcastReceiver() {
// broadcast에서 보낸 intent
override fun onReceive(context: Context, intent: Intent) {
Log.d("LocaleChangedRecevier", "onReceive: receive 받기: ${intent.action}")
}
}
Settings -> System > Languages & input -> Languages
안드로이드에서 암시적 브로드캐스트(implicit broadcast)는 BroadcastReceiver를 사용하여 시스템에서 발생하는 특정 이벤트를 수신하는 것을 의미합니다. 암시적 브로드캐스트는 명시적(explicit) 브로드캐스트와는 달리 특정한 액션(action)을 지정하지 않고, 그냥 인텐트(intent) 객체를 사용하여 전체 시스템에 브로드캐스트됩니다.
하지만, 안드로이드 시스템에서 모든 암시적 브로드캐스트를 수신하는 것은 안전하지 않을 수 있습니다. 왜냐하면 다른 애플리케이션에서 브로드캐스트를 발생시키면 해당 앱에서 수신할 수 있기 때문입니다. 따라서 Android 8.0(Oreo)부터는 암시적 브로드캐스트의 사용을 제한하고, 보안상 이유로 일부 브로드캐스트는 명시적으로 전달해야 합니다.
따라서, 안드로이드 앱을 개발할 때, 가능한한 명시적 브로드캐스트를 사용하도록 권장됩니다. 또한, 안드로이드 8.0 이상에서는 암시적 브로드캐스트 예외를 방지하기 위해 명시적으로 수신자(receiver)를 등록해야 합니다.
class BroadcastActivity : AppCompatActivity() {
lateinit var receiver:BroadcastReceiver
@RequiresApi(Build.VERSION_CODES.O)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_broadcast)
setTitle("BroadcastActivity")
/***** Screen On/Off *******/
val intentFilter2 = IntentFilter(Intent.ACTION_SCREEN_OFF)
intentFilter2.addAction(Intent.ACTION_SCREEN_ON)
receiver = object: BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val action = intent.action
Log.d(TAG, "receive : $action")
when (action) {
Intent.ACTION_SCREEN_ON -> {
// do something
Log.d(TAG,"ACTION_SCREEN_ON");
}
Intent.ACTION_SCREEN_OFF -> {
// do something
Log.d(TAG,"ACTION_SCREEN_OFF");
}
}
}
}
// 시스템에게 intentFilter2에 해당하는 이벤트가 오면 receiver를 실행시켜달라고 등록
registerReceiver(receiver, intentFilter2);
/***** Screen On/Off *******/
}
override fun onDestroy() {
super.onDestroy()
// 리시버 등록을 해제
unregisterReceiver(receiver)
}
}
<receiver android:name=".CustomReceiver" android:enabled="true" android:exported="false" >
<intent-filter>
<!-- 사용자 정의 broadcast 수신 -->
<action android:name="custom.MY" />
</intent-filter>
</receiver>
class MainActivity : AppCompatActivity() {
private lateinit var broadcastBtn: Button
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
broadcastBtn = findViewById(R.id.broadcast_btn)
broadcastBtn.setOnClickListener {
val intent = Intent(this, CustomReceiver::class.java)
intent.action = "custom.MY"
intent.putExtra("content", "custom recevier 테스요~~.")
sendBroadcast(intent)
Log.d("CustomReceiver", "onCreate: 발송 완료")
}
}
}
class CustomReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
Log.d("CustomReceiver", "onReceive: receive 받기: ${intent.action}")
Log.d("CustomReceiver", "onReceive: extra: ${intent.getStringExtra("content")}")
}
}