-
Broadcast Receiver 예제안드로이드 학습/Android 기술면접 대비 코드 2023. 6. 11. 09:03
Broadcast Receiver에서 받을수 있는 이벤트가 너무 많기 때문에 그중 일부를 알아보자면 아래와 같다.
Broadcast Receiver에서 받을수 있는 이벤트:
더보기ACTION_BOOT_COMPLETED
부팅이 끝났을 때 (RECEIVE_BOOT_COMPLETED 권한등록 필요)
ACTION_CAMERA_BUTTON
카메라 버튼이 눌렸을 때
ACTION_DATE_CHANGED
ACTION_TIME_CHANGED
폰의 날짜, 시간이 수동으로 변했을때 (설정에서 수정했을때)
ACTION_SCREEN_OFF
ACTION_SCREEN_ON
화면 on, off
ACTION_AIRPLANE_MODE_CHANGED
비행기 모드
ACTION_BATTERY_CHANGED
ACTION_BATTERY_LOW
ACTION_BATTERY_OKAY
배터리 상태변화
ACTION_PACKAGE_ADDED
ACTION_PACKAGE_CHANGED
ACTION_PACKAGE_DATA_CLEARED
ACTION_PACKAGE_INSTALL
ACTION_PACKAGE_REMOVED
ACTION_PACKAGE_REPLACED
ACTION_PACKAGE_RESTARTED
어플 설치/제거
ACTION_POWER_CONNECTED
ACTION_POWER_DISCONNECTED
충전 관련
ACTION_REBOOT
ACTION_SHUTDOWN
재부팅/종료
ACTION_TIME_TICK
매분마다 수신
android.provider.Telephony.SMS_RECEIVED
sms 수신 (RECEIVE_SMS 권한 필요)이런 것들 말고도 앱내에서 개발자가 직접 발송해서 받을 수도 있다.
여러가지 이벤트들 중에 쉽게 표시가 나는 이벤트를 택해서 예제에 넣어봤다.
ACTION_BATTERY_CHANGED : 배터리 상태변화
ACTION_POWER_CONNECTED : 배터리 충전중?
ACTION_POWER_DISCONNECTED : 배터리 안충전중?그리고 Broadcast Receiver는 정적 리시버(Static Receiver)와 동적 리시버(Dynamic Receiver)로 두 가지 형태로 나뉜다.
정적 리시버
정적 리시버는 사용할 수 있는 것의 제한이 있다.
"Android 8.0(API 레벨 26) 백그라운드 실행 제한의 일환으로 API 레벨 26 이상을 타겟팅하는 앱은 암시적 브로드캐스트의 broadcast receiver를 manifest에 더 이상 등록할 수 없습니다. 하지만 현재 몇몇 브로드캐스트는 이러한 제한에서 제외됩니다. 앱이 타겟팅하는 API 레벨과 관계없이 앱은 다음 브로드캐스트의 리스너를 계속 등록할 수 있습니다."
참고 : https://developer.android.com/guide/components/broadcast-exceptions?hl=ko1. MyBroadcastReceiver에서 이벤트 받는 부분
class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent) { Toast.makeText(context, intent.action, Toast.LENGTH_SHORT).show() Log.d("LocaleChangedRecevier", "onReceive: receive 받기: ${intent.action}") when (intent.action) { "custom.MyStaticAction" -> { Toast.makeText(context, "custom.MyStaticAction", Toast.LENGTH_SHORT).show() } Intent.ACTION_BOOT_COMPLETED -> { Toast.makeText(context, "ACTION_BOOT_COMPLETED", Toast.LENGTH_SHORT).show() } } } }
2. 테스트를 위해 동적으로 Receiver 실행
class MainActivity : AppCompatActivity() { @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) ... 생략 ... staticReceiverBtn.setOnClickListener{ val intent = Intent(this, MyBroadcastReceiver::class.java) intent.action = "custom.MyStaticAction" sendBroadcast(intent) } ... 생략 ... }
3. AndroidManifest.xml 등록
<application ... 생략 ... <receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.ACTION_BOOT_COMPLETED" /> </intent-filter> </receiver> ... 생략 ... </application>
동적 리시버
1. 동적 리시버 등록
private fun dynamicBroadcastReceiverInitialze(){ intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED) intentFilter.addAction("custom.MyDynamicAction") receiver = object: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action = intent.action when (action) { Intent.ACTION_BATTERY_CHANGED -> { Toast.makeText(context, "ACTION_BATTERY_CHANGED", Toast.LENGTH_SHORT).show() } "custom.MyDynamicAction" -> { Toast.makeText(context, "custom.MyDynamicAction", Toast.LENGTH_SHORT).show() } } } } }
2. 테스트를 위해 동적으로 실행
dynamicReceiverBtn.setOnClickListener{ val intent = Intent("custom.MyDynamicAction") sendBroadcast(intent) }
전체 예제 : 정적 + 동적 리시버
AndroidManifest.xml
더보기<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> <application android:allowBackup="true" android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.BroadcaseReceiver" tools:targetApi="31"> <receiver android:name=".MyBroadcastReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.ACTION_BOOT_COMPLETED" /> </intent-filter> </receiver> <activity android:name=".MainActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
MainActivity.kt
더보기class MainActivity : AppCompatActivity() { private lateinit var receiver: BroadcastReceiver private lateinit var staticReceiverBtn: Button private lateinit var dynamicReceiverBtn: Button private val intentFilter = IntentFilter() @RequiresApi(Build.VERSION_CODES.O) override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) staticReceiverBtn = findViewById(R.id.staticReceiverBtn) dynamicReceiverBtn = findViewById(R.id.dynamicReceiverBtn) staticReceiverBtn.setOnClickListener{ val intent = Intent(this, MyBroadcastReceiver::class.java) intent.action = "custom.MyStaticAction" sendBroadcast(intent) } dynamicReceiverBtn.setOnClickListener{ val intent = Intent("custom.MyDynamicAction") sendBroadcast(intent) } dynamicBroadcastReceiverInitialze() } override fun onStart() { super.onStart() registerReceiver(receiver, intentFilter); } override fun onDestroy() { super.onDestroy() unregisterReceiver(receiver) } private fun dynamicBroadcastReceiverInitialze(){ intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED) intentFilter.addAction("custom.MyDynamicAction") receiver = object: BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val action = intent.action when (action) { Intent.ACTION_BATTERY_CHANGED -> { Toast.makeText(context, "ACTION_BATTERY_CHANGED", Toast.LENGTH_SHORT).show() } "custom.MyDynamicAction" -> { Toast.makeText(context, "custom.MyDynamicAction", Toast.LENGTH_SHORT).show() } } } } }
activity_main.xml
더보기<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <Button android:id="@+id/staticReceiverBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="60dp" android:layout_marginTop="500dp" android:text="정적 리시버" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <Button android:id="@+id/dynamicReceiverBtn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="500dp" android:layout_marginEnd="60dp" android:text="동적 리시버" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
MyBroadcastReceiver.kt
더보기class MyBroadcastReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent) { Toast.makeText(context, intent.action, Toast.LENGTH_SHORT).show() Log.d("LocaleChangedRecevier", "onReceive: receive 받기: ${intent.action}") when (intent.action) { "custom.MyStaticAction" -> { Toast.makeText(context, "custom.MyStaticAction", Toast.LENGTH_SHORT).show() } Intent.ACTION_BOOT_COMPLETED -> { Toast.makeText(context, "ACTION_BOOT_COMPLETED", Toast.LENGTH_SHORT).show() } } } }
결과 :
충전중일때 정적 리시버 버튼 눌렀을 때 동적 리시버 버튼 눌렀을 때 아...... 이런 쉬운 예제도 만드는데 5시간이 걸렸다...... 동적 리시버는 금방 됐는데 정적 리시버가 계속 안되서 찾아보니 이제는 몇가지 말고는 정적 리시버로 등록이 불가능한것 같다. 문서를 정독하는 습관을 길러야겠다.......
'안드로이드 학습 > Android 기술면접 대비 코드' 카테고리의 다른 글
MVC 패턴 예제 (0) 2023.12.14 안드로이드 Bound Service 예제 (0) 2023.07.03 MVVM 패턴 + databinding + Room DB + recyclerview 예제 (0) 2023.06.15 (AAC) Room DB (0) 2023.06.14 간단한 MVVM 패턴 예제 (0) 2023.06.07