본문 바로가기
깡샘 코틀린

14-1 브로드캐스트 리시버 이해하기

by 농농씨 2023. 7. 3.

브로드캐스트 리시버는 흔히 이벤트 모델로 실행되는 컴포넌트라고 정의한다. 여기서 이벤트란 액티비티를 다룰 때 살펴본 사용자 이벤트가 아니라 부팅이 완료되는 것과 같은 시스템의 특정한 상황을 말한다. 시스템의 어떤 이벤트가 발생하면 브로드캐스트 리시버를 실행해 앱이 해당 상황에 맞게 동작하도록 할 수 있다.

브로드캐스트 리시버(broadcast receiver)는 줄여서 리시버라고도 하며 직역하면 '방송 수신기'이다. 즉, 시스템에서 특정한 상황을 알리는 방송을 할 때 이를 받아서 처리하는 수신기를 앱에 장착하는 것이다. 이 수신기도 액티비티처럼 안드로이드의 컴포넌트이므로 인텐트를 시스템에 전달함으로써 실행한다.

 

브로드캐스트 리시버 만들기

브로드캐스트 리시버를 만들려면 BroadcastReceiver를 상속받는 클래스를 선언해야 한다. 또한 브로드캐스트 리시버의 생명주기 함수는 onReceive() 하나뿐이다. 어디선가 이 리시버를 실행하려고 인텐트를 시작하면 onReceive() 함수가 자동으로 호출되고, 자신을 호출한 인텐트 객체를 매개변수로 전달받는다.

// 브로드캐스트 리시버 만들기
class MyReceiver : BroadcastReceiver() {
	override fun onReceive(context: Context, intent: Intent) { 
    // 브로드캐스트 리시버의 유일한 생명주기 함수, 인텐트 실행하면 자동으로 호출됨. 이 함수가 실행 마치면 객체가 자동으로 소멸
    }
}

onReceive() 함수는 실행한 수 10초 이내에 완료할 것을 권장하므로 오래 걸리는 작업을 담당하기에는 부적절하다. onReceive() 함수가 실행을 마치면 브로드캐스트 리시버 객체는 소멸한다.

 

브로드캐스트 리시버도 컴포넌트이므로 매니페스트 파일에 등록한다. 브로드캐스트 리시버를 등록하는 태그는 <receiver>이며 필수 속성은 클래스명을 지정하는 name이다. 브로드캐스트 리시버를 명시적 인텐트로 실행하려면 클래스명만 등록하고, 암시적 인텐트이려면 <intent-flilter>를 선언해 줘야 한다.

// 브로드캐스트 리시버 등록
<receiver
    android:neame=".MyReceiver"
    android:enabled="true"
    android:exported="true"></receiver>

 

 

동적 등록과 해제

안드로이드 컴포넌트는 매니페스트에 등록해야 시스템에서 인지하고 어디선가 인텐트가 발생할 때 컴포넌트를 실행해 준다. 이러한 동작 방식은 브로드캐스트 리시버도 마찬가지지만. 매니페스트에 등록하지 않고. 코드에서 필요한 순간에 동적으로 등록할 수도 있다.

* 특정한 상호아에서 브로드캐스트 리시버를 항상 실행해야 한다면 매니페스트 파일에 등록해서 사용하면 된다. 그러나 특정한 액티비티나 서비스가 동작할 때만 브로드캐스트 리시버를 실행해야 한다면 해당 컴포넌트가 실행될 때는 동적으로 등록하는 방법을 사용한다.

다음 코드는 액티비티나 서비스 컴포넌트에서 작성한 코드이다.

// 리시버 객체 생성
val receirer = object : BroadcastReceiver { // 코드에서 변수로 브로드캐스트리시버 객체 생성
    override fun onReceive(context: Context?, intent: Intent?) {
    }
}

 

브로드캐스트 리시버 객체는 액티비티나 서비스에서 생성할 수도 있다. 그리고 필요한 순간에 다음처럼 registerReceiver()라는 함수를 이용해 시스템에 등록한다.

// 동적 등록
val filter = IntentFilter("ACTION_RECEIVER")
registerReceiver(receiver, filter) // 함수 이용해 리시버를 시스템에 동적으로 등록

이처럼 브로드캐스트 리시버를 코드에서 등록하면 매니페스트에 <receiver> 태그로 등록하지 않아도 시스템에서 리시버의 존재를 인지한다.

registerReceiver() 함수로 등록한 리시버는 사용한 후 필요 없으면 해제해 줘야 한다. 이때 unregisterReceiver() 함수를 이용한다.

// 브로드캐스트 리시버 해제 함수
unregisterReceiver(receiver)

 

브로드캐스트 리시버 실행하기

브로드캐스트 리시버를 실행하려면 인텐트가 필요하다. 리시버의 클래스명만 등록했으면 클래스 타입 레퍼런스를 이용해 명시적 인텐트로 실행하고, 인텐트 필터를 등록했으면 암시적 인텐트로 실행한다.

그런데 만약 리시버를 매니페스트 파일에 등록하고 <intent-filter> 태그를 선언했다면 암시적 인텐트로는 실행할 수 없다. (????) 물론 코드에서 registerReceiver() 함수로 등록한 리시버는 암시적 인텐트로도 잘 실행된다. 이는 백그라운드 제약과 관련된 내용으로, 이후 자세히 살펴보도록...

브로드캐스트 리시버를 실행하는 인텐트sendBroadcast() 함수로 시스템에 전달한다. 그러면 시스템은 브로드캐스트 리시버 객체를 생성하여 실행해 준다.

// 리시버 실행
val intent = Intent(this, MyReceiver::class.java) // 브로드캐스트 리시버 실행시키는 인텐트 객체 생성
sendBroadcast(intent) // 그 인텐트를 시스템에 함수로 전달

그런데 리시버와 액티비티 인텐트는 차이가 있다. 

구분 실행 대상 액티비티 수 동작
액티비티 인텐트 없음 오류 발생
1개 정상 실행
여러 개 사용자 선택으로 1개 실행
리시버 인텐트 없음 오류 발생하지 않음
1개 정상 실행
여러 개 모두 실행

액티비티는 실행할 인텐트가 있어야 하고, 여러개이면 한 개만 선택인데, 브로드캐스트 리시버 인텐트는 인텐트가 없으면 없는대로 오류가 발생하지 않고 여러개이면 다 실행한다. 이처럼 독특한 동작 원리 때문에 앱에서는 대부분 브로드캐스트 리시버를 이용한다.

'깡샘 코틀린' 카테고리의 다른 글

15-1 서비스 컴포넌트  (0) 2023.07.06
14-2 시스템 상태 파악하기  (0) 2023.07.03
섹션 0. 들어가기에 앞서  (0) 2023.07.02
13-5 액티비티 ANR 문제와 코루틴  (0) 2023.07.01
13-4 태스크 관리  (0) 2023.07.01