Broadcast Receiver란?
안드로이드 개발자 사이트에서 Broadcast Receiver는 다음과 같이 설명하고 있다.
A broadcast receiver is a component that enables the system to deliver events to the app outside of a regular user flow, allowing the app to respond to system-wide broadcast announcements.
Link: Google Developer
즉, Broadcast Receiver는 시스템 또는 앱에서 발생한 이벤트에 대해 알림 역할을 수행한다. (e.g. 배터리 부족, 기기 충전)
Broadcast Receiver 수신
앱은 Manifest 선언 수신자와 Context 등록 수신자 두 가지 방법으로 브로드캐스트를 수신할 수 있다.
1. Manifest 선언 수신자
Manifest에 Broadcast Receiver를 선언하면 브로드캐스트가 전송될 때 앱이 아직 실행 중이 아니라면 시스템에서 앱을 실행한다.
1. 앱의 manifest에서 <receiver> 요소를 지정
<receiver android:name=".MyBroadcastReceiver" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.INPUT_METHOD_CHANGED" />
</intent-filter>
</receiver>
2. BroadcastReceiver 서브클래스를 선언하고 onReceiver(Context, Intent) 메서드를 구현
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)
Toast.makeText(context, log, Toast.LENGTH_LONG).show()
}
}
}
}
2. Context 등록 수신자
1. BroadcastReceiver 인스턴스를 생성
val br: BroadcastReceiver = MyBroadcastReceiver()
2. IntentFilter를 생성하고 registerReceiver()를 호출하여 수신자 등록
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
}
registerReceiver(br, filter)
3. 수신자가 더 이상 필요하지 않거나 Context가 더 이상 유효하지 않으면 unregisterReceiver()를 호출하여 등록을 취소
unregisterReceiver(br)
Broadcast Receiver 전송
Android는 브로드캐스트를 전송하는 세 가지 방법을 제공한다.
1. sendOrderedBroadcast(Intent, String)
한 번에 하나의 수신자에 브로드캐스트를 전송한다. 각 수신자는 차례로 실행되기 때문에 결과를 다음 수신자로 전파할 수 있다.
/* android.content.Context */
abstract fun sendOrderedBroadcast(
intent: Intent!,
receiverPermission: String?
): Unit
Parameters
Parameters | Description |
---|---|
intent | Intent!: 브로드캐스트 인텐트, 인텐트와 일치하는 모든 리시버가 브로드캐스트를 수신한다. |
receiverPermission | String?: 선택적인 프로퍼티로 브로드캐스트 수신자가 보유해야 하는 사용 권한을 지정하는 문자열이다. null 값을 허용하며 null인 경우 권한이 필요없다. |
2. sendBroadcast(Intent)
정의되지 않은 순서로 모든 수신자에 브로드캐스트를 전송한다. 상당히 효율적이지만 수신자가 다른 수신자의 결과를 읽거나 수신한 데이터를 전파할 수 없다.
/* android.content.Context */
abstract fun sendBroadcast(intent: Intent!): Unit
Parameters
Parameters | Description |
---|---|
intent | Intent!: 브로드캐스트 인텐트, 인텐트와 일치하는 모든 리시버가 브로드캐스트를 수신한다. |
Example
Intent().also { intent ->
intent.setAction("com.example.broadcast.MY_NOTIFICATION")
intent.putExtra("data", "Notice me senpai!")
sendBroadcast(intent)
}
3. LocalBroadcastManager.sendBroadcast
발신자와 동일한 앱에 있는 수신자에 브로드캐스트를 전송한다. 앱 간에 브로드캐스트를 전송할 필요가 없을 때 사용한다.
/* androidx.localbroadcastmanager.content.LocalBroadcastManager */
fun sendBroadcast(@NonNull intent: Intent): Boolean
Parameters
Parameters | Description |
---|---|
intent | Intent!: 브로드캐스트 인텐트, 인텐트와 일치하는 모든 리시버가 브로드캐스트를 수신한다. |
Return
Return | Description |
---|---|
Boolean | 인텐트가 하나 이상의 브로드캐스트 리시버로 전송된 경우 true를 반환한다. |
권한으로 브로드캐스트 제한
Permissions을 통해 특정 권한을 보유한 앱 집합으로 브로드캐스트를 제한할 수 있다.
Permissions을 사용하여 전송
sendBroadcast() 또는 sendOrderedBroadcast()를 호출할 때 권한 매개변수를 지정할 수 있다.
Sending App Source Code
sendBroadcast(Intent("com.example.NOTIFY"), Manifest.permission.SEND_SMS)
Sending App Manifest
<uses-permission android:name="android.permission.SEND_SMS"/>
Permissions을 사용하여 수신
registerReceiver()에 권한 매개변수를 지정하거나 manifest의 <receiver> 태그를 사용하여 권한을 지정하면 <uses-permission> 태그를 사용하여 권한을 요청한 브로드캐스트만 리시버에 인텐트를 전송할 수 있다.
Receiving App Source Code
var filter = IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)
registerReceiver(receiver, filter, Manifest.permission.SEND_SMS, null)
Receiving App Manifest
<receiver
android:name=".MyBroadcastReceiver"
android:permission="android.permission.SEND_SMS">
<intent-filter>
<action android:name="android.intent.action.AIRPLANE_MODE"/>
</intent-filter>
</receiver>
Sending App Manifest
<uses-permission android:name="android.permission.SEND_SMS"/>
보안 고려사항 및 권장사항
앱 외부의 컴포넌트에 브로드캐스트를 전송할 필요가 없다면 Support Library(androidx)에서 제공하는 LocalBroadcastManager를 사용하여 전송 및 수신한다.
여러 앱이 자체 manifest에서 동일한 브로드캐스트를 수신하도록 등록하면 시스템에서 많은 앱을 실행하게 되며 기기 성능과 사용자 환경 모두에 상당한 영향을 줄 수 있다. manifest 선언보다 context 등록으로 사용하는 것이 좋다.
브로드캐스트 작업의 네임스페이스는 전역이다. 작업 이름 및 기타 문자열이 고유한 네임스페이스에 작성되었는지 확인해야 한다. 의도하지 않게 다른 앱과 충돌할 수 있다.
둘 이상의 리시버가 있다면 사용자 환경에 충돌이 발생하기 때문에 Broadcast Receiver에서 활동을 시작하지 않고 notification을 고려해야 한다.
참고 사이트
'Android > Components' 카테고리의 다른 글
[안드로이드] App Components - Content Provider (0) | 2021.06.08 |
---|---|
[안드로이드] App Components - Service (0) | 2021.05.27 |
[안드로이드] App Components - Activity (0) | 2021.01.17 |