안드로이드 시스템 메시지 띄우기
안드로이드에서는 휴대폰에서 사건이 발생하면 사건마다 정해 놓은 이름으로 시스템 메시지를 발생합니다.
브로드 캐스트 리시버에 동일한 이름으로 설정해두어 동작시킬 수도 있습니다.
아래 링크에 있는 것들은 앱이 실행이 아니라도 사용을 할 수 있습니다.
https://developer.android.com/guide/components/broadcast-exceptions
암시적 브로드캐스트 예외 | Android 개발자 | Android Developers
백그라운드 제한에서 제외되는 암시적 브로드캐스트입니다.
developer.android.com
휴대폰 부팅 시 동작하기
휴대폰 부팅 시에 동작하는 브로드 캐스터 리시버를 만들도록 하겠습니다.
먼저 AndroidManifest.xml에 아래 권한을 추가합니다.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
부팅 권한은 권한 체크가 필요 없습니다.

New > Other > Broadcast Receiver를 통해 하나 만들어 줍니다.
AndroidManifest.xml에서 리시버에 intent filter를 추가해줍니다.
<receiver
android:name=".BootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
만든 브로드 캐스터 리시버에 아래와 같이 코드를 작성합니다.
class BootReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
when(intent.action) {
"android.intent.action.BOOT_COMPLETED" -> Toast.makeText(context, "부팅 완료", Toast.LENGTH_SHORT).show()
}
}
}
intent에서 action을 가져와 부팅을 하면 toast 메시지를 띄어주는 코드를 작성하였습니다.
앱을 실행하고 부팅을 하면 아래와 같이 동작하는 것을 확인할 수 있습니다.

지금은 간단히 toast 메시지를 띄우는 코드만 작성을 하였지만 부팅 시 동작하게 하고 싶은 코드를 작성하면 됩니다.
메시지 수신 시 동작하기
https://developer.android.com/reference/android/provider/Telephony.Sms.Intents
Telephony.Sms.Intents | Android 개발자 | Android Developers
developer.android.com
먼저 AndroidManifest.xml에 아래 권한을 추가합니다.
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.RECEIVE_SMS"/>
그리고 리시버의 intent filter에 아래의 코드를 추가해줍니다.
<action android:name="android.provider.Telephony.SMS_RECEIVED"/>
MainActivity에서는 권한 체크 코드를 작성해줍니다.
class MainActivity : AppCompatActivity() {
private val permissionList = arrayOf(
Manifest.permission.READ_PHONE_STATE,
Manifest.permission.RECEIVE_SMS
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
checkPermission()
}
private fun checkPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
for(permission in permissionList) {
if(checkCallingOrSelfPermission(permission) == PackageManager.PERMISSION_DENIED) {
requestPermissions(permissionList, 0)
}
}
}
}
}
그리고 리시버에 아래의 코드를 작성해 줍니다.
"android.provider.Telephony.SMS_RECEIVED" -> {
var str = ""
val bundle = intent.extras
if (bundle != null) {
val obj = bundle.get("pdus") as Array<*>
val msg = arrayOfNulls<SmsMessage>(obj.size)
for (i in obj.indices) {
msg[i] = SmsMessage.createFromPdu(obj[i] as ByteArray)
}
for (i in msg.indices) {
str = "${msg[i]?.originatingAddress } : ${msg[i]?.messageBody}"
Toast.makeText(context, str, Toast.LENGTH_SHORT).show()
}
}
}
val bundle = intent.extras
intent.extras를 통해 bundle 값을 가져왔습니다.
val obj = bundle.get("pdus") as Array<*>
val msg = arrayOfNulls<SmsMessage>(obj.size)
그리고 pdus를 통해 문자 메시지를 가져오고 msg에 문자 메시지의 데이터가 담길 배열을 만들어 줍니다.
for (i in obj.indices) {
msg[i] = SmsMessage.createFromPdu(obj[i] as ByteArray)
}
문자 메시지 객체를 담아 줍니다.
for (i in msg.indices) {
str = "${msg[i]?.originatingAddress } : ${msg[i]?.messageBody}"
Toast.makeText(context, str, Toast.LENGTH_SHORT).show()
}
그리고 toast를 통해 출력을 해줍니다.
originatingAddress는 전화번호이고 messageBody는 문자 내용입니다.
문자 메시지가 여러 개 올 수 있으므로 for문으로 처리를 하였습니다.
실행하면 아래와 같이 동작합니다.

위의 예제에서 리시버 action 값을 아래와 같은 문자열로 처리를 하였습니다.
when(intent.action) {
"android.intent.action.BOOT_COMPLETED" -> {}
"android.provider.Telephony.SMS_RECEIVED" -> {}
}
하지만 아래와 같이 안드로이드에서 제공되는 것으로 처리할 수 있습니다.
when(intent.action) {
Intent.ACTION_BOOT_COMPLETED -> {}
Telephony.Sms.Intents.SMS_RECEIVED_ACTION -> {}
}