본문 바로가기
프로그래밍 놀이터/안드로이드, Java

Android O Background 실행 제한

by 돼지왕 왕돼지 2017. 10. 20.
반응형

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 으로 변경하자.




반응형

댓글