-
Anr 예제안드로이드 학습/Android 기술면접 대비 코드 2024. 1. 23. 10:48
Anr 설명 : https://from-android-to-server.tistory.com/41
github : https://github.com/tvroom88/AIO_Android_Kotlin_Support_Material/tree/main/AnrTest/AnrTest
안드로이드 개발자 페이지에서 보면
다음 조건 중 하나가 발생하면 앱과 관련한 ANR이 트리거됩니다.
- 입력 전달 타임아웃: 앱이 입력 이벤트(예: 키 누름 또는 화면 터치)에 5초 이내에 응답하지 않은 경우
- 서비스 실행: 앱에서 선언한 서비스가 몇 초 이내에 Service.onCreate() 및 Service.onStartCommand()/Service.onBind() 실행을 완료할 수 없는 경우
- Service.startForeground()가 호출되지 않음: 앱이 Context.startForegroundService()를 사용하여 포그라운드에서 새 서비스를 시작했지만 서비스가 5초 내에 startForeground()를 호출하지 않은 경우
- 인텐트 브로드캐스트: BroadcastReceiver가 설정된 시간 내에 실행을 완료하지 못한 경우. 앱에 포그라운드 활동이 있는 경우 이 제한 시간은 5초입니다.
- JobScheduler 상호작용: JobService가 몇 초 이내에 JobService.onStartJob() 또는 JobService.onStopJob()에서 반환되지 않거나 사용자 시작 작업이 시작되고 JobService.onStartJob()이 호출된 후 몇 초 이내에 앱이 JobService.setNotification()을 호출하지 않는 경우. Android 13 및 이전 버전을 타겟팅하는 앱의 경우 ANR이 음소거되고 앱에 보고되지 않습니다. Android 14 및 이후 버전을 타겟팅하는 앱의 경우 ANR이 명시적이고 앱에 보고됩니다.
여태까지 앱을 만들어 보면서 ANR이 걸려볼 일이 없어서 직접 테스트 해보기로 했다
1. 입력 전달 타임아웃: 앱이 입력 이벤트(예: 키 누름 또는 화면 터치)에 5초 이내에 응답하지 않은 경우
5초 이상 걸리는 작업을 만들었다.
// 1. 입력 전달 타임아웃 fun plus(): String { var number = 0 for (i in Int.MIN_VALUE + 0..Int.MAX_VALUE) { number = i } return number.toString() }
그리고 버튼 클릭시 작업이 수행되게 하고 그 다음 다른 버튼을 눌러보면
countBtn.setOnClickListener { plus() }
2. background service에서도 onCreate 수행하면서 오래 걸린다며 ANR이 발생했다.
다만 5초는 아니고 더 오래 걸렸던 것 같다.
class BackgroundService : Service() { override fun onCreate() { super.onCreate() Log.d("BackgroundService", "onCreate") plus() plus() plus() } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { Log.d("BackgroundService", "onStartCommand") Toast.makeText(this, "called onStartCommand", Toast.LENGTH_SHORT).show() return START_STICKY } override fun onDestroy() { super.onDestroy() Log.d("BackgroundService", "onDestroy") Toast.makeText(this, "called onDestroy", Toast.LENGTH_SHORT).show() } @Nullable override fun onBind(intent: Intent?): IBinder? { return null } fun plus(): String { var number = 0 for (i in Int.MIN_VALUE + 0..Int.MAX_VALUE) { number = i } return number.toString() } }
3. Foreground Service에서는 서비스가 시작하고 서비스 내부에서 서비스 시작하는 것을 연결시켜 주지 않으니 ANR이 발생했다.
startForeground(1, notification.build())
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { Log.d(TAG, "ForegroundService - onStartCommand") when (intent.action) { // startService()에 의해 서비스가 시작될 때 "StartForeground" -> { Log.d(TAG, "ForegroundService - StartForeground") val inputTitle = intent.getStringExtra(Noti_Title) val inputContent = intent.getStringExtra(Noti_Content) //안드로이드 sdk 26버전 이상에서는 알림창을 띄워야 Foreground createNotificationChannel() // Notification 클릭시 MainActivity 이동 val notificationIntent = Intent(this, MainActivity::class.java) val pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE) // 버튼 클릭시 Foreground Service 종료 val stopServiceIntent = Intent(this, ForegroundService::class.java) stopServiceIntent.action = ("StopService") val stopPendingIntent = PendingIntent.getService(this, 0, stopServiceIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_MUTABLE) notification = NotificationCompat.Builder(this, CHANNEL_ID).apply { setSmallIcon(R.drawable.ic_launcher_foreground) setContentTitle(inputTitle) setContentText(inputContent) setStyle(NotificationCompat.BigTextStyle().bigText(inputContent)) addAction(R.drawable.ic_launcher_foreground, "stop service", stopPendingIntent) setContentIntent(pendingIntent) } startForeground(1, notification.build()) } "StopService" -> { Log.d(TAG, "ForegroundService - stopSelf") // 서비스를 정지시키는 로직을 구현합니다. stopForeground(STOP_FOREGROUND_REMOVE) stopSelf() } } return START_STICKY }
이렇게 ANR을 강제로 해보면서 느낀건 진짜 큰 데이터를 다루는 것이 아닌 이상 일부로 해도 힘들기도 하고 엄청 많은 데이터를 다룬다고 해도 당연하게 멀티 쓰레드나 코루틴을 이용하기 때문에 굳이 ANR 걱정은 할 필요는 없을 것 같다는 생각을 들게 했다.
'안드로이드 학습 > Android 기술면접 대비 코드' 카테고리의 다른 글
안드로이드 비동기 처리 2-3 (Operators : 연산자들) 코드편 (1) 2024.10.31 안드로이드 Rxjava 사용하기 (1) (0) 2024.03.06 Android Background Service 예제 (1) 2023.12.22 Android Foreground Service 예제 (0) 2023.12.22 MVC 패턴 예제 (0) 2023.12.14