[Android/Kotlin] 브로드캐스트 리시버(Broadcast Receiver) 컴포넌트 정리
안드로이드 4대 컴포넌트
- 액티비티(Activity)
- 브로드캐스트 리시버(Broadcast Receiver)
- 서비스(Service)
- 콘텐츠 프로바이더(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")
}
}
}
브로드캐스트 리시버 실행순서
- 브로드캐스트 리시버 생성
- 시스템에 브로드캐스트 리시버를 실행하는 인텐트 전달
- 시스템 이벤트 발생 시 브로드캐스트 리시버에 정의된 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] 메뉴에서 가상머신의 충전기, 배터리 잔량 등을 변경할 수 있다.