Forgound Service 생명주기
Forgound Service 통신
Forgound Service 최적화
Foreground Service 생명주기
Managing the lifecycle of a service
서비스의 수명 주기는 액티비티의 수명 주기보다 훨씬 간단합니다. 하지만 서비스를 생성하고 소멸하는 방법에 특히 주의를 기울여야 한다는 면에서 중요도는 이쪽이 더 높습니다. 서비스는 사용자가 모르는 채로 백그라운드에서 실행될 수 있기 때문입니다.
서비스 수명 주기(생성된 시점부터 소멸되는 시점까지)는 두 가지 서로 다른 경로를 따를 수 있습니다.
- 시작된 서비스
- 다른 구성 요소가 [startService()]를 호출하면 서비스가 생성됩니다. 그러면 서비스가 무기한으로 실행될 수 있으며, [stopSelf()]를 호출하여 자체적으로 중단해야 합니다. 다른 구성 요소도 [stopService()]를 호출하면 서비스를 중단시킬 수 있습니다. 서비스가 중단되면 시스템이 이를 소멸시킵니다.
- 바인딩된 서비스
- 다른 구성 요소(클라이언트)가 [bindService()]를 호출하면 서비스가 생성됩니다. 그러면 클라이언트가 [IBinder] 인터페이스를 통해 서비스와 통신을 주고받을 수 있습니다. 클라이언트가 연결을 종료하려면 [unbindService()]를 호출하면 됩니다. 여러 클라이언트가 같은 서비스에 바인딩될 수 있으며, 모든 클라이언트가 바인딩을 해제하면 시스템이 해당 서비스를 소멸시킵니다 서비스가 스스로 중단하지 않아도 됩니다.
이 두 가지 경로는 완전히 별개는 아닙니다. 이미 [startService()]로 시작된 서비스에 바인딩할 수도 있습니다. 예를 들어 재생할 음악을 식별하는 [Intent]를 포함해 [startService()]를 호출하면 백그라운드 음악 서비스를 시작할 수 있습니다. 나중에 아마도 사용자가 플레이어에 좀 더 많은 통제력을 발휘하려고 하거나 현재 노래에 대한 정보를 얻고자 할 때, 액티비티가 [bindService()]를 호출하여 서비스에 바인딩할 수 있습니다. 이와 같은 경우에는 모든 클라이언트가 바인딩을 해제할 때까지 [stopService()] 또는 [stopSelf()]가 서비스를 중단하지 않습니다.
Service Lifecycle
class ExampleService : Service() {
private var startMode: Int = 0 // indicates how to behave if the service is killed
private var binder: IBinder? = null // interface for clients that bind
private var allowRebind: Boolean = false // indicates whether onRebind should be used
override fun onCreate() {
// The service is being created
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
// The service is starting, due to a call to startService()
return mStartMode
}
override fun onBind(intent: Intent): IBinder? {
// A client is binding to the service with bindService()
return mBinder
}
override fun onUnbind(intent: Intent): Boolean {
// All clients have unbound with unbindService()
return mAllowRebind
}
override fun onRebind(intent: Intent) {
// A client is binding to the service with bindService(),
// after onUnbind() has already been called
}
override fun onDestroy() {
// The service is no longer used and is being destroyed
}
}
Foreground Service 통신
- ChatGPT 답변
- BroadcastReceiver 사용 BroadcastReceiver를 등록하고 Intent를 전달하여 Foreground Service에 명령을 보낼 수 있습니다. Foreground Service에서는 BroadcastReceiver를 수신하여 해당 작업을 수행하도록 할 수 있습니다.
- LocalBroadcastManager 사용 LocalBroadcastManager를 사용하여 Foreground Service에서 브로드캐스트 이벤트를 보내고 수신할 수 있습니다. 이 방법은 BroadcastReceiver와 유사하지만 로컬 브로드캐스트를 사용하기 때문에 안전하고 효율적입니다.
- Messenger 사용 Messenger를 사용하여 Foreground Service와 메시지를 주고받을 수 있습니다. 메시지는 Android.os.Message 클래스를 사용하여 전송하고 수신합니다. 이 방법은 Intent와 BroadcastReceiver를 사용하는 것보다 조금 더 복잡하지만, Foreground Service와 안전하게 통신할 수 있습니다.
- AIDL 사용 AIDL (Android Interface Definition Language)를 사용하여 서비스와 통신할 수 있습니다. 이 방법은 Service와 다른 애플리케이션 간의 통신에 사용되며, 인터페이스를 정의하고 메서드를 호출하여 Foreground Service와 상호작용 할 수 있습니다.
Intent(BroadcastReceiver)
Extend the Binder class
- 로컬 애플리케이션만 서비스를 사용하고 프로세스 간에 작업할 필요가 없는 경우 [Binder]서비스의 공용 메서드에 대한 클라이언트 직접 액세스를 제공하는 자체 클래스를 구현할 수 있습니다.
**참고:** 이는 클라이언트와 서비스가 동일한 애플리케이션 및 프로세스에 있는 경우에만 작동하며 가장 일반적입니다.
예를 들어 백그라운드에서 음악을 재생하는 자체 서비스에 활동을 바인딩해야 하는 음악 애플리케이션에 적합합니다.
설정 방법은 다음과 같습니다.
- 서비스에서 다음 중 하나를 수행하는 Binder인스턴스를 만듭니다.
- 클라이언트가 호출할 수 있는 공용 메서드를 포함합니다.
- [Service]클라이언트가 호출할 수 있는 공개 메서드가 있는 현재 인스턴스를 반환합니다 .
- 클라이언트가 호출할 수 있는 공용 메서드를 사용하여 서비스에서 호스팅하는 다른 클래스의 인스턴스를 반환합니다.
- [onBind()]콜백 메서드에서 Binder 인스턴스를 반환합니다.
- 클라이언트에서 콜백 메서드 [onServiceConnected()]에서 Binder를 수신하고 제공된 메서드를 사용하여 바인딩된 서비스를 호출합니다.
class LocalService : Service() {
// Binder given to clients.
private val binder = LocalBinder()
// Random number generator.
private val mGenerator = Random()
/** Method for clients. */
val randomNumber: Int
get() = mGenerator.nextInt(100)
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
inner class LocalBinder : Binder() {
// Return this instance of LocalService so clients can call public methods.
fun getService(): LocalService = this@LocalService
}
override fun onBind(intent: Intent): IBinder {
return binder
}
}
class BindingActivity : Activity() {
private lateinit var mService: LocalService
private var mBound: Boolean = false
/** Defines callbacks for service binding, passed to bindService(). */
private val connection = object : ServiceConnection {
override fun onServiceConnected(className: ComponentName, service: IBinder) {
// We've bound to LocalService, cast the IBinder and get LocalService instance.
val binder = service as LocalService.LocalBinder
mService = binder.getService()
mBound = true
}
override fun onServiceDisconnected(arg0: ComponentName) {
mBound = false
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.main)
}
override fun onStart() {
super.onStart()
// Bind to LocalService.
Intent(this, LocalService::class.java).also { intent ->
bindService(intent, connection, Context.BIND_AUTO_CREATE)
}
}
override fun onStop() {
super.onStop()
unbindService(connection)
mBound = false
}
/** Called when a button is clicked (the button in the layout file attaches to
* this method with the android:onClick attribute). */
fun onButtonClick(v: View) {
if (mBound) {
// Call a method from the LocalService.
// However, if this call is something that might hang, then put this request
// in a separate thread to avoid slowing down the activity performance.
val num: Int = mService.randomNumber
Toast.makeText(this, "number: $num", Toast.LENGTH_SHORT).show()
}
}
}
참고: 앞의 예에서 [onStop()]메서드는 서비스에서 클라이언트를 바인딩 해제합니다.
[추가 참고 사항] 섹션 에서 설명한 대로 적절한 시간에 서비스에서 클라이언트 바인딩을 해제합니다 .
IPC(Inter-Process Communication, 프로세스 간 통신)
Foreground Service 최적화
- ChatGPT 답변
- 필요한 작업만 수행하도록 서비스를 설계하십시오. 서비스가 백그라운드에서 실행 중일 때 필요한 작업만 수행하도록 설계하면 리소스 사용량을 줄일 수 있습니다. 예를 들어, 위치 정보를 가져 오는 경우, 위치 정보를 가져 오는 작업을 수행하는 동안에만 서비스를 실행하고 그렇지 않은 경우에는 서비스를 중지하십시오.
- Foreground Service에서 사용하는 리소스를 최소화하십시오. Foreground Service에서 사용하는 리소스를 최소화하면 배터리 수명을 연장할 수 있습니다. 예를 들어, 서비스가 작동 중일 때 불필요한 데이터베이스 또는 네트워크 호출을 피하십시오.
- 대기 시간을 최소화하십시오. Foreground Service가 사용자에게 계속해서 정보를 표시하도록하면 대기 시간을 최소화할 수 있습니다. 예를 들어, 노티피케이션을 사용하여 Foreground Service가 실행 중인 것을 사용자에게 알리고 작업을 수행하고 있는 동안 진행 상황을 계속해서 업데이트하십시오.
- 백그라운드 작업을 최적화하십시오. Foreground Service가 실행 중이지 않은 경우에도 필요한 작업을 수행하기 위해 백그라운드 작업을 사용하십시오. 예를 들어, AlarmManager나 JobScheduler를 사용하여 Foreground Service가 실행 중이지 않은 경우에도 정기적으로 작업을 수행하십시오.
- 리소스 누출을 방지하십시오. 리소스 누출을 방지하도록 코드를 작성하십시오. Foreground Service가 실행 중인 동안 리소스 누출이 발생하면 성능에 영향을 미칠 수 있습니다.
Foreground Service CheckList
- Android 13(API 레벨 33)부터 사용자는 기본적으로 포그라운드 서비스와 연결된 알림을 해제할 수 있습니다. 사용자가 알림을 닫을 수 없게 하려면 Notification.Builder를 사용하여 알림을 만들 때 [setOngoing()] 메소드에 true 전달하십시오.
- Android 13(API 레벨 33) 이상에서 사용자가 알림 권한을 거부하면 작업 관리자 에 포그라운드 서비스 관련 알림이 계속 표시되지만 알림 창에는 표시되지 않습니다.
- Android 9(API 레벨 28) 이상을 대상으로 하고 포그라운드 서비스를 사용하는 앱은 [FOREGROUND_SERVICE] 다음 코드 스니펫과 같이 권한을 요청해야 합니다. 이는 정상적인 권한 이므로 시스템에서 요청한 앱에 자동으로 권한을 부여합니다.
- 서비스를 포그라운드 서비스로 실행하도록 시스템에 요청하기 전에 서비스 자체를 시작하십시오. 이후 5초 이내 startForeground를 호출해야 함.
- startForegroundService(Service)
- startForeground(ID, Notification)
- Android 12(API 레벨 31) 이상을 대상으로 하는 앱은 몇 가지 특별한 경우를 제외하고는 백그라운드에서 실행되는 동안 포그라운드 서비스를 시작할 수 없습니다.
- 12 이상에서 앱이 백그라운드에서 실행되는 동안 포그라운드 서비스를 시작하는 것을 발견하면 WorkManager 를 사용하도록 앱의 로직을 업데이트하세요.
Background 시작 제한 면제
- Activity와 같이 사용자에게 표시되는 상태
- FCM을 사용하는 경우
- 유저가 UI와 상호작용 할 수 있는 경우
- Notification, Bubble, Widget 등
- 유저의 액션에 대해 정확한 알람을 사용하는 경우
- 지오펜싱 또는 사용자 활동에 대한 이벤트를 수신받는 경우
- [ACTION_BOOT_COMPLETED], [ACTION_LOCKED_BOOT_COMPLETED], or [ACTION_MY_PACKAGE_REPLACED] 이벤트에 대해 BroadcastReceiver에서 수신받는 경우
- [ACTION_TIMEZONE_CHANGED], [ACTION_TIME_CHANGED], or [ACTION_LOCALE_CHANGED] 이벤트에 대해 BroadcastReceiver에서 수신받는 경우
- Bluetooth Receiver에 대해서 다음 권한을 수신받는 경우. [BLUETOOTH_CONNECT] or [BLUETOOTH_SCAN] 앱은 Companion Device Manager를 사용해야 하며, [REQUEST_COMPANION_RUN_IN_BACKGROUND] or [REQUEST_COMPANION_START_FOREGROUND_SERVICES_FROM_BACKGROUND] 퍼미션을 선언해야 한다.
- 기기 소유자 또는 프로필 소유자와 같은 특정 시스템 권한 또는 역할이 있는 앱• 사용자가 앱의 배터리 최적화를 끕니다. 시스템 설정에서 앱의 앱 정보 페이지로 사용자를 전송하여 사용자가 이 옵션을 찾도록 도울 수 있습니다. 이렇게 하려면 [ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS] 인텐트 작업이 포함된 인텐트를 호출합니다.
References
서비스 개요 | Android 개발자 | Android Developers
서비스 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Service는 백그라운드에서 오래 실행되는 작업을 수행할 수 있는 애플리케이션 구성 요소이며 사
developer.android.com
Foreground services | Android Developers
Foreground services Stay organized with collections Save and categorize content based on your preferences. Foreground services perform operations that are noticeable to the user. Foreground services show a status bar notification, to make users aware that
developer.android.com
바인드된 서비스 개요 | Android 개발자 | Android Developers
바인드된 서비스 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 바인드된 서비스란 클라이언트-서버 인터페이스 안의 서버를 말합니다. 이를 사용하
developer.android.com