안드로이드 시스템 및 다른 안드로이드 앱에서 브로드캐스트 메시지를 주고받을 수 있음.
예시
시스템은 충전중이거나 배터리 부족, 사진이 캡쳐되었음을 알리는 브로드캐스트를 시작하고 리시버가 이를 수신한다.
앱이 특정 브로드캐스트를 수신하도록 등록할 수 있고, 브로드캐스트가 전송되면 시스템은 특정 유형의 브로드캐스트 수신을 등록한 앱에게 자동으로 브로드캐스트를 라우팅함.
유저 플로우가 아닌 앱 전반에서 메시징 시스템으로 사용할 수 있음.
브로드캐스트 메시지는 발생한 이벤트를 식별하는 액션 문자열이 포함된 인텐트 객체로 래핑됨.
(ex: android.intent.action.AIRPLANE_MODE)
브로드 캐스트를 수신하는데에는 매니페스트에 리시버를 등록하거나 context에 리시버를 등록하는 두 가지 방법이 있다.
매니페스트에서 브로드캐스트 리시버를 선언하면 브로드캐스트가 전송될 때 시스템이 앱을 실행함.
<receiver>
요소를 지정.<receiver android:name=".MyBroadcastReceiver" android:exported="false">
<intent-filter>
<action android:name="APP_SPECIFIC_BROADCAST" />
</intent-filter>
</receiver>
private const val TAG = "MyBroadcastReceiver"
class MyBroadcastReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
StringBuilder().apply {
append("Action: ${intent.action}\n")
append("URI: ${intent.toUri(Intent.URI_INTENT_SCHEME)}\n")
toString().also { log ->
Log.d(TAG, log)
val binding = ActivityNameBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
Snackbar.make(view, log, Snackbar.LENGTH_LONG).show()
}
}
}
}
시스템 패키지 관리자가 앱이 설치될때 리시버를 등록함. 리시버는 앱에 대한 별도의 진입점이 되어 앱이 실행중이 아닌 경우 시스템에서 앱을 시작하고 브로드캐스트를 전달할 수 있음.
컨텍스트에 등록된 리시버는 컨텍스트가 유효할 동안 브로드캐스트를 수신할 수 있다. 예를 들어 액티비티에 리시버를 등록할 경우 액티비티가 파괴되지 않는 이상 브로드캐스트를 수신하며 앱 컨텍스트에 등록하는 경우 앱이 실행중일 동안 브로드캐스트를 수신한다.
앱 모듈 수준 빌드 파일에 AndroidX 코어 라이브러리 버전 1.9.0 이상을 포함한다.
BroadcastReceiver 인스턴스를 생성한다.
val br: BroadcastReceiver = MyBroadcastReceiver()
val filter = IntentFilter(APP_SPECIFIC_BROADCAST)
val listenToBroadcastsFromOtherApps = false
val receiverFlags = if (listenToBroadcastsFromOtherApps) {
ContextCompat.RECEIVER_EXPORTED
} else {
ContextCompat.RECEIVER_NOT_EXPORTED
}
registerReceiver()
를 통해 리시버를 등록한다.ContextCompat.registerReceiver(context, br, filter, receiverFlags)
unregisterReceiver(android.content.BroadcastReceiver)
를 호출.포그라운드 프로세스는 리시버의 onReceive() 메소드를 실행.
브로드캐스트 리시버는 onReceive() 이후 비활성화 됨.
프로세스가 매니페스트에 선언된 리시버만 호스트하는 경우 시스템은 다른 프로세스에 리소스를 제공하기 위해 onReceive() 이후에 해당 프로세스를 종료할 수 있음.
따라서 브로드캐스트 리시버는 장기 실행 백그라운드 스레드를 시작해서는 안됨. 프로세스를 계속 유지하기 위해서는 JobScheduler를 이용하여 시스템이 프로세스가 계속 작동중임을 알 수 있게 해야함.
한 번에 하나의 리시버에게 브로드캐스트를 전송. 리시버의 실행 순서는 일치하는 인텐트 필터의 android:priority 속성으로 제어하며 같은 우선순위를 가진 리시버는 임의의 순서로 실행됨.
정의되지 않은 순서로 모든 리시버에게 브로드캐스트를 보냄. (Normal Broadcast)
효율적인 방법이지만 리시버가 다른 리시버의 결과를 읽을 수 없고 브로드캐스트에서 수신한 데이터를 전파할 수 없으며 브로드캐스트를 중단할 수 없는 단점이 있음.
Intent().also { intent ->
intent.setAction("com.example.broadcast.MY_NOTIFICATION")
intent.putExtra("data", "Nothing to see here, move along.")
sendBroadcast(intent)
}
브로드캐스트 메시지는 인텐트 객체로 래핑. putExtra(String, Bundle)
로 추가 정보 첨부 가능.
퍼미션을 이용하여 특정 권한을 가진 앱들로 브로드캐스트를 제한할 수 있음.
sendBroadcast(Intent, String)
또는 sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
를 호출할 때 권한 파라미터를 지정할 수 있음. 해당 퍼미션을 요청한 리시버만 브로드캐스트 수신 가능.sendBroadcast(Intent(BluetoothDevice.ACTION_FOUND),
Manifest.permission.BLUETOOTH_CONNECT)
<receiver android:name=".MyBroadcastReceiver"
android:permission="android.permission.BLUETOOTH_CONNECT">
<intent-filter>
<action android:name="android.intent.action.ACTION_FOUND"/>
</intent-filter>
</receiver>
또는 컨텍스트에 리시버 등록
var filter = IntentFilter(Intent.ACTION_FOUND)
registerReceiver(receiver, filter, Manifest.permission.BLUETOOTH_CONNECT, null)
그리고 브로드캐스트를 보내는 앱과 수신하는 앱에서 다음과 같이 권한을 설정해줘야함.
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
좋은 글 감사합니다~