will come true

[Android/Kotlin] 브로드캐스트 리시버(Broadcast Receiver) 컴포넌트 정리 본문

Android

[Android/Kotlin] 브로드캐스트 리시버(Broadcast Receiver) 컴포넌트 정리

haehyun 2022. 1. 21. 00:00
728x90

안드로이드 4대 컴포넌트

  1. 액티비티(Activity)
  2. 브로드캐스트 리시버(Broadcast Receiver)
  3. 서비스(Service)
  4. 콘텐츠 프로바이더(Content Provider)

 

브로드캐스트 리시버(Broadcast Receiver) 란?

  • 이벤트 모델로 실행되는 컴포넌트.
  • 시스템 이벤트가 발생하면 브로드캐스트 리시버를 실행해 앱이 해당 상황에 맞게 동작하도록 할 수 있다.
  • 시스템에 특정한 상황이 일어났다는 방송(Broadcast)이 되면 이를 받아 처리하는 수신기(Receiver)를 코드로 작성하는 것이다.
  • 브로드캐스트 리시버 = 리시버

 

브로드캐스트 리시버 생성

1. [패키지명] > [New] > [Other] > [Broadcast Receiver]

 

2. 생성된 파일에 BroadcastReceiver 클래스를 상속받는 클래스 선언

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent

class MyReceiver : BroadcastReceiver() {
    override fun onReceive(context: Context, intent: Intent) {
    }
}
  • 해당 리시버를 실행하려고 인텐트를 전달하면 onReceive() 함수가 자동 호출된다.

 

3. 브로드캐스트 리시버를 매니페스트 파일(AndroidManifest.xml)에 등록

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true"></receiver>

  • 명시적 인텐트로 실행하려면 클래스명을 지정하는 android:name 속성만 등록한다.
  • 암시적 인텐트로 실행하려면 <intent-filter> 태그를 추가해줘야 한다.
  • 안드로이드 컴포넌트는 매니페스트에 등록해야 시스템에서 인지하고, 인텐트가 발생할 때 컴포넌트를 실행해 준다.

 

브로드캐스트 리시버 동적 생성

1. 리시버 객체 생성

val receiver = object : BroadcastReceiver() {
    override fun onReceive(context: Context?, intent: Intent?) {
    }
}
  • Activity, Service 컴포넌트 내에서 BoradcastReceiver를 동적으로 생성해서 사용할 수 있다.
  • 리시버를 Manifest 파일에 등록하지 않아도 시스템에서 리시버를 인식함.
  • BroadcastReceiver 클래스를 상속받는 익명 클래스.

 

2. 리시버 동적 등록

val filter = IntentFilter("ACTION_RECEIVER")
registerReceiver(receiver, filter)
  • IntentFilter(String action) : 액션 문자열을 가지는 인텐트 필터 생성. 아래와 같은 내용을 의미.
<intent-filter> 
	<action android:name="ACTION_RECEIVER" /> 
</intent-filter>
  • registerReceiver(BroadcastReceiver receiver, IntetFilter filter) : IntentFilter 정보를 가지는 BroadcastReceiver를 시스템에 등록

 

3. 리시버 해제

unregisterReceiver(receiver)
  • registerReceiver() 로 등록한 리시버는 사용 후 필요가 없어지면 해제해야 한다.

 

브로드캐스트 리시버 실행

클래스 타입 레퍼런스를 이용해 명시적 인텐트로 실행

val intent = Intent(this, MyReceiver::class.java)
sendBroadcast(intent)
  • Intent(Context packageContext, Class<?> cls) : 브로드캐스트 리시버를 실행하는 인텐트 생성
  • sendBroadcast() : 인텐트를 시스템에 전달
  • 시스템에서 브로드캐스트 리시버스 객체를 생성하여 실행해 준다.

 

시스템에서 발생하는 인텐트

시스템 이벤트가 발생했을 때 특정한 작업을 수행하려면 브로드캐스트 리시버를 생성한 뒤, 매니페스트 파일의 <intent-filter>의 하위 태그 <action>에 특정 이벤트를 가리키는 액션문자열을 설정한다. 다만, 특정 시스템 이벤트는 브로드캐스트 리시버를 동적으로 생성할 때만 실행된다. (ex: SCREEN_ON, SCREEN_OFF)

등록된 리시버는 시스템에서 상태가 변경되었을 때 인텐트를 발생시켜 줘야만 실행된다.

Ex) 시스템 부팅 완료시 동작하는 브로드캐스트 리시버

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

매니페스트 권한 설정

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

 

Intent 액션 문자열

Manifest.xml 파일에서 <action> 태그의 name속성으로 사용할 때는 "android.intent.action.BOOT_COMPLETED"와 같이 쓰며, 액티비티 코드에서 사용할 때는 Intent.ACTION_BOOT_COMPLETED 와 같이 사용한다.

  • BOOT_COMPLETED : 부팅 완료
  • SCREEN_ON : 화면 켜짐
  • SCREEN_OFF : 화면 꺼짐
  • BATTERY_LOW : 배터리가 낮은 상태로 변경됨
  • BATTERY_OKAY : 배터리가 정상 상태로 변경됨
  • BATTERY_CHANGED : 충전 상태가 변경됨
  • BATTERY_POWER_CONNECTED : 전원 공급 시작
  • BATTERY_POWER_DISCONNECTED : 전원 공급 중단

 

시스템으로부터 배터리 정보 얻기 예제

package com.example.androidlab

import android.content.Intent
import android.content.IntentFilter
import android.os.BatteryManager
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.example.androidlab.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val intentFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
        // 배터리 정보를 반환값인 인텐트 객체의 엑스트라 정보로 등록
        val batteryStatus = registerReceiver(null, intentFilter)

        // 엑스트라 정보에서 배터리 상태 가져오기
        val status = batteryStatus!!.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
        if (status == BatteryManager.BATTERY_STATUS_CHARGING) {
            // 전원이 공급되고 있음
            val chargePlug = batteryStatus.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
            when (chargePlug) {
                BatteryManager.BATTERY_PLUGGED_USB -> Log.d("battery", "usb charge")
                BatteryManager.BATTERY_PLUGGED_AC -> Log.d("battery", "ac charge")
            }
        } else {
            // 전원이 공급되고 있지 않음
            Log.d("battery", "not charging")
        }
    }
}

 

브로드캐스트 리시버 실행순서

  1. 브로드캐스트 리시버 생성
  2. 시스템에 브로드캐스트 리시버를 실행하는 인텐트 전달
  3. 시스템 이벤트 발생 시 브로드캐스트 리시버에 정의된 onReceive() 함수 자동 호출

BatteryManager 상수

액션 문자열 Intent.ACTION_BATTERY_CHANGED(=충전 상태 변경) 에 대한 엑스트라 데이터들.
정수 상수 값으로 각 상태를 나타낸다. 

상수 설명
EXTRA_STATUS 현재 상태
BATTERY_STATUS_CHARGING 전원 연결된 상태 : 2
BATTERY_STATIS_DISCHARGING 전원 연결되지 않은 상태 : 3
EXTRA_PLUGGED 장치가 전원에 연결되어 있는지 여부
EXTRA_PLUGGED_USB 전원이 USB 포트
EXTRA_PLUGGED_AC 전원이 AC 충전기
EXTRA_PLUGGED_WIRELESS 전원이 무선
EXTRA_LEVEL 현재 배터리 레벨, (0~EXTRA_SCALE)
EXTRA_SCALE 최대 배터리 레벨

 

ex) 배터리 퍼센트(백분률%) 구하기

(현재 배터리량 / 최대 배터리량) * 100 => (EXTRA_LEVEL / EXTRA_SCALE) * 100

 

안드로이드 에뮬레이터에서 실습을 진행할 경우, [Extended Control] 창 > [Battery] 메뉴에서 가상머신의 충전기, 배터리 잔량 등을 변경할 수 있다.

728x90
Comments