본문 바로가기
안드로이드 자바

[Android][java] 서비스 onStartCommand()와 플래그

by teamnova 2023. 9. 26.
728x90

안녕하세요. 이전에 우리는 서비스를 어떻게 구현할 수 있는지 알아본 적이 있습니다. (참고 게시글: [JAVA][Andorid] 서비스 구현하기) 이에 이어서 오늘은 서비스와 서비스 플래그에 대해 설명해보려고합니다.

 

  서비스는 액티비티와 마찬가지로 수명 주기 콜백 메서드(생명주기)가 있습니다. 플래그를 설명하기 위해서는 우선 서비스가 어떻게 생성되는지 이 생명주기부터 보아야합니다. 이 부분은 서비스 클래스 내의 onStartCommand() 를 설명하기 위함이니 혹시 기억이 나지않는다면 이전 게시글을 참고바랍니다.([Android][java] Service 사용 이해를 위한 예시)  

 

서비스의 생명주기 그림(출처: 안드로이드 공식사이트) startService()로 호출된 경우와 bindService()로 호출 된 두 경우를 보여주고 있다.

 

위 그림에서 서비스의 생명주기는 호출 된 방법에 따라 어떻게 생명주기가 다른지를 설명하고 있지만, 기본적으로 서비스는 onCreate로 시작하여 onDestroy로 종료하는 것을 볼 수 있습니다. 아래는 공식 홈페이지의 설명입니다.

 

"서비스의 전체 수명은 onCreate()가 호출된 시점부터 onDestroy() 반환 시점까지입니다. 액티비티와 마찬가지로 서비스는 자신의 초기 설정을 onCreate()에서 수행하며, 남은 리소스를 모두 onDestroy() 에서 릴리스합니다. 예를 들어 음악 재생 서비스는 스레드를 생성하고, 이 스레드의 onCreate() 에서 음악이 재생됩니다. 그 다음 onDestroy()에서 스레드를 중단할 수 있습니다."

요약:  onCreate() 및 onDestroy() 메서드는 모든 서비스에 대해 호출됩니다. 이는 서비스가 startService()
로 생성되었든 bindService() 로 생성되었든 상관없이 적용됩니다.
+참고 및 주의)
"위 그림에서는 호출 방식에 따라 서비스를 구분하고 있지만 , 어떤 식으로 시작되었든 모든 서비스는 클라이언트와 바인딩되도록 허용할 수 있습니다. "
"이 문서(공식사이트)에서는 시작된 서비스와 바인딩된 서비스를 전반적으로 별도로 논하지만, 서비스는 양쪽 방식으로 둘 다 작동할 수 있습니다. 즉 시작해서(무한히 실행되도록) 바인드도 허용할 수 있습니다. 이것은 단순히 두어 가지 콜백 메서드를 구현했는지 여부에 좌우되는 문제입니다."

요약: startService()로 서비스를 호출해도 여전히 서비스는 onBind()에 대한 호출을 받을 수 있습니다.

 

시작과 끝이 onCreate()와 onDestory 였다면, 서비스의 활성 수명은 onStartCommand()와 onBind()에서 시작합니다.

 onStartCommand()는 구성 요소가 서비스를 시작하게 하고 onBind()는 바인드를 허용합니다. (오늘은 onStartCommand()와 플래그에 대해 알아보려하기 때문에 onBind()에 대한 상세 내용은 다음에 포스팅하도록 하겠습니다.)

 

아래는 onStartCommand()에 대한 설명입니다. 

 

1) onStartCommand() : 서비스가 실질적으로 실행되는 부분.

 "이 메서드가 실행되면 서비스가 시작되고 백그라운드에서 무한히 실행될 수 있습니다. 이것을 구현하면 서비스의 작업이 완료되었을 때 해당 서비스를 중단하는 것은 개발자 본인의 책임이며, 이때 stopSelf() 또는 stopService()를 호출하면 됩니다. 바인딩만 제공하고자 하는 경우, 이 메서드를 구현하지 않아도 됩니다."

2) onStartCommand()의 구조

@Override
public int onStartCommand(Intent intent, int flags, int startId) {   
      //내부 코드 작성   
      return super.onStartCommand(intent,flags,startId);// 플래그가 리턴되는 부분
}

2-1) 파라미터/리턴 부분 설명

파라미터
intent Context.startService(Intent) 호출 시 파라미터로 전달 된 intent. 프로세스가 종료 후 서비스 재 시작 시, 이전 START_STICKY_COMPATIITY를 제외한 모든 서비스 플래그를 반환한 경우라면 null 일 수 있다.
flag 서비스 시작 요청에 대한 부가 데이터.(Additiona data)  값은 0 또는 START_FLAG_REDELIVERY, START_FLAG_RETRI의 조합이다.
startId 시작하고자하는 특정 요청을 나타내는 고유 정수(int). stopSelfResult와 함께 사용한다.
리턴
int  이 int 값은 서비스의 현재 시작 상태에 대해 시스템이 사용해야 하는 *시맨틱스를 나타냅니다. 

(START_STICKY_COMPATIITY,
 START_STICKY,
 START_NOT_STICKY,
 START_REDELIVER_INTENT 등을 사용합니다.)

위의 바로 리턴 값이 서비스의 플래그 값이라고 불리는 부분입니다. 위 설명에서 int 값이 '시스템이 사용해야 하는 *시맨틱스를 나타낸다.'라고 설명하는데, 말하자면 onStartCommand()는 마지막에 반드시 정수 값을 리턴하게 되는데 이 각 정수값들이 해당 서비스를 어떻게 동작해야하는지 나타낸다(의미한다)는 뜻입니다. 즉 개발 시 리턴값을 통해 우리는 서비스를 다르게 통제할 수 있습니다.

각 반환 정수 값에 따라 서비스가 어떻게 동작하는지는 아래 표로 정리해 보았습니다. 

플래그
플래그(시맨틱스) 이름 Constant Value (반환하는 int 값) 내용
START_STICKY_COMPATIITY 0
  • StartCommand(Intent, int, int)가 삭제된 후 다시 호출된다는 보장이 없는 START_STICKY 호환성 버전입니다. 
START_STICKY 1
  • 서비스가 강제로 종료되었을 때 시스템이 자동으로 다시 시작하도록 하는 방식입니다.
  • 서비스가 다른 추가적인 작업 없이도 계속 실행되어야 하는 경우에 주로 사용됩니다.
  • 시스템에 의해 재시작되면 onStartCommand()가 호출되지만 Intent는 Null이 전달됩니다.
START_NOT_STICKY 2
  • 서비스가 강제로 종료되었을 때 시스템이 자동으로 다시 시작하지 않도록 하는 방식입니다.
  • 이 방식은 서비스가 특정 작업을 완료한 후에는 더 이상 실행되지 않아도 되는 경우에 주로 사용됩니다.
  • 시스템 자원 부족으로 서비스가 강제종료되어도 문제가 없는 경우에 사용됩니다.
START_REDELIVER_INTENT 3
  • 서비스가 강제로 종료되었을 때 시스템이 자동으로 다시 시작하고, 마지막으로 전달된 Intent를 다시 전달해주는 방식입니다.
    (서비스가 시작되는 동안 이 서비스의 프로세스가 중지되면(onStartCommand()에서 반환된 후) 재시작이 예약되고 마지막으로 전달된 Intent가 onStartCommand()를 통해 다시 전달됩니다.


     Intent는 서비스 호출이 시작 ID(Intent, int, int)를 onStartCommand(onStartCommand)에 제공하는 Self(int)를 중지할 때까지 재전달이 예약된 상태로 유지됩니다. 서비스는 nullIntent로 전송된 모든 Intent 처리가 완료되지 않은 경우에만 다시 시작되므로(이러한 보류 중인 이벤트는 재시작 시점에 전달됩니다) nullIntent로 호출되지 않습니다.)

  • 서비스가 실행 중인 작업을 반드시 완료해야 하는 경우에 주로 사용됩니다.

  • 마지막으로 전달된 Intent가 다시 동일하게 전달되므로 취소된 작업을 이어서 수행할 수 있습니다.
  • 하지만 그만큼 시스템 자원을 더 사용하기 때문에 필수적인 작업의 완료를 보장하고 싶을 때에만 사용해야 합니다.

(출처: 안드로이드 공식 홈페이지 및 https://work2type.tistory.com/entry/STARTSTICKY-STARTNOTSTICKY

 

다음 포스트에서는 이어서 바인딩 서비스에 대해서 알아보겠습니다.

 

 

 

+) 자세한 내용은 아래 참고 부탁드립니다.

https://developer.android.com/guide/components/services?hl=ko 

 

서비스 개요  |  Android 개발자  |  Android Developers

서비스 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Service는 백그라운드에서 오래 실행되는 작업을 수행할 수 있는 애플리케이션 구성 요소이며 사

developer.android.com

https://developer.android.com/guide/components/bound-services?hl=ko 

 

바인드된 서비스 개요  |  Android 개발자  |  Android Developers

바인드된 서비스 개요 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 바인드된 서비스란 클라이언트-서버 인터페이스 안의 서버를 말합니다. 이를 사용하

developer.android.com

https://developer.android.com/reference/android/app/Service#onStartCommand(android.content.Intent,%20int,%20int) 

 

Service  |  Android Developers

 

developer.android.com

https://work2type.tistory.com/entry/STARTSTICKY-STARTNOTSTICKY

 

[안드로이드] START_STICKY & START_NOT_STICKY

🎈 안드로이드 서비스 오늘 알아볼 것은 안드로이드 서비스에서 주로 사용되는 세가지 시작 방법에 대한 정보입니다. START_STICKY, START_NOT_STICKY, START_REDELIVER_INTENT가 있으며, 각각에 대해 자세히

work2type.tistory.com