개발/Android

Service.startForeground란? (Android Developers documentation 읽기)

doyou1 2023. 2. 5. 21:27
반응형

****************230205****************

 

- references: https://developer.android.com/guide/components/foreground-services

 

Foreground services  |  Android Developers

Foreground services Stay organized with collections Save and categorize content based on your preferences. Foreground services perform operations that are noticeable to the user. Foreground services show a status bar notification, to make users aware that

developer.android.com

 

포그라운드 서비스는 사용자에게 눈에 띄는 작업을 수행한다.

포그라운드 서비스는 상태 표시줄 알림을 표시하여 앱이 포그라운드에서 작업을 수행하고 있으며 시스템 리소스를 사용하고 있음을 사용자에게 알립니다.

Android 12(API 레벨 31) 이상을 실행하는 장치는 짧은 실행 포그라운드 서비스를 위한 간소화된 경험을 제공합니다. 이러한 장치에서는 시스템이 10초를 기다린 후 포그라운드 서비스와 관련된 알림을 표시합니다. 몇 가지 예외가 있는데, 이는 여러 유형의 서비스가 항상 즉시 알림을 표시하기 때문입니다.

포그라운드 서비스를 사용하는 앱의 예는 다음과 같다:

- 포그라운드 서비스에서 음악을 재생하는 음악 플레이어 앱입니다. 알림에 현재 재생 중인 노래가 표시될 수 있습니다.

- 사용자로부터 허가를 받은 후, 포그라운드 서비스에서 사용자의 실행을 기록하는 피트니스 앱. 알림은 사용자가 현재 피트니스 세션 동안 이동한 거리를 표시할 수 있습니다.

 

사용자가 앱과 직접 상호 작용하지 않는 경우에도 사용자가 볼 수 있는 작업을 수행해야 하는 경우에만 포그라운드 서비스를 사용하십시오. 최소 우선 순위 통지를 사용할 정도로 중요도가 낮은 작업인 경우 백그라운드 태스크를 대신 생성하십시오.

 

이 문서에서는 포그라운드 서비스 사용에 필요한 권한과 포그라운드 서비스를 시작하고 백그라운드에서 제거하는 방법에 대해 설명합니다. 또한 특정 사용 사례를 포그라운드 서비스 유형과 연결하는 방법과 백그라운드에서 실행 중인 앱에서 포그라운드 서비스를 시작할 때 적용되는 액세스 제한에 대해서도 설명합니다.

 

# 사용자는 기본적으로 알림을 해제할 수 있습니다

안드로이드 13(API 레벨 33)부터 사용자는 기본적으로 포그라운드 서비스와 관련된 알림을 해제할 수 있다. 이를 위해 사용자는 알림에서 스와이프 제스처를 수행합니다. 전통적으로 포그라운드 서비스가 중지되거나 포그라운드에서 제거되지 않는 한 알림은 해제되지 않습니다.

사용자가 통지를 무시할 수 없도록 하려면 Notification.Builder를 사용하여 Notification를 작성할 때 setOngoing() 메서드에 true를 전달합니다.

 

# 알림을 즉시 표시하는 서비스

포그라운드 서비스가 다음과 같은 특성 중 하나 이상을 가지고 있는 경우, 안드로이드 12 이상을 실행하는 장치에서도 시스템은 서비스 시작 직후 관련 알림을 표시한다:

- 서비스는 action button이 포함된 알림과 연결됩니다.

- 서비스에는 mediaPlayback, mediaProjection 또는 phoneCall의 foregroundServiceType이 있습니다.

- 이 서비스는 notification의 category 특성에 정의된 대로 phone calls, navigation 또는 media playback과 관련된 사용 사례를 제공합니다.

- 서비스가 알림을 설정할 때 FOREGROUND_SERVICE_IMMEDIATE를 setForegroundServiceBehavior()로 전달하여 동작 변경을 거부했습니다.

Android 13(API 레벨 33) 이상에서는 사용자가 알림 권한을 거부해도 FGS(Forground Services) 작업 관리자에는 포그라운드 서비스와 관련된 알림이 표시되지만 알림 드로어에는 표시되지 않습니다.

 

# Foreground Service 사용 권한 요청

Android 9(API 레벨 28) 이상을 대상으로 하고 포그라운드 서비스를 사용하는 앱은 다음 코드 스니펫에 표시된 것처럼 FOREGROUND_SERVICE 권한을 요청해야 합니다. 이것은 정상적인 권한이므로 시스템이 요청하는 앱에 자동으로 부여합니다.

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

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

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

 

# 포그라운드 서비스 시작

서비스를 포그라운드 서비스로 실행하도록 시스템에 요청하기 전에 서비스 자체를 시작합니다:

val intent = Intent(...) // Build the intent for the service
applicationContext.startForegroundService(intent)

일반적으로 onStartCommand()에서 서비스 내부에서 서비스를 프런트에서 실행하도록 요청할 수 있습니다. 이렇게 하려면 startForground()를 호출합니다. 이 메서드는 상태 표시줄에서 Notification을 고유하게 식별하는 양의 정수와 알림 개체 자체의 두 가지 매개 변수를 사용합니다.

 

***********************230206*****************

 

참고: 상태 표시줄 알림은 우선 순위 PRIORITY_LOW 이상을 사용해야 합니다. 앱이 우선 순위가 낮은 알림을 사용하려고 하면 시스템은 알림 드로어에 메시지를 추가하여 앱의 포그라운드 서비스 사용을 사용자에게 알립니다.

 

// If the notification supports a direct reply action, 
// use PendingIntent.FLAG_MUTABLE instead.
val pendingIntent: PendingIntent = Intent(this, ExampleActivity::class.java).let { notificationIntent ->
	PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
}

val notification: Notification = Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE)
							.setContentTitle(getText(R.string.notificaiton_title))
                            .setContentText(getText(R.string.notification_message))
                            .setSmallIcon(R.drawable.icon)
                            .setContentIntent(pendingIntent)
                            .setTicker(getText(R.string.ticker_text))
                            .build()
 
 // Notification ID cannot be 0.
 startForeground(ONGOING_NOTIFICATION_ID, notification)

 

# 백그라운드 시작에 대한 제한 사항

안드로이드 12(API 레벨 31) 이상을 대상으로 하는 앱은 몇 가지 특별한 경우를 제외하고는 백그라운드에서 실행하는 동안 포그라운드 서비스를 시작할 수 없다. 앱이 백그라운드에서 실행되는 동안 앱이 포그라운드 서비스를 시작하려고 하는데 포그라운드 서비스가 예외적인 경우 중 하나를 충족하지 못하면 시스템에서 "ForegroundServiceStartNotAllowedException"을(를) 실행합니다.

 

참고: 한 앱이 Context.startForgroundService()를 호출하여 다른 앱이 소유한 포그라운드 서비스를 시작하는 경우, 두 앱 모두 Android 12 이상을 대상으로 하는 경우에만 이러한 제한이 적용됩니다.

 

# 앱이 백그라운드 시작을 수행하는지 확인합니다

백그라운드에서 실행되는 동안 앱이 포그라운드 서비스를 시작하려고 할 때 이 동작이 발생할 때마다 나타나는 알림을 활성화하면 더 잘 이해할 수 있습니다. 이렇게 하려면 테스트 장치 또는 에뮬레이터에 연결된 개발 시스템에서 다음 ADB 명령을 실행합니다:

adb shell device_config put activity_manager \
  default_fgs_starts_restriction_notification_enabled true

# 앱의 로직 업데이트

백그라운드에서 실행하는 동안 앱이 포그라운드 서비스를 시작하는 것을 발견하면 WorkManager를 사용하도록 앱의 로직을 업데이트합니다. 앱을 업데이트하는 방법의 예를 보려면 GitHub의 WorkManager Sample을 살펴보십시오.

 

# 백그라운드 시작 제한의 예외

다음과 같은 경우에는 앱이 백그라운드에서 실행되는 동안에도 앱이 포그라운드 서비스를 시작할 수 있습니다:

- 앱이 activity과 같은 사용자가 볼 수 있는 상태에서 전환됩니다.

- 앱이 기존 작업의 백스택에 activity가 있는 경우를 제외하고 백그라운드에서 활동을 시작할 수 있습니다.

- Firebase Cloud Messaging을 사용하여 앱에 높은 우선순위 메시지가 표시됩니다.

 

참고: 앱이 사용자에게 시간에 민감한 콘텐츠를 제공하기 위해 높은 우선순위 메시지를 사용하지 않을 경우 시스템은 높은 우선순위 메시지를 일반 우선순위로 다운그레이드할 수 있습니다. 메시지의 우선 순위가 다운그레이드되면 앱이 포그라운드 서비스를 시작할 수 없으며 하나를 시작하려고 하면 "ForegroundServiceStartNotAllowedException"이 표시됩니다.

 

따라서 포그라운드 서비스를 시작하기 전에 RemoteMessage.getPriority()의 결과를 확인하고 PRIORITY_HIGH인지 확인하는 것이 좋습니다. 우선순위가 높은 메시지와 메시지 사용 시기에 대한 지침은 FCM의 설명서를 참조하십시오.

- 사용자는 앱과 관련된 UI 요소에서 작업을 수행합니다. 예를 들어 bubble, notification, widget 또는 activity과 상호 작용할 수 있습니다.

- 앱이 정확한 alarm을 호출하여 사용자가 요청하는 작업을 완료합니다.

- 앱이 device의 현재 입력 방법입니다.

- 앱은 지오펜싱(geofencing) 또는 activity 인식(recognition) 전환(transition)과 관련된 이벤트를 수신합니다.
- 디바이스가 재부팅되고 브로드캐스트 수신기에서 ACTION_BOOT_COMPLETED, ACTION_LOCKED_BOOT_COMPLETED 또는 ACTION_MY_PACKAGE_REPLACED intent 액션을 수신한 후.
- 앱이 브로드캐스트 수신기에서 ACTION_TIMEZONE_CHANGED, ACTION_TIME_CHANGED 또는 ACTION_LOCALE_CHANGED 의도 액션을 수신합니다.
- 앱이 Bluetooth_CONNECT 또는 Bluetooth_SCAN 권한이 필요한 Bluetooth 브로드캐스트를 수신합니다.
- 장치 소유자 및 프로필 소유자와 같은 특정 시스템 역할 또는 권한이 있는 앱.
- 앱이 Companion Device Manager를 사용하고 REQUEST_COMPANION_START_FOREGROUND_SERVICE_FROM_BACKGROUN 권한 또는 REQUEST_COMPANION_RUN_IN_BACKROUND 권한을 선언합니다. 가능하면 REQUEST_COMPANION_START_FOREGROUND_SERVICE_FROM_BACKGROUND를 사용하십시오.
- 사용자가 앱에 대한 배터리 최적화를 해제합니다. 사용자가 시스템 설정에서 앱의 앱 정보 페이지로 전송하여 이 옵션을 찾는 데 도움을 줄 수 있습니다. 이렇게 하려면 ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS intent action이 포함된 intent를 호출합니다.

 

# 포그라운드에서 서비스 제거

서비스를 포그라운드에서 제거하려면 stopForeground()를 호출합니다. 이 메서드는 상태 표시줄 알림도 제거할지 여부를 나타내는 부울을 사용합니다. 서비스는 계속 실행됩니다.
서비스가 포그라운드에서 실행되는 동안 서비스를 중지하면 알림이 제거됩니다.

 

# 포그라운드 서비스를 실행하는 앱의 사용자 시작 중지 처리

안드로이드 13(API 레벨 33)부터 사용자는 알림 드로어에서 워크플로우를 완료하여 해당 앱의 대상 SDK 버전에 관계없이 진행 중인 포그라운드 서비스가 있는 앱을 중지할 수 있다. FGS(Foreground Services) 작업 관리자라고 하는 이 어포던스는 현재 포그라운드 서비스를 실행 중인 앱 목록을 보여준다.

이 목록에는 활성 앱이라는 레이블이 있습니다. 각 앱 옆에는 중지 버튼이 있습니다. 그림 1은 Android 13을 실행하는 장치의 FGS 작업 관리자 워크플로우를 보여줍니다.

사용자가 FGS 작업 관리자에서 앱 옆에 있는 중지 버튼을 누르면 다음 작업이 수행됩니다:

- 시스템이 메모리에서 앱을 제거합니다. 따라서 실행 중인 foreground service뿐만 아니라 전체 앱이 중지됩니다.

- 시스템이 앱의 activity 백스택을 제거합니다.

- 미디어 재생이 중지됩니다.

- 포그라운드 서비스와 연결된 알림이 제거됩니다.

- 앱이 기록에 남아 있습니다.

- 예약된 작업은 예약된 시간에 실행됩니다.
- 알람은 예약된 시간 또는 시간대에 울립니다.

 

참고: 시스템은 사용자가 중지 버튼을 누를 때 앱에 콜백을 보내지 않습니다. 앱이 다시 시작되면, ApplicationExitInfo API의 일부인 REASON_USER_REQUESTED 이유를 확인하는 것이 도움이 됩니다.

 

****************230207****************

사용자가 앱을 중지하는 동안 및 중지한 후에 앱이 예상대로 작동하는지 테스트하려면 터미널 창에서 다음 ADB 명령을 실행합니다:

adb shell cmd activity stop-app PACKAGE_NAME

 

# 예외

시스템은 특정 유형의 앱에 대해 다음 섹션에서 설명하는 몇 가지 수준의 예외를 제공합니다.
예외는 프로세스별이 아니라 앱별로 적용됩니다. 시스템이 앱의 한 프로세스를 예외하면 해당 앱의 다른 모든 프로세스도 예외됩니다.

 

참고: 제조업체에서 구성한 일부 사전 설치된 앱도 예외일 수 있습니다.

 

# FGS 작업 관리자에 나타나는 예외

다음 앱은 포그라운드 서비스를 실행할 수 있으며 FGS 작업 관리자에 전혀 표시되지 않습니다:

- 시스템 수준 앱

- 안전 앱, 즉 ROLE_EMERGENCY 역할을 하는 앱

- 데모 모드에 있는 장치

 

# 사용자가 중지할 수 있는 예외

다음 유형의 앱이 포그라운드 서비스를 실행하면 FGS 작업 관리자에 표시되지만 사용자가 탭할 수 있는 앱 이름 옆에 중지 버튼이 없습니다:

- 장치 소유자 앱
- 프로필 소유자 앱
- 영구 앱
- ROLE_DIALER 역할을 가진 앱

 

# 포그라운드 서비스 유형 선언

앱이 Android 10(API 레벨 29) 이상을 대상으로 포그라운드 서비스에서 위치 정보에 액세스하는 경우 위치 포그라운드 서비스 유형을 <service> 구성 요소의 속성으로 선언합니다.

앱이 Android 11(API 레벨 30) 이상을 대상으로 하고 포그라운드 서비스에서 카메라 또는 마이크에 액세스하는 경우 카메라 또는 마이크 포그라운드 서비스 유형을 각각 <service> 구성 요소의 속성으로 선언합니다.

 

참고: 포그라운드 서비스 유형을 추가하면 포그라운드 서비스가 위치, 카메라 또는 마이크에 액세스할 수 있는 기능을 제공하지만, 이 포그라운드 서비스는 여전히 Android 11에 도입된 액세스 제한에 의해 영향을 받습니다.

기본적으로 런타임에 startForeground()를 호출하면 앱 매니페스트에 선언한 각 서비스 유형에 시스템이 액세스합니다. 다음 섹션의 코드 조각에 표시된 것처럼 선언된 서비스 유형의 하위 집합에 대한 액세스를 제한하도록 선택할 수 있습니다.

 

# 위치 및 카메라 사용 예제

앱의 포그라운드 서비스가 장치의 위치와 카메라에 액세스해야 하는 경우 다음 스니펫에 표시된 대로 서비스를 선언하십시오:

AndroidManifest.xml

<manifest>
    ...
    <service ... android:foregroundServiceType="location|camera" />
</manifest>

 

런타임에 포그라운드 서비스가 매니페스트에 선언된 유형의 하위 집합에만 액세스해야 하는 경우 다음 코드 조각의 논리를 사용하여 서비스의 액세스를 제한할 수 있습니다:

MyService

val notification: Notification = ...;
Service.startForeground(notification, FOREGROUND_SERVICE_TYPE_LOCATION)

런타임에 포그라운드 서비스가 매니페스트에 선언된 유형의 하위 집합에만 액세스해야 하는 경우 다음 코드 조각의 논리를 사용하여 서비스의 액세스를 제한할 수 있습니다:

MyService

val notification: Notification = ...;
Service.startForeground(notification,
        FOREGROUND_SERVICE_TYPE_LOCATION or FOREGROUND_SERVICE_TYPE_CAMERA)

 

# Work Manager 작업자의 포그라운드 서비스 유형 추가

앱에서 Work Manager를 사용하고 위치, 카메라 또는 마이크에 액세스해야 하는 장시간 실행 중인 작업자가 있는 경우 단계에 따라 장시간 실행 중인 작업자에 전경 서비스 유형을 추가하고 작업자가 사용하는 추가 또는 대체 전경 서비스 유형을 지정합니다. 다음 포그라운드 서비스 유형 중에서 선택할 수 있습니다:

- FOREGROUND_SERVICE_TYPE_LOCATION
- FOREGROUND_SERVICE_TYPE_CAMERA
- FOREGROUND_SERVICE_TYPE_MICROPHONE

 

# 위치, 카메라 및 마이크에 대한 액세스 제한

사용자 개인 정보 보호를 돕기 위해 안드로이드 11(API 레벨 30)은 포그라운드 서비스가 장치의 위치, 카메라 또는 마이크에 액세스할 수 있는 시간 제한을 도입합니다. 앱이 백그라운드에서 실행되는 동안 앱이 포그라운드 서비스를 시작할 때 포그라운드 서비스에는 다음과 같은 제한이 있습니다:

- 사용자가 앱에 ACCESS_BACKGROUND_LOCATION 권한을 부여하지 않는 한 포그라운드 서비스는 위치에 액세스할 수 없습니다.
- 포그라운드 서비스에서 마이크 또는 카메라에 액세스할 수 없습니다.

 

# 제한사항 예외

앱이 백그라운드에서 실행되는 동안 포그라운드 서비스가 시작되더라도 앱이 포그라운드에서 실행되는 동안 위치, 카메라, 마이크 정보에 액세스할 수 있습니다("사용 중").

이러한 상황에서 서비스가 위치의 포그라운드 서비스 유형을 선언하고 ACCESS_BACKGROUND_LOCATION 권한을 가진 앱에 의해 시작되면 앱이 백그라운드에서 실행되더라도 이 서비스는 항상 위치 정보에 액세스할 수 있습니다.

 

다음 목록에는 이러한 상황이 나와 있습니다:

- 시스템 구성 요소가 서비스를 시작합니다.
- 서비스는 앱 위젯과 상호 작용하는 것으로 시작됩니다.
- 서비스는 알림과 상호 작용하는 것으로 시작됩니다.
- 서비스가 눈에 보이는 다른 앱에서 보내는 PendingIntent으로 시작됩니다.
- 서비스는 장치 소유자 모드에서 실행되는 장치 정책 컨트롤러인 앱으로 시작됩니다.
- 서비스는 음성을 제공하는 앱에 의해 시작됩니다상호 작용 서비스.
- 서비스는 START_ACTIVITES_FROM_BACKGROUND 권한이 있는 앱으로 시작됩니다.

 

# 앱에서 영향을 받는 서비스 확인

앱을 테스트할 때 포그라운드 서비스를 시작합니다. 시작된 서비스가 위치, 마이크 및 카메라에 대한 액세스를 제한한 경우 Logcat에 다음 메시지가 표시됩니다:

Foreground service started from background can not have \
location/camera/microphone access: service SERVICE_NAME
반응형