안드로이드 서비스의 유형은 총 세가지가 있다.
그 중 포그라운드 서비스는 사용자에게 눈에 띄는 작업을 수행한다. 가시적인 알림을 띄워서 사용자에게 앱 사용중이 아닐 때도 시스템이 계속 수행되고 있음을 알리는 것이다.
먼저 서비스에 대해 간략히 짚고 넘어가자면, 액티비티(Activity)와는 다른 개념이다. 액티비티는 사용자에게 직접 보여지고 상호작용을 할 수 있는 인터페이스를 제공하지만, 서비스는 사용자 ui를 제공하지 않는다. 대신 백그라운드에서 작업을 실행한다. 또한 사용자가 다른 앱을 사용하고 있을 때에도 서비스는 실행될 수 있다. 백그라운드에서 파일을 다운로드하고 네트워크 트랜잭션을 처리하는 일 등을 하는 것이다.
그렇다면 포그라운드 서비스는 언제 사용하면 될까?
이를 테면 이러한 앱에서 포그라운드 서비스를 사용할 수 있다.
- 음악 재생 플레이어 앱
- 이동 거리를 측정하는 피트니스 앱
즉 사용자가 앱과 직접 상호작용하지 않을 때에도 작업이 수행중임을 사용자가 알 수 있어야 하는 경우에만 포그라운드 서비스를 사용한다. 이때는 필수적으로 사용자에게 알림을 표시해야 한다. 기본적으로 포그라운드 서비스 알림은 포그라운드 서비스가 중지되거나 제거되지 않는 한 닫히지 않는다. (안드로이드 13부터는 스와이프 동작을 통해 사용자가 포그라운드 서비스 알림을 닫을 수 있다.)
알림 표시 (Notification)
안드로이드 12 이상부터는 포그라운드 실행 직후 즉시 알림을 표시하지 않고, 10초 기다렸다가 알림을 표시한다. 이는 단기적으로 짧게 수행되는 서비스를 위해 최적화된 방식이다. 그러나 특정 유형의 서비스는 10초 지연 없이 사용자에게 즉시 알링을 표시한다.
그러한 유형의 예시로 아래 상황들이 있다.
- 사용자가 직접 상호작용할 수 있는 버튼과 연결된 액션인 경우
- 서비스 타입이 미디어 재생, 미디어 투영, 전화 통화인 경우
- 서비스의 기능이 전화 통화, 네비게이션, 미디어 재생과 관련된 경우
- setForegroundServiceBehavior()에 FOREGROUND_SERVICE_IMMEDIATE가 전달된 경우
따라서 포그라운드 실행 시 알림 노출 시점에 대한 부분을 제어하고자 한다면 setForegroundServiceBehavior()를 통해 원하는 파라미터를 넣어 전달할 수 있다.
포그라운드 선언
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<application ...>
<service
android:name=".MyForegroundService"
android:foregroundServiceType="mediaPlayback" // 음악 재생 서비스를 생성하는 경우
android:exported="false">
</service>
</application>
</manifest>
앱 manifest 파일에서 <service> 요소 내에 포그라운드 서비스를 선언한다. foregroundServiceType 속성을 사용하여 서비스가 수행하는 작업 종류를 지정할 수 있다. 만약 여러 유형이 사용되는 경우, 연산자 | 를 통해 두 가지 이상의 유형을 구분하여 같이 선언할 수 있다. 되도록이면 manifest 파일에 포그라운드 서비스와 해당 서비스 유형을 선언할 것이 권장되고 있다. (앱이 대상으로 하는 API 수준에 따라 필수는 아닐 수 있지만)
포그라운드 서비스 권한 요청
API 28 이상을 대상으로 하는 앱에서 포그라운드 서비스를 사용하려면 manifest 파일에서 FOREGROUND_SERVICE 권한을 요청해야 한다. 추가적으로 API 레벨이 34 이상일 때는 포그라운드 서비스가 수행할 기능에 맞는 포그라운드 서비스 권한 유형을 요청한다. 이는 모두 일반 권한이므로 매니페스트에 선언만 해주면 시스템에서 자동으로 부여한다.
<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>
포그라운드 서비스를 시작하면 서비스는 해당 서비스 유형에 필요한 특정 권한이 부여되었는지 확인한다. (API 34 이상일 때) 그렇기 때문에 포그라운드 서비스를 시작하기 전에 해당 서비스가 사용하는 기능에 대한 필수 전제 조건이 충족되었는지 확인해야 한다.
포그라운드 서비스 시작하기
서비스를 포그라운드로 실행하려면 먼저 서비스 자체를 시작해야 한다.
public static void startForeground(
@NonNull Service service,
int id,
@NonNull Notification notification,
int foregroundServiceType
)
startForeground()를 호출해 서비스가 포그라운드로 실행되도록 요청한다. 보통은 서비스 내부 onStartCommand() 내부에서 호출한다. API 29 이상부터는 파라미터에 foregroundServiceType을 넣어 호출해야 한다. (이전 수준에는 포함하지 않음)
다음은 카메라 기능 관련 포그라운드를 사용할 때의 예시이다. 해당 포그라운드 서비스를 시작하기 전에 앱에 먼저 카메라 권한을 부여해야 한다.
val notification = NotificationCompat.Builder(this, "CHANNEL_ID") // 알림 생성
.build()
ServiceCompat.startForeground(
this,
100,
notification,
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA
} else {
0
},
)
포그라운드에서 서비스 제거
stopForeground()를 호출해 포그라운드에서 서비스를 제거할 수 있다. 이때 파라미터로 boolean 값을 넣어 상태 알림도 제거할 것인지 선택할 수 있다. (API 33부터는 stopForeground(int)를 호출해 STOP_FOREGROUND_REMOVE 또는 STOP_FOREGROUND_DETACH를 명시적으로 전달함으로서 상태 알림 제거 여부를 결정한다.)
사용자 중지 액션
Android 13 부터는 사용자가 알림창을 통해 진행중인 포그라운드 서비스를 중지할 수 있다. 작업 관리자 내 실행 중인 앱 목록이 활성 앱을 표시하고, 앱 옆에는 중지 버튼이 있다.
사용자가 중지 버튼을 누르면, 시스템이 앱을 메모리에서 제거한다. 이때 실행 중인 포그라운드 서비스와 함께 앱 전체가 중지된다. 음악 재생 중이었다면 해당 작업도 중지되며 포그라운드 서비스와 관련된 앱 알림도 제거된다.
'Android' 카테고리의 다른 글
[Android] Branch.io SDK 연동 / 딥링크 사용법 / 커스텀 이벤트 트래킹하기 (0) | 2024.01.16 |
---|---|
[Android] Widget 에서 ListView 사용하여 데이터 노출하기 (2) | 2023.10.12 |
[Android] 딥링크 / URI Scheme 방식 사용하기 (0) | 2023.04.04 |
[Android] Naver Map Api로 네이버 지도 사용하기 (0) | 2022.04.07 |