#Service Android Developer 공식 문서
=> https://developer.android.com/guide/components/services?hl=ko
-Background Service는 사용자에게 보이지 않는 작업을 수행한다.
-Jetpack의 WorkManager가 나와서 굳이 Background Service를 사용 할 필요성이 없어서 백그라운드에서 작업한는 것은 추후에 WorkManager를 통해서 다루겠음.
-서비스가 처음 생성 될 때 호출된다. 이 메서드에서는 서비스의 초기 설정을 진행 하는 생명 주기 단계이다. 만약 서비스가 이미 실행중이라면 onCreate()는 호출되지 않는다.
-그러나 굳이 Service 생명주기의 onCreate()에서 하지 않아도 된다. 다른 클래스에서 서비스에 대한 초기 설정을 진행해줘도 괜찮다.
-서비스가 시작 될 때마다 호출되는 메서드로서 startService()가 호출되면 해당 생명주기가 시작된다.
-해당 생명주기에서는 서비스가 수행할 작업을 정의하며 , 이 생명주기 내부에서 startForeground()를 호출하여 사용자에게 서비스가 실행중인 알림을 표시해야 한다.
-서비스가 클라이언트에 의해 바인드 되어야 하는 경우 호출하는데 , Foreground Service는 일반적으로 바인딩을 위해 사용되지 않으므로 'null'을 반환하는 것이 일반적이다.
-서비스가 더 이상 필요하지 않아서 종료 될 때 호출된다. 이 생명주기에서는 서비스가 자체적으로 stopSelf()를 호출하거나 다른 컴포넌트에서 stopService()를 호출하여 서비스를 종료할 수 있다. 또한 서비스 종료 할 때 필요한 작업들을 수행 할 수 있다.
class RunningService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when(intent?.action) {
Actions.START.toString() -> start()
Actions.STOP.toString() -> stopSelf()
}
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent?): IBinder? {
return null
>return null을 한 이유는 서비스가 바인드를 통해서 클라이언트와 상호작용을 하지 않을 것이며,
>오직 startService(Intent)를 통해 시작되어 백그라운드에서 독립적으로 작업을 수행하는
서비스임을 나타내는 것이야.
>클라이언트가 서비스와 직접적으로 통신하여 서비스의 메서드를 호출할 필요가 없을 때 이 방식을
사용한다.
>서비스로 수행 할 수 있는 작업은 하나의 활성 인스턴스와 여러 구성 요소를 해당 단일 인스턴스에
연결하고 해당 서비스와 통신하고 수신하기 위한 통신을 위한 스트림을 수행 하는 것이다
}
private fun start() {
val notification = NotificationCompat.Builder(this , "running_channel")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("Run is active")
.setContentText("Elapsed time : 00 : 50")
.build()
// startForeground()는 ID와 Notification이 필요하다.
startForeground(1, notification)
}
enum class Actions {
START , STOP
}
}
-Foreground Service는 사용자에게 보이는 몇몇 작업을 수행한다. 또한 Foreground Service는 알림을 표시해야 하며 , 사용자가 앱과 상호작용하지 않을 때도 계속 실행되는 특징이 있다.
-Foreground Service를 사용하기 위해서는 AndroidManifest.xml 파일에 Service를 상속받은 클래스를 [service] 태그 내부에 넣어줘야 한다. 이렇게 되면 Android System에서 Service를 사용하겠다는 것을 알려줌으로서 우리가 해당 Service를 사용 할 수 있다.
-우선 Foreground Service를 사용한다는 것은 앱에서 실행되는 알림을 받겠다는 것이므로 알림권한 요청을 허용해주는 코드를 작성해줘야 한다. 따라서 AndroidManifest.xml 파일에 아래와 같은 코드를 추가해줘야 한다.
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".RunningService" />
-굳이 Service를 상속받은 클래스에서 서비스 초기 설정을 하지 않고 다른 클래스에서 서비스 초기 설정을 진행해줘도 된다. 아래는 예시코드이다.
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
"running_channel",
"Running Notifications",
NotificationManager.IMPORTANCE_HIGH
)
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
-onStartCommand 생명주기에서 진짜 서비스가 실행되는데 이때 어떤 서비스를 실행 할 지 어떡해 알 수 있을 까?
Button(onClick = {
Intent(applicationContext , RunningService::class.java).also {
it.action = RunningService.Actions.START.toString()
startService(it)
}
}) {
Text("Start run")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when(intent?.action) {
Actions.START.toString() -> start()
Actions.STOP.toString() -> stopSelf()
}
return super.onStartCommand(intent, flags, startId)
}
-위 코드에서 Actions.START.toStrint()을 통해서 start() 함수가 실행되고
private fun start() {
val notification = NotificationCompat.Builder(this , "running_channel")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentTitle("포그라운드 서비스 시작")
.setContentText("자고 싶다...")
.build()
> startForeground()는 ID와 Notification이 필요하다.
startForeground(1, notification)
}
-위 코드가 실행되면서 사용자에게 알림이 가게된다.
Button(onClick = {
Intent(applicationContext , RunningService::class.java).also {
it.action = RunningService.Actions.STOP.toString()
startService(it)
}
}) {
Text("Stop run")
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
when(intent?.action) {
Actions.START.toString() -> start()
Actions.STOP.toString() -> stopSelf()
}
return super.onStartCommand(intent, flags, startId)
}
#정리
-AndroidManifest.xml : [Service 선언] , [권한 설정]
-onCreate 또는 다른 클래스에서 서비스 초기 설정
-onStartCommand에서 서비스 액션 코드 지정
-