Android
[Android] 백그라운드 제약(Background Execution Limit), 발생 오류
haehyun
2022. 1. 23. 20:55
728x90
백그라운드 제약(Background Execution Limit)
- 앱이 백그라운드 상황일 때 작업 처리에 받는 제약들.
- 브로드캐스트 제약 : 브로드캐스트 리시버(Broadcast Receiver) 컴포넌트 실행에 대한 제약
- 백그라운드 서비스 제약 : 서비스(Service) 컴포넌트 실행에 대한 제약
- 액티비티와 달리 화면이 없는 상태에서 실행되며, 백그라운드에서 실행될 때마다 앱이 기기의 제한된 리소스(ex: RAM)을 사용해 사용자 환경이 손상될 수 있기 때문에 Android 8.0(API Level 26) 부터 백그라운드 작업에 대해 여러 제약이 생겼다.
- ex) 사용자가 현재 창에서 게임을 하면서 다른 창으로 웹을 탐색하고, 타사 앱을 사용해 백그라운드로 음악을 재생하는 경우 동시에 실행되는 앱들로 인해 시스템 부하가 걸리는데, 이 때 추가 앱이나 서비스가 백그라운드에서 실행중이면 시스템 부하가 더욱 가중된다. 이러한 부하 때문에 앱이 강제로 종료될 수 있다.
- 이러한 문제를 줄이기 위해 사용자가 앱과 직접 상호작용하지 않을 때 이 앱이 수행할 수 있는 작업을 제한한다.
요약 : 어쨌거나 모든 프로그램에서 최대한 막아야 하는 건 앱이 강제 종료되는 상황....😥 강종을 일으키는 원인 중 하나인 시스템 과부화를 방지하기 위해 문제를 일으킬만한 행동들을 못 하도록 안드로이드 측에서 미리 제한해두는 것.
브로드캐스트 제약
Background execution not allowed: receiving Intent { act=ACT_RECEIVER flg=0x10 } to com.example.test/.MyReceiver
- 매니페스트 파일에 등록한 리시버는 암시적 인텐트로 실행할 수 없다.
- 내부 앱이든 외부 앱이든 registerReceiver()로 동적 생성한 리시버만 암시적 인텐트로 실행할 수 있다.
- 매니페스트 파일에 등록한 리시버 → 명시적 인텐트O, 암시적 인텐트X
- 매니페스트 파일에 등록하지 않은 리시버, 동적 생성 → 명시적 인텐트X, 암시적 인텐트O
*리시버 생성 및 실행 방법
- 정적 생성 (미리 만들어두고 사용하는 방법)
- Receiver 파일을 생성, BoradcastReceiver를 상속받는 클래스 선언
- onReceive() 함수 오버라이딩
- 매니페스트 파일에 등록
(클래스명을 나타내는 name속성 필수, 암시적 인텐트 할거면 <intent-filter> 추가) - 명시적 인텐트 or 암시적 인텐트로 서비스를 실행하는 인텐트 생성
- sendBroadcast() 함수로 인텐트 전달
- 동적 생성 (바로 만들어서 사용하는 방법)
- BroadcastReceiver를 상속받는 익명 클래스(객체) 선언
- onReceive() 함수 오버라이딩
- registerReceiver() 함수에 리시버 객체, 인텐트 필터를 전달해 리시버 등록
- 암시적 인텐트로 서비스를 실행하는 인텐트 생성
- sendBroadcast() 함수로 인텐트 전달
*인텐트 생성 방법
- 암시적 인텐트 : 인텐트 필터로 인텐트를 생성하는 방법.
- 명시적 인텐트 : 클래스 레퍼런스 타입으로 인텐트를 생성하는 방법.
백그라운드 서비스 제약
Not allowed to start service Intent { act=ACTION_OUTER_SERVICE pkg=com.example.test }: app is in background uid null
- 앱이 백그라운드 상태일 때 인텐트를 전달하면 오류가 발생해 서비스가 실행할 수 없다.
Context.startForegroundService() did not then call Service.startForeground()
- 일반적인 startService() 함수가 아니라 startForegroundService() 함수로 인텐트를 전달하면 백그라운드 상태에서도 앱이 실행되기는 하나, 잠시 후 다른 오류가 발생한다.
- 인텐트를 startForegroundService()로 실행한 뒤, 빠른 시간안에 startForeground() 함수를 호출해 포그라운드 상황으로 만들면 서비스를 정상 실행할 수 있다.
ex) 액티비티 코드에서 startForegroundService()로 서비스 실행 → 서비스 코드에서 startForeground() 호출 - 이 때 startForeground() 함수 매개변수로 Notification객체가 전달되는데, 이건 즉 사용자에게 푸시 알림을 띄우는 행동. 즉, 백그라운드 상황에서 프로그램을 실행하고 싶다면 이 앱이 실행되고 있다는 것을 사용자에게 알려야 한다는 의미이다.
- 참고로 startForground() 함수를 사용하려면 퍼미션을 등록해야 한다.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
참고자료
- Do it! 깡샘의 안드로이드 프로그래밍 with Kotlin
- Android Developers
- Background Execution Limit, https://developer.android.com/guide/background
- Guide to bacgkround work, https://developer.android.com/guide/background
728x90