Android O Background 실행 제한
https://developer.android.com/about/versions/oreo/background.html#services
-
앱이 Background 로 돌 때는 디바이스의 리소스를 사용한다. 예를 들면 RAM, CPU.
이런것들이 리소스를 많이 사용하는 게임이나 비디오 시청 등에 방해가 된다.
이를 개선하기 위해 Android 8.0 ( API 26 ) 부터는 background 작업에 대한 제한이 추가되었다.
Overview
-
많은 안드로이드 앱과 서비스는 동시에 돌 수 있다.
예를 들면 게임을 한 윈도우에서 하면서 다른 윈도우에서는 브라우징을 하고, 백그라운드에서는 음악도 재생할 수 있다.
더 많은 앱들이 한번에 돌면서 시스템에 더 많은 부하가 생긴다.
이는 User Experience 를 망칠 수 있다.
그래서 아래와 같은 제약이 생겼다.
Background Service 제약 : App 이 background 일 때 foreground service 가 아니면 background service 를 쓸 수 없다.
Broadcast 제약 : 매니페스트에 등록한 암시적 broadcast 를 받을 수 없다. ( 약간의 예외는 있다. )
이런 제약은 Android 8.0 ( API 26 ) 을 target 으로 했을 때만 기본으로 적용된다.
하지만 target 이 26 이하라도 Settings 를 통해 이 설정을 enable 시킬 수 있다.
-
대부분의 경우 이런 제약사항은 JobScheduler 를 통해 해결할 수 있다.
앱이 active running 상태가 아닐 때 작업을 조정할 수 있다. 그러나 이 조정은 system 재량에 달라진다. 이 시스템 재량이라는 것은 UX 를 해치지 않는 선에서 시스템이 결정한다는 이야기이다.
Android 8.0 은 JobScheduler 에 이 제약들을 해결하기 위한 몇 가지 향상을 가져왔다.
JobScheduler 향상에 대해 알고 싶다면 아래 링크를 참조
https://developer.android.com/about/versions/oreo/android-8.0.html#jobscheduler
Background Service 제약
-
Background 에서 도는 서비스는 리소스를 사용하면서 나쁜 UX 를 초래하기 쉽다.
System 은 foreground app 과 background app 을 구분한다.
이 background 제약에 대한 정의는 memory management 관점과는 다르다.
앱은 다음 조건에 해당하면 foreground 에 해당한다.
Started 또는 Paused 상태의 보여지는 Activity 가 있다.
Foreground service 가 있다.
service binding 이나 content provider 등을 통해 다른 Foreground app 과 연결되어 있다. 예를 들어 앱이 다음에 binding 되어 있다면 그 앱은 foreground 이다.
IME
Wallpaper service
Notification listener
Voice or text service
-
앱이 foreground 상태라면 자유롭게 foreground service 던 background service 던 띄울 수 있다.
앱이 background 로 가면, 몇 분의 범위(window) 안에(system, environment dependent 할듯) service 를 생성하고 사용할 수 있다.
몇 분의 범위(window) 의 마지막에 앱은 idle 로 전환된다.
이 시기에 system 은 background service 를 정지시킨다. service 가 Service.stopSelf() 를 부른것처럼.
-
몇 가지 환경에서 background 앱은 몇분동안 임시 whitelist 에 등록된다.
이 whitelist 에 등록된 동안 service 를 limit 없이 실행할 수 있다.
Whitelist 에 들어가는 조건은 보통 user 에게 visible 한 무언가를 줄 수 있을 떄이다.
High-priorty FCM message 를 다룰 때
SMS/MMS message 의 broadcast 를 받았을 때
Notification 을 통해 PendingIntent 가 실행될 때.
VPN 앱이 스스로를 foreground 로 올리기 전 VpnService 를 실행하는 경우
-
많은 경우에 background service 를 JobScheduler 로 교체하면서 문제를 해결할 수 있다.
-
Android 8.0 이전에 foreground service 를 만드는 일반적인 방법은 background service 를 만들고 그것을 foreground service 로 승격시키는 것이었다.
그러나 제약으로 background service 자체를 실행 시킬 수 없기 때문에 Android 8.0 에서는 startForegroundService 라를 API 를 제공한다.
System 이 service 를 생성한 이후에 5초 이내에 startForeground() 를 호출해주어 user 가 볼 수 있는 notification 을 생성해주어야 한다.
앱이 해당 method 를 시간 내에 불러주지 않으면, system 은 service 를 stop 시키고 app 을 ANR 로 처리한다.
Broadcast Limitations
-
broadcast 를 등록하면, broadcast 가 보내질 때마다 앱이 리소스를 사용한다.
너무 많은 app 이 system event 를 등록했다면 모든 앱이 깨어나면서 리소스를 사용한다.
이 문제를 해결하기 위해 Android 7.0 ( API 25 ) 에서는 broadcast 를 제약하는 규칙을 제공했는데, 그 제약이 Android 8.0 ( API 26 ) 에서 더 강화되었다.
7.0 에서 추가된 제약 : https://developer.android.com/topic/performance/background-optimization.html
Android 8.0 이상을 target 하는 앱들은 더 이상 Manifest 에 등록한 암시적 브로드케스트를 받을 수 없다. 암시적 브로드케스트란 그 앱을 딱 타게팅하지 않는 것을 이야기한다. 예를 들면 ACTION_PACKAGE_REPLACED 가 암시적 broadcast 이다. ACTION_MY_PACKAGE_REPLACED 는 target 이 딱 지정되는 형태이기 때문에 암시적 broadcast 가 아니다.
앱은 명시적 broadcast 는 계속 등록할 수 있다.
Runtime receiver 등록은 암시적이던 명시적이던 다 받을 수 있다.
Signature permission 을 요하는 broadcast 는 해당 제약을 받지 않는다.
-
JobScheduler 은 기존의 암시적 broadcast 등록에 대한 대안이 될 수 있다.
예를 들어 ACTION_POWER_CONNECTED 를 받아 job 을 수행하던 앱은 manifest 에서 해당 receiver 를 제거하고 device 가 idle 이거나 charging 하는 순간에 해당 job 을 수행하게 바꿀 수 있다.
-
몇 개의 암시적 broadcast 는 예외로 처리되어 있다.
해당 리스트는 아래 링크를 참조
https://developer.android.com/guide/components/broadcast-exceptions.html
Migration Guide
-
기본적으로 이런 변화는 Android 8.0 ( API 26 ) 이상을 target 했을 때만 적용된다. 하지만 Setting 에서 해당 옵션을 켤 수도 있다.
앱에서 service 를 어떻게 사용하고 있는지 살펴보라. background 서비스를 idle 상태에서 쓰는 경우라면 다음의 것들로 바꿀 수 있다.
App 이 background 인데 foreground service 를 써야 한다면 NotificationManager.startServiceInForeground() 함수를 사용하자. 그리고 이를 foreground 로 승격시켜주자.
service 가 user 에게 어떤 보여주는 힌트를 주고 있다면, foreground service 로 만들자. 그런 service 의 예는 audio player.
Service 의 기능을 scheduled job 으로 바꿀 수 있는지 확인하자. 만약 바로 user 에게 영향을 줄 수 있는 무엇을 할 필요가 없다면, 그것으로 바꾸자.
Background 에서 polling 하기보다는 FCM 을 이용해서 app 을 깨워서 network 를 사용하자.
앱이 foreground 로 올라올때까지 최대한 job 을 미뤄두자.
-
Manifest 에 있는 Broadcast receiver 를 살펴보고, 다음으로 변경해보자.
Runtime broadcast 를 등록하거나,
Implicit broadcast 로 trigger 할 수 있는 Scheduled job 으로 변경하자.
'프로그래밍 놀이터 > 안드로이드, Java' 카테고리의 다른 글
[android] Firebase JobDispatcher 문제.. (Job 미실행) (0) | 2017.12.05 |
---|---|
안드로이드 O 암시적 브로드케스트 예외 ( Implicit Broadcast Exceptions ) (0) | 2017.10.21 |
[android] 외부저장소의 앱 고유 영역 사용하기 (0) | 2017.09.21 |
[android] onActivityResult 는 app 이 background 일 때 불리지 않는다 (0) | 2017.09.20 |
[android] Android 6.0(MOS) SDK 에서 바뀐 것들!! (0) | 2017.09.18 |
댓글