일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 클린아키텍처
- 2022 KAKAO BLIND RECRUITMENT
- derivedstateof
- compose
- 양과 늑대
- 명령형 ui
- JCF
- 명령형ui
- Java
- 선언형ui
- NavHost
- producestate
- mutablestate
- BottomSheet
- ModalBottomSheet
- bottomscaffold
- genarics
- 안드로이드
- clean coder
- remembercoroutinescope
- rememberupdatedstate
- mutableStateOf
- NavGraph
- snapshotflow
- 2022 kakao blind
- apollo3
- 선언형 ui
- State
- 2989번
- 자바
- Today
- Total
버미
[Android] 컴포넌트 - 서비스(Service) 본문
Service 란?
백그라운드에서 오랜 시간동안 작업을 수행할 수 있는 어플리케이션 컴포넌트
- 사용자에게 UI를 제공하지 않는다.
- 어플리케이션 컴포넌트와 Service를 바인딩하여 상호작용할 수 있고, 프로세스간 통신(IPC)도 가능하다.
- Service는 별개의 프로세스나 스레드가 아니다.
(특별히 지정하지 않은 경우 메인스레드에서 실행된다. 따라서 긴 작업을 수행하려는 경우 IntentService, JobIntentService, WorkManager을 고려할 수 있다.) - Service는 앱에서 오직 1개의 인스턴스만 생성가능하다
Service 종류
1. Foreground Service
- 사용자에게 보이는 작업을 수행한다.
- 알림창을 통해 Service가 실행중인 것을 나타낸다.
(이 알림은 서비스가 멈추거나 Foreground에서 서비스가 제거되기 전까지 해제할 수 없다.) - 사용자가 앱과 상호작용을 하지 않을 때도 동작한다.
많은 경우에, WorkManager를 이용하는 것이 foreground service를 직접적으로 이용하는 것보다 더 좋다.
2. Background Service
- 사용자에게 보이지 않는 작업을 수행한다.
- 시스템에서 리소스가 부족할 경우 강제 종료 될 수 있다.
- API 26(오레오) 앱이 포그라운드에 있지 않을 때 백그라운드 서비스를 강제로 종료시킨다.
scheduled job을 사용하여 강제 종료를 막을 수 있다.
3. Bind Service
- 클라이언트 - 서버 구조에서 서버에 해당한다.
- 액티비티와 같은 컴포넌트들이 바인드 한 후 요청을 보내고, 응답을 받고, 프로세스간 통신(IPC)를 할 수 있도록 만들 수 있다.
- Bound된 서비스는 다른 앱의 컴포넌트가 이 서비스에 바인딩 되어 있는 동안에 실행된다.
여러개의 컴포넌트가 동시에 서비스에 바인딩될 수 있는데, 이 컴포넌트들이 바인딩 햊제시 서비스는 destroy된다.
Foreground, Background 서비스는 started Service, Bind 서비스는 bound Service로 작동이 된다.
( 한 서비스에서 bindService()와 startService()의 실행이 동시에 가능하다.)
Service 생명주기

Service 구현
- AndroidManifest.xml
Service는 어플리케이션 컴포넌트이므로 AndroidManifest.xml 파일에 등록해야 한다.
<manifest ... >
...
<application ... >
<service android:name=".MyService" />
...
</application>
</manifest>
서비스를 자신의 앱에서만 사용할 것이라면 android:exported = false로 지정하면 다른 앱에서 서비스를 사용하지 못한다.
서비스를 시작할 때는 명시적 인텐트를 사용해야 한다.
암시적 인텐트를 사용할 경우, 액션에 반응하는 모든 서비스가 잠재적으로 시작될 수 있으며 악의적인 앱이 같은 액션을 사용하여 의도하지 않은 서비스를 시작할 수 있다.
Android 5.0(API Level 21) 이상에서는 bindService()와 함께 암시적 인텐트를 사용하면 예외를 던진다.
1) startService()
- onCreate()
- Service가 처음 생성되었을 경우 onStartCommand() 및 onBind()가 호출되기 전에 실행된다.
( 서비스가 이미 실행중인 경우는 실행되지 않는다)
- Service가 처음 생성되었을 경우 onStartCommand() 및 onBind()가 호출되기 전에 실행된다.
- onStartCommand()
- 다른 컴포넌트(액티비티)가 서비스를 시작하도록 요청하는 경우에 이 메서드를 실행한다.
- startService 메서드를 통해 호출한다.
- 이 메서드가 실행될 시 백그라운드에서 무한히 실행되므로, 반드시 stopSelf() 혹은 stopService()로 서비스를 종료시켜야한다.
- 바인드 서비스만 이용하는 경우에 이 메서드를 사용하지 않아도 된다.
- 만약 서비스가 startService()를 통해 실행중일 때, 종료하지 않고 다시 서비스를 시작한다면 onStartCommand()가 계속해서 호출된다.
- onStartCommand()의 Return값을 살펴보면 다음이 있다.
- START_NOT_STICKY : 시스템이 서비스의 onStartCommand()를 반환 후에 중단시키면 서비스를 재생성하면 안됨
- START_STICKY : 시스템이 onStartCommand()를 반환 후 서비스를 중단하는 경우 서비스를 자동으로 다시 생성하고 마지막 인텐트는 전달하지 않는다. 이때 Intent를 null로 반환한다.
별다른 동작이 없는 음악앱과 같은 곳에 적합. - START_REDELIVER_INTENT : 시스템이 onStartCommand()를 반환 후에 서비스를 다시 생성하고 이 서비스에 전달된 마지막 인텐트로 onStartCommand()를 호출시 모든 보류 인텐트가 차례로 전달된다.
즉시 재개되어야 하는 작업을 수행하는데 파일 다운로드에 적합하다.
- onDestroy()
- 서비스가 종료될 때 이 메소드가 반한된다. 서비스에 등록된 리소스들을 정리하는 작업들을 여기서 한다.
- startService(), stopService()
- 서비스 실행 및 종료시에 사용한다.
2) BindService
- onCreate()
- onBind()
- 안드로이드의 구성요소가 서비스에 바인딩하고자 하는 경우, 이 메소드가 호출된다.
- 이 메소드를 구현할 때에는 클라이언트가 서비스와 통신을 주고 받기 위해 사용할 인터페이스를 제공해야 한다.
- 이를 위해 IBinder를 반환하면 된다.
- 이 메서드는 항상 구현해야 하지만, 바인딩을 허용하지 않으려면 null을 반환하면 된다.
- onRebind()
- unBind()된 후에 서비스가 다시 실행될 경우 호출 된다.
- onUnbind()
- unBindService() 호출시 true가 호출된다.
- bindService()
- 서비스에 바인딩하고자 할 때 사용한다.
- unBindService()
- 서비스를 언바인딩하고자 할 때 사용한다.
Service connection 콜백 메소드
- onServiceConnected()
- 서비스에 바인딩 되었을 때 호출 된다.
- onServiceDisconnected()
- 서비스와 바인드 된 구성요소가 중단되거나 예기치 않게 서비스와 연결이 끊어졌을 때 호출된다.
- unBind()를 통해 호출되었을 경우에는 호출되지 않는다.
Foreground services
Foreground 서비스는 사용자가 알아차릴 수 있는 작업을 수행한다.
Foreground 서비스는 status bar notification을 보여주기에 사용자들은 앱이 foreground에서 작업중이고 시스템의 리소스를 사용중인 것을 안다. 알림은 서비스가 중단되거나 foreground로 부터 서비스가 제거되기 전까지 해제될(사라질) 수 없다.
다음은 foreground 서비스를 이용한 예제이다.
- foreground 서비스로 음악을 재생하고 있는 음악앱. 알림은 현재 재생되고 있는 노래를 보여준다.
- foreground 서비스로 사용자가 달리는 것을 기록하는 피트니스 앱. 알림은 사용자가 현재 세션동안 이동한 거리를 보여준다.
권한 요청
Android 9(API Level 28) 이상부터는 foreground 서비스를 사용하기 위해서 FOREGROUND_SERVICE 권한이 필요하다. normal permission으로 단지 선언하기만 하면 된다.
<manifest xmlns:android="http://schemas.android.com/apk/res/android" ...>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<application ...>
...
</application>
</manifest>
Foreground service 시작하기
foreground 서비스를 실행하기 위해서 intent를 생성 후 startForegroundService()를 호출한다. API Level 26 이상에서는 앱이 포그라운드 서비스를 만들어야 하는 경우 startForegroundService()를 호출해야 한다. 그리고 서비스가 만들어지고나서 서비스는 5초 이내에 startForeground()를 호출해야 한다.
val intent = Intent(...) // Build the intent for the service
applicationContext.startForegroundService(intent)
그 후 대부분 service의 onStartCommand() 코드 안에서 service가 foreground에서 작동하도록 startForeground()를 호출합니다. 매개변수로는 알림을 식별할 수 있는 값과 알림 객체 자체를 넘기면 된다.
val pendingIntent: PendingIntent =
Intent(this, ExampleActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, 0)
}
val notification: Notification = Notification.Builder(this, CHANNEL_DEFAULT_IMPORTANCE)
.setContentTitle(getText(R.string.notification_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)
제한
Android 12 이상의 앱에서는 background있는 동안 foreground 서비스를 실행할 수 없다. 만약 background에 있는 동안 foreground 서비스를 실행한다면 특별한 경우를 제외하고 ForegroundServiceStartNotAllowedException 에러가 발생한다.
Foreground 서비스 종료하기
foreground 서비스를 제거하기 위해서 stopForeground()를 호출하면 된다. 이 메서드는 boolean 값을 인자로 가지는데 이는 상태바에서 알림이 제거되었는지를 나타낸다.
만약 서비스를 foreground에서 수행하는 동안 service를 종료한다면, 알림도 사라진다.
- 참고
[안드로이드] 컴포넌트 - 서비스개요와 ForegroundService
'안드로이드' 카테고리의 다른 글
[Android] 안드로이드 컴포즈란? (0) | 2024.10.12 |
---|---|
Clean Architecture + MVVM Pattern (0) | 2024.08.06 |
[Android] ListAdapter, AsyncListDiffer, DiffUtil 알아보기 (0) | 2024.06.28 |
shouldShowRequestPermissionRationale (0) | 2024.03.06 |
RecyclerView(리사이클러뷰) (0) | 2024.02.02 |