Android 브로드캐스트 리시버

timothy jeong·2021년 11월 14일
0

Android with Kotlin

목록 보기
41/69

브로드캐스트 리시버는 안드로이드 시스템에서 생명주기를 관리하는 컴포넌트 클래스 4개 가운데 하나이다. 브로드캐스트 리시버는 액티비티와 달리 앱의 핵심 로직을 담당하지 않는다. 그리고 브로드캐스트 리시버를 작성하는데 도움을 주는 별도의 API도 별로 없다. 그런데도 동작 방식이 독특해서 자주 이용한다. 따라서 브로드 캐스트 리시버에 대한 포스팅은 API 자체보다는 시스템의 동작 방식에 대해 이야기한다.

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

흔히 이벤트 모델로 실행되는 컴포넌트 라고 정의한다. 여기에서 이벤트란 액티비티의 사용자 이벤트가 아니라 부팅이 완료되는 것과 같은 시스템의 특정한 상황을 의미한다. 시스템에 어떤 이벤트가 발생하면 브로드캐스트 리시버를 실행해 앱이 해당 상황에 맞게 동작하도록 할 수 있다. 이 수신기(브로드캐스트 리시버)도 안드로이드 컴포넌트이므로 인텐트를 시스템에 전달함으로써 실행한다.

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

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

class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
        
    }
}

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

리시버 역시 안드로이드 컴포넌트이므로 메니페스트에 등록해야한다. 명시적으로만 쓸거라면 name 필드만 등록하면 되고, 암시적으로도 사용하고자 한다면 intent-filter 를 추가해줘야한다.

    <application ... >
        <activity ... />
        <receiver android:name=".MyReceiver"/>
    </application>

동적 등록과 해제

브로드캐스트 리시버는 메니페스트에 등록하지 않고 코드에서 필요한 순간에 동적으로 등록할 수 있다. 액티비티나 서비스 컴포넌트에서 등록한다. 브로드캐스트 리시버 객체를 생성하고, 필요한 순간 registerReceiver() 함수를 이용해서 시스템에 등록한다.

        val receiver = object: BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                TODO("Not yet implemented")
            }
        }
        val filter = IntentFilter("ACTION_RECEIVER")
        registerReceiver(receiver, filter)
        
        unregisterReceiver(receiver)

이렇게 리시버를 등록하면 메니페스트에 등록하지 않아도 시스템이 인지하다. registerReceiver() 함수로 등록한 리시버는 사용한 후 필요 없으면 해제해 줘야 한다. 그때는 unregisterReceiver() 함수를 이용한다.

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

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

val intent = Intent(this, MyReceiver::class.java)
sendBroadcast(intent)

액티비티 인텐트는 시스템에 해당 인테트로 실행될 액티비티가 없으면 인텐트를 시작한 곳에서 오류가 발생한다. 그리고 실행될 액티비티가 여러 개 있으면 사용자가 선택하게 한다. 그런데 브로드캐스트 리시버는 실행될 인텐트가 없으면 아무런 일도 일어나지 않는다. 또한 실행될 리시버가 여러 개면 모두 실행된다. 이러한 동특한 동작 원리 때문에 앱에서는 대부분 브로드캐스트 리시버를 이용한다.

브로드 캐스트 리시버 활용하기

시스템 상태 파악하기

부팅 완료

안드로이드 기기의 전원을 켜면 시스팀에 동작해 부팅이 시작되고 완료되면 사용자가 기기를 사용할 수 있는 상태가 된다. 만약 앱에서 부팅이 완료될 때 특정한 작업을 수행하고 싶다면 브로드캐스트 리시버를 만들고 등록하면 된다.

부팅이 완료되면 시스템에서는 android.intent.action.BOOT_COMPLETED 라는 액션 문자열을 포함하는 인텐트가 발생한다. 이때 실행할 리시버에는 action 의 name 속성에 똑같은 액션 문자열을 등록한다.

        <receiver android:name=".MyReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
    </application>

그리고 리시버를 실행하려면 권한이 필요하므로 메니페스트에 퍼미션을 추가한다.

    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

화면 켜기/끄기

안드로이드 기기의 화면을 켜거나 끌 때 이를 감지하는 리시버도 있다. 그런데 화면을 켜거나 끄는 상황을 감지하는 브로드캐스트 리시버는 메니페스트에 등록하면 실행되지 않는다. 동적으로 등록해야만 한다.

화면을 켤때와 끌때의 브로드캐스트 리시버를 따로 만들어도 되지만 하나의 리시버에서 켜고 끄는 상황을 모두 감지하도록 할 수도 있다.

        val receiver = object: BroadcastReceiver() {
            override fun onReceive(context: Context?, intent: Intent?) {
                when (intent?.action) {
                    Intent.ACTION_SCREEN_ON -> Log.d("INFO", "screen on")
                    Intent.ACTION_SCREEN_OFF -> Log.d("INFO", "screen off")
                }
            }
        }

        val filter = IntentFilter(Intent.ACTION_SCREEN_ON).apply { 
            addAction(Intent.ACTION_SCREEN_OFF)
        }
        registerReceiver(receiver, filter)

        unregisterReceiver(receiver)

배터리 상태

배터리 상태는 현재 기기에 전원이 공급되는지, 충전량은 얼마나 되는지 등을 나타낸다. 안드로이드 시스템에서 배터리 상태가 변겨오디면 아래와 같은 액션 문자열로 인텐트가 발생한다.

  • BATTERY_LOW : 낮은 상태로 변경되는 순간
  • BATTERY_OKAY : 정상 상태로 변경되는 순간
  • BATTERY_CHANGED : 충전 상태가 변경되는 순간
  • ACTION_POWER_CONNECTED : 전원이 공급되기 시작하는 순간
  • ACTION_POWER_DISCONNECTED : 전원 공급을 끊은 순간

이러한 배터리 관련 이벤트가 발생할 때 실행될 브로드캐스트 리시버는 위의 스크린 온, 오프와 같이 액션 내용만 바꿔서 작성하면 된다. 이상의 브로드캐스트 리시버는 시스템에서 상태가 변경되었을 때 인텐트를 발생시켜 줘야만 실행된다.

profile
개발자

0개의 댓글