서비스
서비스는 사용자가 앱과 상호작용 중이지 않을 때도 백그라운드에서 작업을 수행하기 위해 사용하는 앱 컴포넌트다.
액티비티와 달리 UI를 제공하지 않는다.
서비스 선언하기
서비스는 Service
클래스를 직접 구현하거나 프레임워크에서 제공하는 하위 클래스를 사용한다.
매니페스트 파일에 선언하기
다음처럼 <application>
의 하위 태그로 <service>
를 선언한다.
<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
필수 속성인 android:name
속성은 서비스 클래스의 이름을 의미한다. 이외에도 서비스를 실행하는데 필요한 권한, 실행되어야 하는 프로세스 등 여러 속성이 있다.
서비스를 앱 내에서만 사용하려면 android:exported
속성을 false
로 설정하여 외부 앱의 접근을 방지할 수 있다(명시적 인텐트를 사용해도 실행되지 않는다).
android:description
속성을 사용하면 사용자가 확인할 수 있는 서비스 설명문을 설정할 수 있다.
서비스의 콜백 메서드
Service
클래스를 구현할 때 몇 가지 중요한 콜백 메서드를 재정의해야 한다.
onCreate(): Unit
서비스 인스턴스가 생성될 때 가장 먼저 호출되는 콜백 메서드. 서비스가 이미 실행 중이라면 호출되지 않는다. 초기 설정 로직을 작성할 수 있다.onStartCommand(Intent, Int, Int): Int
클라이언트(다른 앱 컴포넌트)가startService()
를 호출하여 서비스를 시작할 때 호출되는 콜백 메서드. 이 메서드가 실행되면 서비스는 무기한으로 실행되기 때문에, 작업을 마쳤다면stopSelf()
를 호출하여 스스로 중지하거나 클라이언트에서stopService()
를 호출하여 중지해야 한다. 서비스가 바인딩만 허용할 경우 이 메서드는 구현하지 않아도 된다.onBind(Intent): IBinder?
클라이언트가bindService()
를 호출하여 서비스에 바인딩할 때 호출되는 콜백 메서드. 반환하는IBinder
는 클라이언트와 서비스가 상호작용할 때 사용하는 인터페이스다. 서비스가 바인딩을 허용하지 않을 경우null
을 반환해야 한다.onDestroy(): Unit
서비스가 소멸할 때 호출되는 콜백 메서드. 생성했던 스레드나 리스너 등 남은 리소스를 정리하는 로직을 작성할 수 있다.
포그라운드 서비스
사용자가 확인할 수 있도록 알림을 표시하는 서비스를 말한다.
Android 버전별 포그라운드 서비스 알림 동작
알림 해제하기
API 레벨 33 이상 버전에서는 포그라운드 서비스 알림을 해제할 수 있다. 이전 버전에서는 서비스가 중지되거나 포그라운드에서 제외되지 않으면 해제할 수 없었다. 물론 알림을 빌드할 때 Notification.Builder.setOngoing()
에 true
를 전달하여 이전처럼 해제하지 못하도록 설정할 수도 있다.
알림 표시 지연
API 레벨 31 이상 버전에서는 포그라운드 서비스 알림이 10초 동안 지연된 다음 표시된다. 하지만 다음과 같은 경우에는 즉시 표시된다.
- 알림이 액션 버튼을 포함한다.
- 포그라운드 서비스 유형이
mediaPlayback
,mediaProjection
,phoneCall
이다. - 알림을 빌드할 때
Notification.Builder.setForegroundServiceBehavior(Int)
에Notification.FOREGROUND_SERVICE_IMMEDIATE
를 전달한다.
알림 권한
API 레벨 33 이상 버전에서 알림 권한이 승인되지 않으면 알림이 포그라운드 서비스 태스크 매니저에는 표시되지만 알림 창에는 표시되지 않는다.
포그라운드 서비스 권한
API 레벨 28 이상 버전에서 포그라운드 서비스를 사용하려면 FOREGROUND_SERVICE
권한이 필요하다. 이는 일반 권한이므로 요청하면 자동으로 승인된다.
포그라운드 서비스 시작하기
서비스를 시작하는 인텐트를 준비한다. 이 인텐트를 컴포넌트의 startForegroundService(Intent)
에 전달한다. startService()
를 사용하여 서비스를 시작할 수 있지만 startForegroundService()
는 5초 이내에 서비스에서 startForeground()
를 호출할 것이라고 약속된 상황일 때 사용한다.
val intent = Intent( ... ) // 서비스를 시작하는 인텐트
applicationContext.startForegroundService(intent)
그러고 나서 서비스에서 startForeground()
를 호출하여 서비스가 포그라운드에서 실행되도록 시스템에 요청한다.
startForeground(id: Int, notification: Notification): Unit
* added in API lvl 5
파라미터 타입 설명 id
Int
표시할 포그라운드 서비스 알림의 ID. notification
Notification
표시할 포그라운드 서비스 알림. startForeground(id: Int, notification: Notification, foregroundServiceType: Int): Unit
* added in API lvl 29
파라미터 타입 설명 foregroundServiceType
Int
포그라운드 서비스 유형을 나타내는 정수형 플래그. ServiceInfo.FOREGROUND_SERVICE_TYPE_*
상수를 조합하여 사용한다.
백그라운드에서 포그라운드 서비스 시작 제한
API 레벨 31 이상 버전을 타겟팅하는 앱이 백그라운드에서 실행 중일 때 몇 가지 예외를 제외하고 포그라운드 서비스를 시작할 수 없다.
포그라운드에서 포그라운드 서비스 제외하기
포그라운드에서 포그라운드 서비스를 제외하려면 서비스에서 stopForeground()
를 호출하면 된다. 이 메서드를 호출해도 서비스가 중지되지는 않고 포그라운드에서만 제외될 뿐이다. 서비스가 포그라운드에서 제외되면 메모리가 부족할 때 시스템이 중지할 수 있다.
stopForeground(notificationBehavior: Int): Unit
* added in API lvl 24
서비스를 포그라운드 상태에서 제거한다.
파라미터 타입 설명 notificationBehavior
Int
제거할 서비스의 알림의 동작 방식을 의미한다. 아래 나열된 Service
클래스의 상수를 사용할 수 있다.STOP_FOREGROUND_REMOVE
서비스의 알림이 즉시 해제된다.STOP_FOREGROUND_DETACH
서비스와 알림의 연결이 해제된다. 알림 지연 정책(시스템이 10초 동안 대기했다가 알림을 표시)으로 인해 아직 알림이 표시되지 않았을 때stopForeground()
이 호출되었다면 알림이 즉시 표시된다. 알림은 서비스가 완전히 중지되고 소멸된 후에도 표시되어 있다.
stopForeground(removeNotification: Boolean): Unit
* added in API lvl 5 / deprecated in API lvl 33
파라미터 타입 설명 removeNotification
Boolean
포그라운드에서 제거할 서비스의 알림을 해제할지 여부를 의미한다. true
를 전달하면stopForeground(Int)
에Service.STOP_FOREGROUND_REMOVE
가 전달되고 그렇지 않으면STOP_FOREGROUND_LEGACY
가 전달된다.
포그라운드 서비스를 실행 중인 앱 종료하기
API 레벨 33 이상 버전을 실행하는 디바이스는 알림 창에서 포그라운드 서비스 태스크 매니저를 통해 포그라운드 서비스를 실행 중인 앱을 종료할 수 있다. 그렇게 하면 다음 동작이 발생한다.
- 시스템이 메모리에서 앱을 제거한다. 따라서 포그라운드 서비스뿐 아니라 앱 자체가 종료된다.
- 앱의 액티비티가 백스택에서 제거된다.
- 미디어 재생이 중지된다.
- 앱이 히스토리에서 제거되지는 않는다.
- 예약된 작업 및 알람은 보존된다.
포그라운드 서비스 유형 설정하기
포그라운드 서비스 유형을 설정하려면 <service>
의 android:foregroundServiceType
속성을 사용한다. 한 서비스에 여러 값을 동시에 설정할 수 있으며 설정할 수 있는 값은 다음과 같다.
"camera"
카메라 액세스."connectedDevice"
자동차, TV, 블루투스 등 다른 기기와의 연결을 모니터링 및 상호작용."dataSync"
데이터(사진, 파일, 계정 등)의 업로드 및 다운로드, 가져오기 및 내보내기, 디바이스와 클라우드 사이 네트워크를 통한 전송."location"
위치 정보 액세스."mediaPlayback"
음악, 동영상, 뉴스 또는 기타 미디어 재생."mediaProjection"
스크린샷 촬영, 화면 녹화와 같은 미디어 프로젝션 세션 관리."microphone"
마이크에 액세스."phoneCall"
통화, 화상 회의, 또는 이와 유사한 상호작용 통신과 관련된 지속적인 작업.
액세스 제한
API 레벨 30 이상 버전에서 앱이 백그라운드에서 실행되고 있을 때 포그라운드 서비스를 시작하면 서비스는 카메라 및 마이크에 액세스할 수 없다. 또한 백그라운드 위치 권한(ACCESS_BACKGROUND_LOCATION
)이 없으면 서비스는 위치 정보에 액세스할 수 없다.
포그라운드 서비스 유형 필터링
서비스에서 startForeground()
를 호출하면 매니페스트에 선언된 포그라운드 서비스 유형에 대한 액세스가 허용된다. 허용된 유형 중에서 일부분만 필요하다면 다음처럼 startForeground()
에 플래그를 전달하여 필요한 포그라운드 서비스 유형을 필터링할 수 있다.
val notification: Notification = ...;
startForeground(
NOTIFICATION_ID,
notification,
ServiceInfo.FOREGROUND_SERVICE_TYPE_CAMERA or
ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE
)
플래그로 사용할 수 있는 값은 ServiceInfo
클래스의 FOREGROUND_SERVICE_TYPE_*
상수다.
FOREGROUND_SERVICE_TYPE_MANIFEST
매니페스트 파일에 선언된 모든 유형을 그대로 사용.FOREGROUND_SERVICE_TYPE_NONE
매니페스트 파일에 선언되지 않은 경우 기본 포그라운드 서비스 유형을 사용.FOREGROUND_SERVICE_TYPE_CAMERA
"camera"
에 대응.FOREGROUND_SERVICE_TYPE_CONNECTED_DEVICE
"connectedDevice"
에 대응.FOREGROUND_SERVICE_TYPE_DATA_SYNC
"dataSync"
에 대응.FOREGROUND_SERVICE_TYPE_LOCATION
"location"
에 대응.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
"mediaPlayback"
에 대응.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION
"mediaProjection"
에 대응.FOREGROUND_SERVICE_TYPE_MICROPHONE
"microphone"
에 대응.FOREGROUND_SERVICE_TYPE_PHONE_CALL
"phoneCall"
에 대응.
백그라운드 서비스
사용자에게 직접적으로 보이지 않는 작업을 수행하는 서비스.
백그라운드 서비스 제한
API 레벨 26 이상 버전을 타겟팅하는 앱이 포그라운드에 있지 않으면 백그라운드 서비스 실행이 제한된다.
다음과 같은 경우 앱이 포그라운드에 있는 것으로 간주된다.
- 상태가 "시작됨"이든 "일시중지됨"이든 눈에 보이는 액티비티가 있다.
- 포그라운드 서비스가 있다.
- 포그라운드에 있는 다른 앱과 연결(다른 앱의 서비스에 바인딩되어 있거나 컨텐츠 프로바이더를 사용)되어 있다.
위에 하나도 해당하지 않는 경우 앱이 백그라운드에 있는 것으로 간주된다.
앱이 포그라운드에 있는 동안 포그라운드 및 백그라운드 서비스를 자유롭게 생성하고 실행할 수 있다. 앱이 백그라운드로 이동해도 몇 분 동안은 서비스를 생성하고 사용할 수 있다. 그 뒤에는 앱이 유휴 상태로 간주된다. 이 때 시스템이 앱의 백그라운드 서비스를 중지한다.
하지만 백그라운드에 있는 앱이 자유롭게 서비스를 시작하고 백그라운드 서비스를 실행할 수 있다. 앱이 사용자에게 보이는 작업을 처리할 때 이것이 가능해진다.
'Android' 카테고리의 다른 글
서비스 (3) : 시작되는 서비스 (0) | 2022.08.29 |
---|---|
서비스 (2) : 바인딩된 서비스 (0) | 2022.08.28 |
액션 바 사용하기 (0) | 2022.08.09 |
알림 표시하기 (0) | 2022.07.26 |
진동 울리기 (0) | 2022.07.21 |