Broadcast Receiver 란?

berry·2023년 5월 8일
0

브로드캐스트란?

안드로이드 공식 문서에서 말하는 브로드캐스트

Android 앱은 Android 시스템 및 기타 Android 앱에서 게시-구독 디자인 패턴과 유사한 브로드캐스트 메시지를 받거나 보낼 수 있습니다. 관심 있는 이벤트가 발생할 때 이러한 브로드캐스트가 전송됩니다. 예를 들어 Android 시스템은 시스템 부팅 또는 기기 충전 시작과 같은 다양한 시스템 이벤트가 발생할 때 브로드캐스트를 전송합니다. 또한 앱은 맞춤 브로드캐스트를 전송하여 다른 앱이 관심을 가질만한 사항(예: 일부 새로운 데이터가 다운로드됨)을 관련 앱에 알릴 수 있습니다.

시스템에서 발생할 수 있는 다양한 이벤트를 브로드 캐스트라고 한다. 안드로이드 앱은 시스템이나 다른 앱으로부터 오는 브로드캐스트 메시지를 받거나 보낼 수 있다.
예를 들어, 시스템 부팅 또는 기기 충전 시작과 같은 시스템 이벤트가 발생할 때 브로드캐스트를 전송한다.
시스템 브로드 캐스트 뿐만 아니라 custom 브로드캐스트 또한 전송 가능하다.

브로드캐스트 리시버란?

앱은 특정 브로드캐스트를 수신하도록 브로드캐스트 리시버라는 것을 등록할 수 있다. 브로드캐스트가 전송되면 시스템은 특정 유형의 브로드캐스트 리시버에 브로드캐스트를 자동으로 라우팅한다.

리시버 등록 방법

앱은 두 가지 방식, 즉 manifest 에 선언된 리시버 및 context 에 등록된 리시버를 통해 브로드캐스트를 수신할 수 있다.

manifest 등록

manifest 에 브로드캐스트 리시버를 선언하면 앱 전반에 걸쳐서 브로드캐스트를 수신한다. 브로드캐스트가 전송될 때 앱이 아직 실행 중이 아니어도 시스템에서 앱을 실행하기 때문에 브로드캐스트를 받을 수 있다.

  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>

인텐트 필터는 리시버가 수신할 브로드캐스트를 지정한다.

  1. BroadcastReceiver 클래스를 상속받아 onReceive 함수를 오버라이딩해서 브로드캐스트를 수신했을 때 수행될 로직을 작성한다.
    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()
                }
            }
        }
    }

manifest 에 리시버를 등록하면 앱이 설치될 때 시스템 관리자가 리시버를 등록한다. 그러면 리시버가 앱으로 향하는 별도의 진입점이 된다. 즉, 앱이 실행되고 있지 않으면 시스템이 앱을 시작하고 브로드캐스트를 전달할 수 있다는 뜻이다.

주의할 점:

안드로이드 8.0(API 레벨 26) 이상을 타켓팅하는 앱은 앱 manifest 에 있는 암시적 브로드캐스트에 대해서는 브로드캐스트 리시버를 더 이상 등록할 수 없다. 암시적 브로드캐스트란 특정 앱을 대상으로 하지 않는 브로드캐스트로, 인텐트와 관련된 모든 리시버에게 전달되는 브로드캐스트를 말한다. 해당 브로드캐스트를 리시브하는 모든 앱들이 실행되어 리소스가 낭비될 수 있기 때문에 안드로이드에서는 백그라운드 실행 제한의 일환으로 이를 제한한다. 단, 예외 브로드캐스트 존재

manifest 에 리시버를 등록하고 정상적으로 브로드캐스트를 수신하기 위해서는 브로드캐스트를 보낼 때 Intent 에 setPackage(String packageName) 메소드를 통해 같은 앱 내부로만 브로드캐스트를 제한할 수 있다. (getApplicationPackageName() 으로 패키지 이름 얻어올 수 있음)

context 등록

이 방법은 직접 코드로 컨텍스트에 리시버를 등록하는 방법이다.
1. BroadcastReceiver 인스턴스를 생성한다.

val br: BroadcastReceiver = MyBroadcastReceiver()
  1. IntentFilter 를 생성하고 registerReceiver 함수를 이용해 리시버를 등록한다.
val filter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION).apply {
        addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED)
    }
    registerReceiver(br, filter)

컨텍스트에 등록된 리시버는 해당 컨텍스트가 유효한 동안 브로드캐스트를 수신한다. 만약 Activity Context 에 등록하면 Activity 가 Destroy 되면 브로드캐스트를 수신하지 않는다.

주의할 점:

context 에 리시버를 등록할 때는 리시버가 더이상 필요하지 않거나 context 가 유효하지 않은 경우 unregisterReceiver 메소드를 이용해서 수신자의 등록을 취소해야된다. 취소하지 않으면 리시버가 여러 번 등록되는 오류가 발생할 수 있다.
리비서의 등록 및 등록 취소 위치의 예시는 다음과 같다.

  • onCreate 등록 -> onDestroy 해제
  • onResume 등록 -> onPause 해제

단, onSaveInstanceState 에서 등록을 취소해서는 안되는데, 그 이유는 이 메소드가 항상 호출된다는 보장이 없기 때문이다.

브로드캐스트 전송

Intent(컴포넌트 간 작업 수행을 위한 정보를 전달하는 역할) 를 이용해서 브로드캐스트를 전송할 수 있다.
앱에서 브로드캐스트를 전송하는 방법은 세 가지가 있다.

  • sendOrderedBroadcast(Intent, String): 한 번에 하나의 리시버에 브로드캐스트를 전송하며, 각 리시버가 차례로 실행된다.
  • sendBroadcast(Intent): 일반 브로드캐스트 방법이다. 정의되지 않은 순서로 모든 리시버에 브로드캐스트를 전송한다.
  • LocalBroadcastManager.sendBroadcast: 발신자와 동일한 앱에 있는 수신자에 브로드캐스트를 전송한다. 앱 간에 브로드캐스트를 전송할 필요가 없다면 로컬 브로드캐스트를 사용하는게 훨씬 효율적이다.

sendBroadcast 예시

브로드캐스트 메시지를 Intent 객체에 래핑된다.
setAction 을 이용해서 브로드캐스트 이벤트를 지정해줄 수 있다. putExtra 를 사용하여 인텐트에 추가 정보를 첨부할 수 있다.

    Intent().also { intent ->
        intent.setAction("com.example.broadcast.MY_NOTIFICATION")
        intent.putExtra("data", "Notice me senpai!")
        sendBroadcast(intent)
    }
profile
공부 내용 기록

0개의 댓글