[Android] 포그라운드 서비스(Foreground Service) 개요 및 구현 방법
포그라운드 서비스(Foreground Service)
포그라운드 서비스는 사용자가 인식할 수 있는 중요한 작업을 수행하는 서비스입니다.
이 서비스는 백그라운드에서 실행되지만, 사용자에게 알림(Notification)을 통해 실행 중임을 지속적으로 알려야 합니다.
시스템 자원을 효율적으로 관리하면서 중요한 작업을 처리할 때 사용됩니다.
포그라운드 서비스의 특징
- 알림 표시
포그라운드 서비스는 알림을 반드시 표시해야 합니다.
알림은 사용자가 서비스를 인식할 수 있게 도와줍니다.
알림은 상태 바나 알림 영역에 표시되며, 서비스가 실행되는 동안 계속 표시됩니다. - 시스템 종료 방지
일반적인 백그라운드 서비스는 자원 부족 시 시스템에 의해 종료될 수 있지만, 포그라운드 서비스는 시스템에 의해 종료되지 않습니다. 따라서 장시간 실행이 필요한 작업에 적합합니다. - 장시간 실행
포그라운드 서비스는 장시간 실행이 가능합니다.
예를 들어, 음악 재생, GPS 네비게이션, 파일 다운로드와 같은 작업은 포그라운드 서비스로 실행하면 중단 없이 계속 작업을 수행할 수 있습니다.
그렇기에 배터리 소모를 최소화하는 방법을 고려해야 합니다.
GPS, 네트워크 사용 등의 자원을 많이 소모하는 작업을 최적화하여 배터리 소모를 줄여야 합니다. - 사용자에게 중요한 작업 처리
포그라운드 서비스는 사용자에게 중요한 작업을 처리할 때 주로 사용됩니다.
사용자는 알림을 통해 서비스의 진행 상태를 확인할 수 있습니다.
사용 예시
- 음악 재생 앱
: 음악 앱은 포그라운드 서비스를 사용하여, 사용자가 음악을 재생 중임을 알림으로 표시하고, 앱을 최소화하거나 화면을 꺼도 음악이 계속 재생되도록 합니다. - GPS 네비게이션 앱
: GPS 네비게이션 앱은 위치 정보를 제공하면서 음성 안내를 하기 위해 포그라운드 서비스를 사용합니다.
이 서비스는 장시간 실행되므로 시스템에 의해 종료되지 않습니다. - 파일 다운로드
: 대용량 파일 다운로드 작업은 포그라운드 서비스를 사용하여 다운로드 상태를 알림으로 표시하고, 다운로드 완료까지 서비스를 계속 실행할 수 있습니다.
포그라운드 서비스 구현 방법
1. 서비스 클래스 작성
Service 클래스를 확장하여 포그라운드 서비스를 구현합니다.
onStartCommand() 메서드에서 startForeground() 를 호출하여 서비스를 포그라운드로 설정합니다.
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.os.IBinder
import androidx.core.app.NotificationCompat
class MyForegroundService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// 포그라운드 서비스 시작
startForeground(1, createNotification())
return START_STICKY // 서비스가 종료되지 않도록 함
}
override fun onBind(intent: Intent?): IBinder? {
return null // 바인딩되지 않는 서비스
}
private fun createNotification(): Notification {
val channelId = "default"
val channelName = "Foreground Service"
val notificationManager = getSystemService(NotificationManager::class.java)
// NotificationChannel 생성 (Android 8.0 이상에서 필요)
val channel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
// 알림 생성
return NotificationCompat.Builder(this, channelId)
.setContentTitle("포그라운드 서비스 실행 중")
.setContentText("서비스가 계속 실행되고 있습니다.")
.setSmallIcon(R.drawable.ic_service) // 원하는 아이콘으로 변경
.build()
}
}
2. 서비스 시작
서비스는 startService() 로 시작합니다.
포그라운드 서비스를 시작하려면 startForeground() 메서드를 호출하고, 알림을 반드시 제공해야 합니다.
val serviceIntent = Intent(this, MyForegroundService::class.java)
startService(serviceIntent)
3. 서비스 종료
포그라운드 서비스가 더 이상 필요하지 않으면 stopForeground() 와 stopSelf() 를 호출하여 서비스를 종료할 수 있습니다.
stopForeground(true) // 알림 제거
stopSelf() // 서비스 종료
4. AndroidManifest.xml 설정
서비스는 AndroidManifest.xml 에 등록해야 합니다.
<service
android:name=".MyForegroundService"
android:permission="android.permission.FOREGROUND_SERVICE" />
android.permission.FOREGROUND_SERVICE 권한은 Android 9 (API 28) 이상에서 필수입니다.
왼쪽 다이어그램이 startService() 로 서비스가 생성된 경우의 생명 주기이고, 오른쪽은 bindService() 로 서비스 생성된 경우의 생명 주기입니다.
bindService() 에 대해서는 다음에 작성해보겠습니다.
사용자 알림 닫기
Android 13 (API 33) 부터는 사용자가 기본적으로 포그라운드 서비스와 연결된 알림을 스와이프 동작을 실행해서 닫을 수 있습니다.
기존에는 포그라운드 서비스가 중지되거나 포그라운드에서 삭제되지 않는 한 알림이 해제되지 않았습니다.
사용자가 알림을 닫을 수 없도록 하려면, Notification.Builder 를 사용하여 알림을 만들 때 setOngoing(true) 를 설정하면 됩니다.