[Android] Foreground Service 정리

성승모·2026년 2월 23일

선언

  • manifest에서 등록할때 foregroundServiceType를 지정해줘야 함. 이는 서비스가 어떤 요구를 필요로 하는지를 설명해줌.
  • 타입에는 Camera, connectDevice, mediaPlayback, mediaProjection 등이 있음. 물론, use-permission 단에도 추가해줘야 함.

실행하기

  • 실행하려면 startForegroundService를 해줘야하고, 5초 이내에 서비스 내에서 startForeground를 호출해줘야 함.
public abstract ComponentName startForegroundService (Intent service)
  • 명시적 Intent를 통해 서비스를 시작
public static void startForeground(
    @NonNull Service service,
    int id,
    @NonNull Notification notification,
    int foregroundServiceType
)
  1. service: 해당 서비스 객체를
  2. id: 절대 0이 되면 안되고, notification의 id를 넘겨줌으로서, NotificationManager가 해당 서비스와 대응되는 Noti를 적절히 다룰 수 있게 해줌.
  3. notificaiton: foregroundService는 무조건 noti가 필요하기 때문에 이를 생성해서 넘겨줘야 함.
  4. foregroundServiceType: manifest에 적었던 것과 동일하게 하는 것이 좋다. 권한 확인을 명시적으로 넘기는 것으로 생각할 수 있기 때문에 포함되지 않은 것, 해당 서비스와 관련없는 것들은 제외하고 넣는 것이 좋다. 만약 아예 생략한다면, manifest에 적힌 모든 권한을 검사하게 된다.

stopForeground??

public final void stopForeground (int notificationBehavior)
  • 말그대로 "foreground 상태"를 멈추는 것이다. 즉, killed 되는 것이 아닌 백그라운드 상태로 전환되는 것이다.
  • notificationBehavior을 총 세 가지가 있다.
    • STOP_FOREGROUND_LEGACY: deprecated in api 33 -> 옛날 함수인 staopForeground(boolean)에 false를 담아 호출한다. 버그 & 예상하기 어려운 결과가 많아 사장됨.
    • STOP_FOREGROUND_REMOVE: 묶인 notification이 즉시 취소된다.
    • STOP_FOREGROUND_DETACH: 묶인 notification가 상태 창에 남아있게 된다.

제한

  • API 버전마다 다르니 따로 찾아서 적용해야 함.
  • 기본적으로 API 31 이상부터는 앱 자체가 백그라운드에 있을땐 start 할 수 없음.
  • service를 시작하기 전, 권한을 확인하고 거부된 경우 -> SecurityException
  • TYPE_NONE은 API 34 이상부터는 불가하니 사용하지 말자

background에서 foregroundService의 실행 제한

  • 기본적으로 API 31 이상부턴 "몇 가지 예외"를 제외하곤 background에서 foregroundService를 실행할 수 없다.
  • 이 예외를 만족시키지 않으면 -> ForegroundServiceStartNotAllowedException

예외는 다음과 같다.

  • activity 같은 시각적 트랜지션
  • FCM을 이용해서 고-우선순위 메세징을 사용한 경우
  • notification, 위젯, 버블을 사용자가 직접 클릭한 경우
  • etc...

"앱 사용 중 허가" 권한이 있을 경우 가능

  • 하지만, ACCESS_BACKGROUND_LOCATION 등은 앱 심사 시 매우 까다로워 합당한 이유가 있어야 함.
  • 그리고 무조건 foreground 상태를 유지해야함.
  • checkSelfPermission 자체가 작동하지 않으니 앱 실행 시 권한을 받아놔야 함.

Time Out

  • API 35 이상에선, dataSync와 mediaProcessing 타입을 가진 서비스는 해당 앱이 무조건 백그라운드에 있어야 함.

dataSybc: 저장, 업로드, 백업, 패치 등
mediaProcesss: 미디어에 대한 변환
-> 즉, 백그라운드에서 수행될 무거운 작업들

  • 해당 앱은 두 타입의 서비스를 24시간 중 6시간만큼 활용 가능하다.
  • Service.onTimeout()을 호출하면 foreground 상태에서 내려오고, 이때 stopSelf를 하지 않으면 -> RemoteServiceException: "A foreground service of
    type [service type] did not stop within its timeout:

따라서, timeout에 대해 다음 대처가 필요하다.

  • onTimeout 호출 이후 stopSelf 호출하기
  • 6시간 이상 사용하지 않도록 하기
  • dataSync와 mediaProcessing은 무조건 포그라운드로
  • 가능한 Workmanager 같은 대체 API를 활용

ForegroundService로 바꾸기

  • API 36
    • 모든 서비스는 runtime quotas에 종속되어 관리됨.
    • 즉, 이전 꼼수들이 먹히지 않음.
    • runtime quotas는 앱의 등급(App Standby Buckets)에 따라 결정됨.
      • Active: 현재 보고 있거나 방금까지 사용했던 앱
      • Working Set: 매우 자주 이용하는 앱 (하루에 한 번씩 꼭)
      • Frequent: 자주 사용하지만 매일은 아닌 앱
      • Rare: 자주 사용하지 않는 앱
      • Restricted: 매우 큰 리소스를 먹거나 권장되지 않는 동작을 하는 앱
  • API 35
    • 모든 foregroundService는 type을 설정해줘야 함.
    • 각 type은 기존의 권한과 유사함. 예를 들어, camera를 사용하려면 FOREGROUND_SERVICE_CAMERA를 사용하면 됨.
  • API 31
    • 앱이 백그라운드에 있을 때, 몇가지 예외를 제외하곤 Foreground Service를 실행할 수 없다.
  • API 30
    • Foreground Service가 카메라나 마이크를 사용하면, camera 또는 microphone type을 따로 지정해줘야 함.
  • API 29
    • 위치는 location type 지정
  • API 28
    • FOREGROUND_SERVICE 권한을 도입하여 이에 대한 허가를 미리 받아야 한다.
profile
안녕하세요!

0개의 댓글