안드로이드 개발자의 창고
[39일차 Android] Broadcast Receiver 본문
출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT
📖 Broadcast Receiver
- 안드로이드 OS에서 특정 상황에 발생하는 메시지를 받아 들여 동작하는 실행 단위
- 반드시 외부에서 접근을 하기 위한 이름을 가져야 한다.
- 실제 동작은 애플리케이션이 단말기에 설치되면 안드로이드 OS는 Broad Cast Receiver에 등록된 이름으로 정리하여 목록화한다.
- 안드로이드 OS에서 어떤 사건이 발생하면 사건과 관련된 이름으로 지정된 Broad Cast Receiver를 찾아 동작 시킨다.
- 또 애플리케이션에서 이름을 전달하여 실행을 요청하면 해당 이름이 지정된 Broad Cast Receiver를 찾아 동작 시킨다.
Broadcast Receiver의 이름
- Broad Cast Receiver는 평소에는 동작하지 않다가 동작 요청이 발생하면 동작하게 된다.
- 이 때, 동작 요청은 이름을 통해 요청할 수 있으며 intent filter를 통해 이름을 등록한다.
안드로이드 8.0 이후 제약 사항
- 안드로이드 8.0부터는 개발자가 만든 Broad Cast Receiver와 OS에서 제공하는 일부 Broad Cast Receiver는 코드를 통해서만 등록이 가능하다.
- 이는 보안 상의 이유로 Broad Cast Receiver를 가진 애플리케이션 내부에서만 사용하기 위한 제약이다.
📖 예제 코드
같은 애플리케이션에 있는 Broadcast Receiver 실행
TestReceiver.kt
class TestReceiver : BroadcastReceiver() {
// BroadcastReceiver가 동작할 때 자동으로 호출되는 메서드
override fun onReceive(context: Context, intent: Intent) {
var str1 = "브로드캐스트 리시버가 동작하였습니다."
val t1 = Toast.makeText(context, str1, Toast.LENGTH_SHORT)
t1.show()
}
}
MainActivity.kt
button.setOnClickListener {
// 클래스 이름을 지정하여 같은 애플리케이션에 있는 BR를 동작시킨다.
val brIntent = Intent(this@MainActivity, TestReceiver::class.java)
sendBroadcast(brIntent)
}
- MainActivity의 button을 클릭했을 때 brIntent를 생성한다.
- brIntent 내부에 클래스 이름을 지정하여 TestReceiver를 동작시킨다.
- TestReceiver는 Toast 메세지를 띄운다.
다른 애플리케이션에 있는 Broadcast Receiver 실행
다른 애플리케이션의 AndroidManifest.xml
<receiver
android:name=".App2Receiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="com.test.testbr"/>
</intent-filter>
</receiver>
다른 애플리케이션의 App2Receiver.kt
class App2Receiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
val str1 = "App2의 BR이 동작하였습니다."
val t1 = Toast.makeText(context, str1, Toast.LENGTH_SHORT)
t1.show()
}
}
다른 애플리케이션의 MainActivity.kt
class MainActivity : AppCompatActivity() {
// BR 객체 생성
val r1 = App2Receiver()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
val filter = IntentFilter("com.test.testbr")
registerReceiver(r1, filter)
}
}
override fun onDestroy() {
super.onDestroy()
// 등록된 BR을 해제한다.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
unregisterReceiver(r1)
}
}
}
- 안드로이드 8.0부터는 BR를 코드로 등록해야지만 다른 어플리케이션이 사용할 수 있다.
- 따라서 if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ ... } 코드를 통해 SDK 버전을 확인하여 코드로 등록한다.
MainActivity.kt
button2.setOnClickListener {
val brIntent = Intent("com.test.testbr")
sendBroadcast(brIntent)
}
- 다른 애플리케이션의 AndroidManifest.xml에서 설정한 BR의 이름을 확인하여 Intent로 넘겨준다.
- 이 이름으로 다른 애플리케이션의 BR을 찾아 실행시킨다.
시스템 메세지를 이용한 Broadcast Receiver 실행
AndroidManifest.xml
<receiver
android:name=".TestReceiver2"
android:enabled="true"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
<intent-filter>
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
</intent-filter>
</receiver>
class TestReceiver2 : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
// BR를 등록했을 때 사용한 이름을 가져온다.
when(intent.action){
// 부팅 완료
"android.intent.action.BOOT_COMPLETED" -> {
Toast.makeText(context, "부팅 완료", Toast.LENGTH_LONG).show()
}
// 문자 수신
"android.provider.Telephony.SMS_RECEIVED" -> {
// 수신 문자를 가지고 있는 객체를 추출한다.
if (intent.extras != null){
// 문자 메세지 정보 객체를 추출한다.
val objs = intent.extras?.get("pdus") as Array<Any?>
if (objs != null){
// 추출한 메세지 수 만큼 반복한다.
for (obj in objs){
// 문자 메세지 객체를 추출한다.
val format = intent.extras?.getString("format")
// 문자 메세지 객체를 생성한다.
val currentSMS = SmsMessage.createFromPdu(obj as ByteArray?, format)
val str1 = """전화번호 : ${currentSMS.displayOriginatingAddress}
|내용 : ${currentSMS.displayMessageBody}
""".trimMargin()
Toast.makeText(context, str1, Toast.LENGTH_LONG).show()
}
}
}
}
}
}
}
- 안드로이드에서는 단말기에서 사건이 발생했을 경우 각 사건에 대해 정해진 메시지를 발생시킨다.
-
개발자가 각 사건에 대한 이름으로 Broadcast Receiver를 등록해 놓으면 OS가 이를 찾아 동작시키는 방식이다.
'Computer > Android' 카테고리의 다른 글
[39일차 Android] Fargment (0) | 2023.07.01 |
---|---|
[39일차 Android] Service (0) | 2023.06.29 |
[39일차 Android] Thread, runOnUiThraad (0) | 2023.06.26 |
[38일차 Android] 다양한 Notification (0) | 2023.06.25 |
[38일차 Android] Pending Intent (0) | 2023.06.25 |