Hanbit the Developer

Android Document | Foreground services > Overview 본문

Mobile/Android

Android Document | Foreground services > Overview

hanbikan 2023. 11. 21. 17:48

User can dismiss notification by default

Android 13(API level 33)부터 사용자는 foreground service 관련 알림을 제거할 수 있다. 기존에는 foreground service가 꺼질 때까지 제거할 수 없었다.

만약 non-dismissable하게 하고 싶다면, Notification.Builder로 알림을 생성할 때 setOngoing(true) 메소드를 사용하라.

Services that show a notification immediately

아래 조건 중 하나를 충족하면 서비스 시작 시 시스템이 알림을 띄운다:

  • 서비스가 action button을 포함한 알림과 연관될 때
  • 서비스가 mediaPlayback, mediaProjection, or phoneCall 유형의 타입(foregroundServiceType)을 가질 때
  • 서비스가 알림 설정 시 setForegroundServiceBehavior()에 FOREGROUND_SERVICE_IMMEDIATE를 넣어 호출할 때

Android 13(API level 33) 이상에서 알림 권한이 없을 때, notification drawer에서는 보이지 않지만 여전히 Task Manager에서 notice를 받게 된다.

Declare foreground services in your manifest

선언 시 서비스 유형을 foregroundServiceType를 통해 지정한다.

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <service
        android:name=".MyMediaPlaybackService"
        android:foregroundServiceType="mediaPlayback"
        android:exported="false">
    </service>
</manifest>
android:foregroundServiceType="camera|microphone"

API 레벨별 필수로 명시해야 하는 서비스 타입은 다음과 같다.

  • API level 29 or higher: location
  • API level 30 or higher: camera, microphone
  • API level 34 or higher: 모든 foreground service에 서비스 타입을 명시해야 한다.

만약 이를 어기면, startForeground() 호출 시 시스템이 MissingForegroundServiceTypeException 예외를 던진다.

Request the foreground service permissions

Android 9(API level 28) 이상 버전에서 FOREGROUND_SERVICE 권한을 매니페스트 파일에 명시해야 한다.

API level 34 이상 버전에서는 foreground service가 하는 작업에 대해 적절한 권한을 요청해야 한다. 각 foreground service type은 그에 상응하는 권한 타입을 갖고 있다.

예를 들어 카메라를 사용하는 서비스는 다음과 같이 선언해야 한다:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
    <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>

    <application ...>
        ...
    </application>
</manifest>

Foreground service prerequisites

Android 14(API level 34)부터 foreground service 시작 전에 해당 시스템이 서비스가 사용하는 모든 권한이 있는지 체크한다.(권한이 없을 경우 예외를 던짐)

Start a foreground service

val intent = Intent(...) // Build the intent for the service
context.startForegroundService(intent)
class MyCameraService: Service() {

  private fun startForeground() {
    // Before starting the service as foreground check that the app has the
    // appropriate runtime permissions. In this case, verify that the user has
    // granted the CAMERA permission.
    val cameraPermission =
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
    if (cameraPermission == PackageManager.PERMISSION_DENIED) {
        // Without camera permissions the service cannot run in the foreground
        // Consider informing user or updating your app UI if visible.
        stopSelf()
        return
    }

    try {
        val notification = NotificationCompat.Builder(this, "CHANNEL_ID")
            // Create the notification to display while the service is running
            .build()
        ServiceCompat.startForeground(
            /* service = */ this,
            /* id = */ 100, // Cannot be 0
            /* notification = */ notification,
            /* foregroundServiceType = */
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
            } else {
                0
            },
        )
    } catch (e: Exception) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
                && e is ForegroundServiceStartNotAllowedException) {
            // App not in a valid state to start foreground service
            // (e.g. started from bg)
        }
        // ...
    }
  }
}

Remove a service from the foreground

stopForeground()를 호출하여 서비스를 제거할 수 있다. 인자로 boolean을 넣게 되는데, status bar notification 또한 제거할지 여부를 의미한다.

Handle user-initiated stopping of apps running foreground services

Android 13(API level 33)부터 notification drawer에서 Task Manager를 통해 작동하고 있는 foreground service를 중단할 수 있다.

중단 버튼을 누르면 다음과 같은 액션이 수행된다:

  • 시스템이 앱을 메모리에서 제거한다. 이후 foreground service뿐만 아니라 앱 전체가 중단된다.
  • 시스템이 백스택에서 앱을 제거한다.
  • 미디어 재생이 중단된다.
  • 해당 foreground service와 관련된 알림이 제거된다.
  • 앱이 history에 남는다.
  • 예약된 작업 및 알람이 예정된 시간에 작동한다.

중단 버튼을 누를 때 아무런 콜백도 없기 때문에, 백업을 원한다면 ApplicationExitInfo API의 REASON_USER_REQUESTED를 활용하라.

Exemptions

시스템은 앱 단위(프로세스 단위가 아닌)로 exemptions을 제공한다.

Task Manager에 노출되지 않음

  • 시스템 레벨 앱
  • ROLE_EMERGENCY 롤을 가지고 있는 안전 앱
  • 데모 모드의 디바이스

유저가 중단할 수 없음

  • Device owner apps: 디바이스 전체에 대한 관리 권한을 가지고 있는 앱
  • Profile owner apps: 특정 사용자 프로필에 대한 관리 권한을 가지고 있는 앱
  • Persistent apps: 시스템에 의해 중요하거나 필수적으로 간주되어 일반적으로는 종료될 수 없는 앱(예: 안드로이드 OS의 핵심 부분)
  • Apps that have the ROLE_DIALER role

Use purpose-built API instead of foreground services

Bubbles API처럼 이미 잘 구성된 API가 있으므로 foreground service 구현만 고집하지는 말라.

foreground service types에 이러한 대체가 리스트업 되어있다.

Restrictions on starting a foreground service from the background

Android 12부터, 백그라운드에서 작동 중인 앱에서 포그라운드 서비스를 시작할 수 없다.(시도하게 되면 예외가 발생한다.)

*Exemptions

Restrictions on starting foreground services that need while-in-use permissions

Android 14(API level 34) 이상에서, while-in-use 권한만 얻은 채로 해당 권한이 필요한 포그라운드 서비스를 실행하면 예외가 발생한다.

*Exemptions

'Mobile > Android' 카테고리의 다른 글

AnimatedVisibility 오버랩 이슈 해결  (1) 2024.01.11
ViewModel 분석  (0) 2023.12.04
Android Document | About Services  (1) 2023.11.20
Android Lifecycle 분석  (0) 2023.10.30
[Kotlin] Coroutines 예외 처리 방법 비교  (0) 2023.08.28