content provider와 상호작용할 수 있다.서비스는 스레드를 생성하지 않고 메인 스레드에서 실행되기 때문에, 서비스의 작업이 많다면 성능의 저하가 오거나 '애플리케이션이 응답하지 않습니다(ANR)' 오류(오류가 나면 제거 되나요?)가 날 수 있기 때문에 서비스 내에서 별도의 스레드를 생성하여 사용한다면 위험을 줄일 수 있다.
onCreate()안에 스레드를 생성하고 이를 onStart()에서 실행시키고, onStop()에서 중단하면 된다. Thread클래스 대신 AsyncTask또는 HandlerThread를 사용하는 방안도 고려해보자 관련문서class MusicService : Service() {
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
val notification = NotificationCompat.Builder(this, "channel_id")
.setContentTitle("재생 중")
.setContentText("좋은 음악을 듣고 있어요")
.setSmallIcon(R.drawable.ic_music_note)
.build()
startForeground(1, notification)
// 음악 재생 로직 시작
return START_STICKY
}
override fun onBind(intent: Intent?): IBinder? = null
}
| 분류 기준 | 이름 | 설명 |
|---|---|---|
| 실행 방식 | Started Service | startService()로 시작되며, 백그라운드 작업 후 스스로 종료됨 |
Bound Service | bindService()로 시작되며, 클라이언트(Activity 등)가 바인딩을 해제하면 종료됨 | |
| 실행 상태 | Foreground Service | 사용자에게 알림(Notification) 을 통해 보여지며, 시스템에서 강제 종료되지 않음 |
Background Service | 알림 없이 동작하며, Android 8.0 이상에선 제약이 많음 (몇 초 내 종료될 수 있음) |
Bound Service
Ex)
val intent = Intent(context, MyService::class.java)
context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
예를들어 백그라운드에서 음악 플레이어가 실행되고 음악에 대한 정보를 notification을 통해 알려준다. 이 notification은 서비스가 중단되거나 foreground에서 제거되지 않는 이상 안드로이드 OS 시스템에 의해 제거 되지 않는다.
Background Service는 사용하기 까다롭기 때문에 정말 특정한 상황에서만 사용되며, 대부분의 경우 Foreground Service나 WorkManager로 대체되고 있다앱이 API 레벨 26이상 앱이 포그라운드에 있지 않을 때 시스템에서 백그라운드 서비스 실행에 대한 제한을 적용하고, 백그라운드 처리 가이드를 따라야 한다.요즘에도 Background Service를 쓸 수 있는 경우는?
startService()를 호출하게 되면 이 메소드가 실행되고 서비스가 시작된다.stopSelf()또는 stopService() 메소드를 호출해야 한다.bindService()를 호출하게 되면 이 메소드가 실행되고 서비스에 바인딩 된다.onCreate()가 실행되며, Service에 대한 설정을 이 메소드에서 구현하도록 한다.onCreate()는 onStartCommand() 또는 onBind()를 호출하기 전에 호출되며 이미 서비스가 실행중일 경우에는 onCreate()는 호출되지 않는다.onDestroy()가 호출된다.onDestroy()에서는 서비스에서 실행한 Thread, Listener, Reciever등의 리소스를 정리하도록 한다.<service>요소를 <application> 요소의 하위로 추가하면 된다.<manifest ... >
...
<application ... >
<service android:name=".ExampleService" />
...
</application>
</manifest>
<service>에 속성을 추가하여 필요한 권한과 특성을 정의할 수 있다
android:name은 필수로 입력해야하며, 서비스의 클래스 이름을 입력한다.
앱의 보안을 위해 Service를 시작할 때는 항상 명시적 intent만 사용해야 한다.
Android 5.0(API 레벨21)부터 시스템은 개발자가 암시적 intent로 bindService()를 호출하면 예외를 발생시킨다.
android:exported="false" 속성을 추가하면 다른 앱에 의해 서비스가 실행되는 걸 막을 수 있다.
android:description 속성은 사용자에게 실행중인 서비스에 대한 설명을 제공하도록 하여 사용자가 서비스의 출처를 모르고 중단시키지 않도록 한다.