[Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 브로드캐스트 리시버 컴포넌트

안드로이드 앱 프로그래밍에서 브로드캐스트 리시버 컴포넌트의 이해와 구현 방법을 정리했다. 브로드캐스트 리시버는 시스템 이벤트를 처리하는 컴포넌트로, BroadcastReceiver 클래스를 상속받아 구현하며, 매니페스트 파일에 등록하거나 동적으로 등록할 수 있다. 또한, 부팅 완료, 화면 켜짐/꺼짐, 배터리 상태 등의 시스템 상태를 파악하는 방법도 다룬다. 각 상황에 맞는 리시버 등록과 해제 방법, 그리고 배터리 상태를 확인하는 코드 예제도 포함되어 있다.
DriedPollack's avatar
Aug 19, 2024
[Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 브로드캐스트 리시버 컴포넌트

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

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

  • 브로드캐스트 리시버는 이벤트 모델로 실행되는 컴포넌트다.
    • 이벤트란 액티비티를 다룰 때 발생하는 사용자 이벤트가 아닌 부팅이 완료되는 것과 같은 시스템의 특정한 상황을 의미한다.
  • 브로드캐스트 리시버를 만들려면 BroadcastReceiver를 상속받는 클래스를 선언해야 한다.
    • 브로드캐스트 리시버의 생명주기 함수는 onReceive() 하나뿐이다.
    • onReceive() 함수는 실행한 후 10초 이내에 완료할 것을 권장하므로 오래 걸리는 작업을 담기에는 부적절하다.
      • // 브로드캐스트 리시버 만들기 class MyReceiver: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent){ } }
    • 브로드캐스트 리시버도 컴포넌트이므로 메니페스트 파일에 등록한다. 명시적으로 실행하려면 클래스명만 등록하고, 암시적으로 실행하려면 <intent-filter>를 선언해 줘야 한다.
      • // 브로드캐스트 리시버 등록 <receiver android:name=".MyReceiver" android:enabled="true" android:exported="true"></receiver>
  • 브로드캐스트 리시버는 다른 안드로이드 컴포넌트와 같이 매니페스트에 등록해야 시스템에서 인지하고 어디선가 인텐트가 발생할 때 컴포넌트를 실행해 준다.
    • 다만 브로드캐스트 리시버를 매니페스트에 등록하지 않고 코드에서 필요한 순간에 동적으로 등록할 수도 있다.
      • // 리시버 객체 생성 val receiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?){ } }
    • 브로드캐스트 리시버 객체는 액티비티나 서비스에서 생성할 수 있다. 그 다음 필요한 순간에 registerReceiver()라는 함수를 이용해 시스템을 등록한다. 이 경우 등록하고자 하는 브로드캐스트 리시버 객체, 인텐트 필더 정보 이외에 공개상태 정보도 명시되어야 한다.
      • // 동적 등록 registerReceiver(receiver, IntentFilter("ACTION_RECEIVER"), RECEIVER_EXPORTED)
    • registerReceiver() 함수로 등록한 리시버는 사용한 후 필요 없으면 해제해 줘야 한다. 이때 unregisterReceiver() 함수를 이용한다.
      • // 브로드캐스트 리시버 해제 함수 unregisterReceiver(receiver)
        💡
        특정 상황에서 브로드캐스트 리시버를 항상 실행해야 한다면 매니페스트 파일에 등록해서 사용하면 된다. 그러나 특정한 액티비티나 서비스가 동작할 때만 브로드캐스트 리시버를 실행해야 한다면 해당 컴포넌트가 실행될 때 동적으로 등록하는 방법을 사용한다.

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

  • 브로드캐스트 리시버를 실행하려면 인텐트가 필요하다. 리시버의 클래스명만 등록했으면 명시적 인텐트로 실행하고, 인텐트 필터를 등록했으면 암시적 인텐트로 실행한다.
    • 만약 리시버를 매니페스트 파일에 등록하고 <intent-filter> 태그를 선언했다면 암시적 인텐트로는 실행할 수 없다.
      • // 리시버 실행 val intent = Intent(this, MyReceiver::class.java) sendBroadcast(intent)
    • 액티비티 인텐트는 시스템에 해당 인텐트로 실행될 액티비티가 없으면 인텐트를 시작한 곳에서 오류가 일어나지만, 브로드캐스트 리시버는 시스템에 해당 인텐트로 실행될 리시버가 없으면 아무런 일도 일어나지 않는다.
    • 반대로 여러 앱이 브로드캐스트 인텐트에 반응하도록 리시버를 만들어 놓았다며 모든 앱의 리시버가 실행된다.
 

🌼시스템 상태 파악하기

💡부팅 완료

  • 안드로이드 기기의 전원을 켜면 시스템이 동작해 부팅이 시작되고 완료되면 사용자가 기기를 사용할 수 있는 상태가 된다.
    • // 브로드캐스트 리시버와 인텐트 필터 등록 <receiver android:name=".MyReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED"/> </intent-filter> </receiver>
  • 그런데 리시버를 실행하려면 권한이 필요하므로 매니페스트에 다음처럼 퍼미션을 추가해야 한다.
    • // 권한 설정 <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>

💡화면 컴/끔

  • 화면을 켜거나 끄는 상황을 감지하는 브로드캐스트 리시버는 매니페스트에 등록하면 실행되지 않는다. 액티비티나 서비스 컴포넌트의 코드에서 registerReceiver() 함수를 이용해 동적으로 등록해야만 한다.
    • // 화면 켬/끔 리시버 receiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?){ when(intent?.action){ Intent.ACTION_SCREEN_ON -> Log.d("kkang","screen on") Intent.ACTION_SCREEN_OFF -> Log.d("kkang","screen off") } } }
  • 이렇게 정의한 브로드캐스트 리시버 객체는 액션 문자열 정보로 구성한 인텐트 필터와 함께 registerReceiver() 함수로 시스템에 등록한다.
    • // 리시버 등록 val filter = IntentFilter(Intent.ACTION_SCREEN_ON).apply{ addAction(Intent.ACTION_SCREEN_OFF) } registerReceiver(receiver, filter)
  • registerReceiver() 함수로 등록한 브로드캐스트 리시버는 필요 없는 순간이 되면 unregisterReceiver() 함수로 등록을 해제해 줘야 한다.
    • // 리시버 등록 해제 unregisterReceiver(receiver)

💡배터리 상태

  • 안드로이드 시스템에서 배터리 상태가 변경되면 다음 액션 문자열로 인텐트가 발생한다.
    • BATTERY_LOW : 배터리가 낮은 상태로 변경되는 순간
    • BATTERY_OKAY : 배터리가 정상 상태로 변경되는 순간
    • BATTERY_CHANGED : 충전 상태가 변경되는 순간
    • ACTION_POWER_CONNECTED : 전원이 공급되기 시작한 순간
    • ACTION_POWER_DISCONNECTED : 전원 공급을 끊은 순간
    • // 배터리 상태 리시버 receiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?){ when(intent?.action){ Intent.ACTION_BATTERY_OKAY -> Log.d("kkang","ACTION_BATTERY_OKAY") Intent.ACTION_BATTERY_LOW -> Log.d("kkang","ACTION_BATTERY_LOW") Intent.ACTION_BATTERY_CHANGED -> Log.d("kkang","ACTION_BATTERY_CHANGED") Intent.ACTION_BATTERY_CONNECTED -> Log.d("kkang","ACTION_BATTERY_CONNECTED") Intent.ACTION_BATTERY_DISCONNECTED -> Log.d("kkang","ACTION_BATTERY_DISCONNECTED") } } }
  • 이렇게 만든 브로드캐스트 리시버와 함께 액션 문자열을 다음처럼 시스템에 등록한다.
    • // 리시버 등록 val filter = IntentFilter(Intent.ACTION_BATTERY_LOW).apply{ addAction(Intent.ACTION_BATTERY_OKAY) addAction(Intent.ACTION_BATTERY_CHANGED) addAction(Intent.ACTION_BATTERY_CONNECTED) addAction(Intent.ACTION_BATTERY_DISCONNECTED) } registerReceiver(receicer, filter)
  • 그런데 시스템이 배터리 관련 인텐트를 발생시키지 않아도 현재 배터리 상태가 필요할 때도 있다.
    • // 시스템 인텐트 없이 배터리 상태 파악하기 val intentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) val batteryStatus = registerReceiver(null, intentFilter)
  • 이 경우 위의 객체를 이용해서 registerReceiver() 함수의 반환값인 인텐트 객체의 엑스트라 정보로 브로드캐스트 리시버를 등록해야 한다.
    • // 인텐트의 엑스트라를 이용해 배터리 상태 파악하기 val status = batteryStatus!!.getIntExtra(BatteryManager.EXTRA_STATUS, -1) if(status == BatteryManager.BATTERY_STATUS_CHARGING){ // 전원이 공급되고 있다면 val chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_STSATUS, -1) when(chargePlug){ BatteryManager.BATTERY_PLUGGED_USB -> Log.d("kkang","usb charge") BatteryManager.BATTERY_PLUGGED_AC -> Log.d("kkang","ac charge") } }else{ // 전원이 공급되고 있지 않다면 Log.d("kkang","not charging") }
  • 배터리가 얼마나 충전되었는지 알고 싶은 경우는 다음처럼 작성한다.
    • // 배터리 충전량을 퍼센트로 출력 val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) val scale = batteryStatus.IntExtra(BatteryManager.Extra_SCALE, -1) val batteryPct = level / scale.toFloat() * 100 Log.d("kkang","batteryPct; $batteryPct")
 

🏁결론

안드로이드 앱 프로그래밍에서 브로드캐스트 리시버 컴포넌트의 이해와 구현 방법을 정리했다. 브로드캐스트 리시버는 시스템 이벤트를 처리하는 컴포넌트로, BroadcastReceiver 클래스를 상속받아 구현하며, 매니페스트 파일에 등록하거나 동적으로 등록할 수 있다. 또한, 부팅 완료, 화면 켜짐/꺼짐, 배터리 상태 등의 시스템 상태를 파악하는 방법도 다룬다. 각 상황에 맞는 리시버 등록과 해제 방법, 그리고 배터리 상태를 확인하는 코드 예제도 포함되어 있다.
Share article

More articles

See more posts

👨🏻‍💻DriedPollack's Blog