diff options
Diffstat (limited to 'docs/html-intl/intl/ko/guide/components/services.jd')
-rw-r--r-- | docs/html-intl/intl/ko/guide/components/services.jd | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/docs/html-intl/intl/ko/guide/components/services.jd b/docs/html-intl/intl/ko/guide/components/services.jd new file mode 100644 index 000000000000..fb95ea5ed0fa --- /dev/null +++ b/docs/html-intl/intl/ko/guide/components/services.jd @@ -0,0 +1,813 @@ +page.title=서비스 +@jd:body + +<div id="qv-wrapper"> +<ol id="qv"> +<h2>이 문서의 내용</h2> +<ol> +<li><a href="#Basics">기본 정보</a></li> +<ol> + <li><a href="#Declaring">매니페스트에서 서비스 선언하기</a></li> +</ol> +<li><a href="#CreatingAService">시작된 서비스 생성하기</a> + <ol> + <li><a href="#ExtendingIntentService">IntentService 클래스 확장하기</a></li> + <li><a href="#ExtendingService">서비스 클래스 확장하기</a></li> + <li><a href="#StartingAService">서비스 시작</a></li> + <li><a href="#Stopping">서비스 중단</a></li> + </ol> +</li> +<li><a href="#CreatingBoundService">바인딩된 서비스 생성</a></li> +<li><a href="#Notifications">사용자에게 알림 전송</a></li> +<li><a href="#Foreground">전경에서 서비스 실행하기</a></li> +<li><a href="#Lifecycle">서비스 수명 주기 관리</a> +<ol> + <li><a href="#LifecycleCallbacks">수명 주기 콜백 구현하기</a></li> +</ol> +</li> +</ol> + +<h2>Key 클래스</h2> +<ol> + <li>{@link android.app.Service}</li> + <li>{@link android.app.IntentService}</li> +</ol> + +<h2>샘플</h2> +<ol> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code + ServiceStartArguments}</a></li> + <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code + LocalService}</a></li> +</ol> + +<h2>참고 항목</h2> +<ol> +<li><a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a></li> +</ol> + +</div> + + +<p>{@link android.app.Service}는 배경에서 오래 실행되는 작업을 +수행할 수 있는 애플리케이션 구성 요소이며 사용자 인터페이스를 제공하지 않습니다. 또 다른 +애플리케이션 구성 요소가 서비스를 시작할 수 있으며, 이는 사용자가 또 다른 +애플리케이션으로 전환하더라도 배경에서 계속해서 실행됩니다. 이외에도, 구성 요소를 서비스에 바인딩하여 +서비스와 상호 작용할 수 있으며, 심지어는 프로세스 간 통신(IPC)도 수행할 수 있습니다. 예를 들어 한 서비스는 +네트워크 트랜잭션을 처리하고, 음악을 재생하고 파일 I/O를 수행하거나 콘텐츠 제공자와 상호 작용할 수 있으며 +이 모든 것을 배경에서 수행할 수 있습니다.</p> + +<p>서비스는 본질적으로 두 가지 형식을 취합니다.</p> + +<dl> + <dt>시작됨</dt> + <dd>서비스가 "시작된" 상태가 되려면 애플리케이션 구성 요소(예: 액티비티)가 +{@link android.content.Context#startService startService()}를 호출하여 시작하면 됩니다. 서비스는 한 번 시작되고 나면 +배경에서 무기한으로 실행될 수 있으며, 이는 해당 서비스를 시작한 구성 요소가 소멸되었더라도 무관합니다. 보통, +시작된 서비스는 한 작업을 수행하고 결과를 발신자에게 반환하지 않습니다. +예를 들어 네트워크에서 파일을 다운로드하거나 업로드할 수 있습니다. 작업을 완료하면, 해당 서비스는 +알아서 중단되는 것이 정상입니다.</dd> + <dt>바인딩됨</dt> + <dd>서비스가 "바인딩된" 상태가 되려면 애플리케이션 구성 요소가 {@link +android.content.Context#bindService bindService()}를 사용하여 해당 서비스에 바인딩되면 됩니다. 바인딩된 서비스는 클라이언트-서버 +인터페이스를 제공하여 구성 요소가 서비스와 상호 작용할 수 있도록 해주며, 결과를 가져올 수도 있고 심지어 +이와 같은 작업을 여러 프로세스에 걸쳐 프로세스 간 통신(IPC)으로 수행할 수도 있습니다. 바인딩된 서비스는 또 다른 애플리케이션 구성 요소가 +이에 바인딩되어 있는 경우에만 실행됩니다. 여러 개의 구성 요소가 서비스에 한꺼번에 바인딩될 수 있지만, +이 모든 것이 바인딩을 해제하면 해당 서비스는 소멸됩니다.</dd> +</dl> + +<p>이 문서는 주로 이러한 두 가지 유형의 서비스를 따로따로 논하지만, 서비스는 +두 가지 방식 모두로 작동할 수 있습니다. 즉 서비스가 시작될 수도 있고(나아가 무기한으로 실행되고) 바인딩도 허용할 수 있다는 뜻입니다. +이는 그저 두어 가지 콜백 메서드의 구현 여부에 달린 문제입니다. {@link +android.app.Service#onStartCommand onStartCommand()}를 사용하면 구성 요소가 서비스를 시작할 수 있게 허용하고, {@link +android.app.Service#onBind onBind()}를 사용하면 바인딩을 허용합니다.</p> + +<p>애플리케이션이 시작되었든, 바인딩되었든 아니면 양쪽 모두이든 모든 애플리케이션 구성 요소가 +해당 서비스를 사용할 수 있으며(별도의 애플리케이션에서라도), 이는 어느 구성 요소든 액티비티를 +사용할 수 있는 것과 같습니다. 이를 {@link android.content.Intent}로 시작하면 됩니다. 그러나, +매니페스트에서 서비스를 비공개로 선언하고 다른 애플리케이션으로부터의 액세스를 차단할 수도 있습니다. 이것은 +<a href="#Declaring">매니페스트에서 서비스 +선언하기</a>에 관한 섹션에서 더 자세히 이야기합니다.</p> + +<p class="caution"><strong>주의:</strong> 서비스는 자신의 호스팅 프로세스의 +기본 스레드에서 실행됩니다. 서비스는 자신의 스레드를 직접 생성하지 <strong>않으며</strong>, +별도의 프로세스에서 실행되지도 <strong>않습니다</strong>(별도로 지정하는 경우는 예외). 이것은 즉, +서비스가 CPU 집약적인 작업을 수행할 예정이거나 차단적인 작업을 수행할 예정인 경우(예를 들어 MP3 +재생 또는 네트워킹 등), 서비스 내에 새 스레드를 생성하여 해당 작업을 수행하도록 해야 한다는 뜻입니다. 별도의 스레드를 사용하면 +'애플리케이션이 응답하지 않습니다(ANR)' 오류가 일어날 위험을 줄일 수 있으며 +애플리케이션의 기본 스레드는 액티비티와 사용자 상호 작용 전용으로 유지될 수 있습니다.</p> + + +<h2 id="Basics">기본 정보</h2> + +<div class="sidebox-wrapper"> +<div class="sidebox"> + <h3>서비스와 스레드 중 어느 것을 사용해야 할까요?</h3> + <p>서비스는 그저 배경에서 실행될 수 있는 구성 요소일 뿐입니다. 이는 사용자가 +애플리케이션과 상호 작용하지 않아도 관계 없이 해당됩니다. 따라서, 서비스를 생성하는 것은 꼭 그것이 필요할 때만으로 국한되어야 +합니다.</p> + <p>기본 스레드 외부에서 작업을 수행해야 하지만 사용자가 애플리케이션과 상호 작용 중인 +동안에만 수행하면 되는 경우라면, 서비스가 아니라 그 대신 새 스레드를 생성해야 합니다. 예를 들어 +액티비티가 실행되는 중에만 음악을 재생하고자 하는 경우, +{@link android.app.Activity#onCreate onCreate()} 안에 스레드를 생성하고 이를 {@link +android.app.Activity#onStart onStart()}에서 실행하기 시작한 다음 {@link android.app.Activity#onStop +onStop()}에서 중단하면 됩니다. 또한, 기존의 {@link java.lang.Thread} 클래스 대신 +{@link android.os.AsyncTask} 또는 {@link android.os.HandlerThread}를 사용하는 방안도 고려하십시오. 스레드에 관한 자세한 정보는 <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">프로세스 및 +스레딩</a> 문서를 참조하십시오.</p> + <p>서비스를 사용하는 경우 기본적으로 애플리케이션의 기본 스레드에서 +계속 실행되므로 서비스가 집약적이거나 차단적인 작업을 수행하는 경우 여전히 서비스 내에 +새 스레드를 생성해야 한다는 점을 명심하십시오.</p> +</div> +</div> + +<p>서비스를 생성하려면 {@link android.app.Service}의 하위 클래스를 생성해야 합니다(아니면 이의 +기존 하위 클래스 중 하나). 구현에서는 서비스 수명 주기의 주요 측면을 처리하는 콜백 메서드를 +몇 가지 재정의해야 하며 서비스에 바인딩할 구성 요소에 대한 메커니즘을 +제공해야 합니다(해당되는 경우). 재정의해야 하는 가장 중요한 콜백 메서드는 다음과 같습니다.</p> + +<dl> + <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt> + <dd>시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소(예: 액티비티)가 서비스를 +시작하도록 요청하는 경우입니다. 이때 {@link android.content.Context#startService +startService()}를 호출하는 방법을 씁니다. 이 메서드가 실행되면 서비스가 시작되고 배경에서 무기한으로 실행될 수 +있습니다. 이것을 구성하면 서비스의 작업이 완료되었을 때 해당 서비스를 중단하는 것은 +개발자 본인의 책임입니다. 이때 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link +android.content.Context#stopService stopService()}를 호출하면 됩니다 (바인딩만 제공하고자 하는 경우, 이 메서드를 구현하지 +않아도 됩니다).</dd> + <dt>{@link android.app.Service#onBind onBind()}</dt> + <dd>시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소가 해당 서비스에 바인딩되고자 하는 경우 +(예를 들어 RPC를 수행하기 위해)입니다. 이때 {@link android.content.Context#bindService +bindService()}를 호출하는 방법을 씁니다. 이 메서드를 구현할 때에는 클라이언트가 서비스와 통신을 주고받기 위해 사용할 +인터페이스를 제공해야 합니다. 이때 {@link android.os.IBinder}를 반환하면 됩니다. 이 메서드는 항상 +구현해야 하지만, 바인딩을 허용하지 않고자 하면 null을 반환해야 합니다.</dd> + <dt>{@link android.app.Service#onCreate()}</dt> + <dd>시스템이 이 메서드를 호출하는 것은 서비스가 처음 생성되어 일회성 설정 +절차를 수행하는 경우입니다({@link android.app.Service#onStartCommand onStartCommand()} 또는 +{@link android.app.Service#onBind onBind()}를 호출하기 전에). 서비스가 이미 실행 중인 경우, 이 메서드는 호출되지 +않습니다.</dd> + <dt>{@link android.app.Service#onDestroy()}</dt> + <dd>시스템이 이 메서드를 호출하는 것은 해당 서비스를 더 이상 사용하지 않고 소멸시키는 경우입니다. +서비스에 이것을 구현해야 스레드, 등록된 각종 수신기(listener, receiver) 등 +모든 리소스를 정리할 수 있습니다. 이것이 서비스가 수신하는 마지막 호출입니다.</dd> +</dl> + +<p>한 구성 요소가 {@link +android.content.Context#startService startService()}를 호출하여 서비스를 시작하면({@link +android.app.Service#onStartCommand onStartCommand()}로의 호출을 초래함), 해당 서비스는 +알아서 {@link android.app.Service#stopSelf()}로 스스로를 중단할 때까지 또는 +또 다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 서비스를 중단시킬 때까지 실행 중인 상태로 유지됩니다.</p> + +<p>한 구성 요소가 +{@link android.content.Context#bindService bindService()}를 호출하여 서비스를 생성하는 경우(그리고 {@link +android.app.Service#onStartCommand onStartCommand()}를 호출하지 <em>않은</em> 경우), 해당 서비스는 +해당 구성 요소가 바인딩되어 있는 경우에만 실행됩니다. 서비스가 모든 클라이언트로부터 바인딩 해제되면 시스템이 이를 +소멸시킵니다.</p> + +<p>Android 시스템이 서비스를 강제 중단시키는 것은 메모리가 부족하여 사용자가 초점을 집중하고 있는 +액티비티를 위해 시스템 리소스를 회복해야만 하는 경우로만 국한됩니다. 해당 서비스가 사용자의 주목을 +끌고 있는 액티비티에 바인딩되어 있다면 중단될 가능성이 낮고, 서비스가 <a href="#Foreground">전경에서 실행</a>된다고 선언된 경우(나중에 자세히 논함), 거의 절대 중단되지 않습니다. +그렇지 않으면, 서비스가 시작되었고 오랫동안 실행되는 경우 +시간이 지나면서 시스템이 배경 작업 목록에서의 이 서비스의 위치를 점점 낮추고 +서비스는 중단되기 매우 쉬워집니다. 서비스가 시작되었다면 이를 시스템에 의한 재시작을 정상적으로 +처리하도록 디자인해야 합니다. 시스템이 서비스를 중단시키는 경우, 리소스를 다시 사용할 수 있게 되면 +시스템이 가능한 한 빨리 이를 다시 시작합니다(다만 이것은 개발자가 {@link +android.app.Service#onStartCommand onStartCommand()}에서 반환하는 값에도 좌우됩니다. 이 내용은 나중에 논합니다). 시스템이 서비스를 +소멸시킬 수 있는 경우에 대한 자세한 정보는 <a href="{@docRoot}guide/components/processes-and-threads.html">프로세스 및 스레딩</a> +문서를 참조하십시오.</p> + +<p>다음 섹션에서는 각 유형의 서비스를 생성하는 방법과 다른 애플리케이션 구성 요소에서 +이를 사용하는 방법을 배우게 됩니다.</p> + + + +<h3 id="Declaring">매니페스트에서 서비스 선언하기</h3> + +<p>액티비티(및 다른 구성 요소)와 마찬가지로, 서비스는 모두 애플리케이션의 매니페스트 +파일에서 선언해야 합니다.</p> + +<p>서비스를 선언하려면 <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> 요소를 +<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> + 요소의 하위로 추가하면 됩니다. 예:</p> + +<pre> +<manifest ... > + ... + <application ... > + <service android:name=".ExampleService" /> + ... + </application> +</manifest> +</pre> + +<p>매니페스트에서 서비스를 선언하는 데 대한 자세한 정보는 <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> +요소 참조를 확인하십시오.</p> + +<p><a href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> 요소에 포함시킬 수 있는 다른 속성도 있습니다. +이를 포함시켜 서비스를 시작하는 데 필요한 권한과 서비스가 실행되어야 하는 프로세스 등의 +속성을 정의할 수 있습니다. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> +속성이 유일한 필수 속성입니다. 이것은 서비스의 클래스 이름을 나타냅니다. 일단 애플리케이션을 +게시하고 나면 이 이름을 변경해서는 안 됩니다. 이름을 변경하면 +서비스를 시작하거나 바인딩할 명시적 인텐트에 대한 종속성으로 인해 코드를 단절시킬 위험이 있기 때문입니다(블로그 게시물의 <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html"> +바꿀 수 없는 항목</a>을 참조하십시오). + +<p>앱의 보안을 보장하려면 <strong> +{@link android.app.Service}을 시작하거나 바인딩할 때 항상 명시적 인텐트를 사용하고</strong> 서비스에 대한 인텐트 필터는 선언하지 마십시오. 어느 +서비스를 시작할지 어느 정도 모호성을 허용하는 것이 중요한 경우, 서비스에 대해 +인텐트 필터를 제공하고 구성 요소 이름을 {@link +android.content.Intent}에서 배제할 수 있지만, 그러면 해당 인텐트에 대한 패키지를 {@link +android.content.Intent#setPackage setPackage()}로 설정하여 대상 서비스에 대해 충분한 명확화를 +제공하도록 해야 합니다.</p> + +<p>이외에도 서비스를 본인의 앱에만 사용 가능하도록 보장할 수도 있습니다. +<a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a> + 속성을 포함시킨 뒤 이를 {@code "false"}로 설정하면 됩니다. 이렇게 하면 다른 앱이 여러분의 서비스를 시작하지 못하도록 효과적으로 방지해주며, +이는 명시적 인텐트를 사용하는 경우에도 문제 없이 적용됩니다.</p> + + + + +<h2 id="CreatingStartedService">시작된 서비스 생성하기</h2> + +<p>시작된 서비스란 다른 구성 요소가 {@link +android.content.Context#startService startService()}를 호출하여 시작하고, 그 결과 서비스의 +{@link android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하는 결과를 초래한 것을 말합니다.</p> + +<p>서비스가 시작되면 이를 시작한 구성 요소와 독립된 자신만의 +수명 주기를 가지며 해당 서비스는 배경에서 무기한으로 실행될 수 있습니다. 이는 해당 서비스를 +시작한 구성 요소가 소멸되었더라도 무관합니다. 따라서, 서비스는 작업이 완료되면 +{@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 알아서 중단되는 것이 정상이며 아니면 다른 구성 요소가 +{@link android.content.Context#stopService stopService()}를 호출하여 중단시킬 수도 있습니다.</p> + +<p>애플리케이션 구성 요소(예: 액티비티)가 서비스를 시작하려면 {@link +android.content.Context#startService startService()}를 호출하고, {@link android.content.Intent}를 +전달하면 됩니다. 이것은 서비스를 나타내고 서비스가 사용할 모든 데이터를 포함합니다. 서비스는 이 +{@link android.content.Intent}를 {@link android.app.Service#onStartCommand +onStartCommand()} 메서드에서 수신합니다.</p> + +<p>예를 들어 어느 액티비티가 온라인 데이터베이스에 데이터를 약간 저장해야 한다고 가정합니다. 액티비티가 +동반자 서비스를 시작하여 저장할 데이터를 이에 전달할 수 있습니다. 이때 인텐트를 {@link +android.content.Context#startService startService()}에 전달하면 됩니다. 서비스는 이 인텐트를 {@link +android.app.Service#onStartCommand onStartCommand()}에서 수신하고 인터넷에 연결한 다음 데이터베이스 +트랜잭션을 수행합니다. 작업을 완료하면, 해당 서비스는 알아서 스스로 중단되고 +소멸됩니다.</p> + +<p class="caution"><strong>주의:</strong> 서비스는 기본적으로 자신이 선언된 애플리케이션의 같은 +프로세스에서 실행되기도 하고 해당 애플리케이션의 기본 스레드에서 실행되기도 합니다. 따라서, 사용자가 +같은 애플리케이션의 액티비티와 상호 작용하는 동안 서비스가 집약적이거나 차단적인 작업을 수행하는 경우, +해당 서비스 때문에 액티비티 성능이 느려지게 됩니다. 애플리케이션 성능에 영향을 미치는 것을 방지하려면, +서비스 내에서 새 스레드를 시작해야 합니다.</p> + +<p>기존에는 시작된 서비스를 생성하기 위해 확장할 수 있는 클래스가 두 개 있었습니다.</p> +<dl> + <dt>{@link android.app.Service}</dt> + <dd>이것이 모든 서비스의 기본 클래스입니다. 이 클래스를 확장하는 경우, 서비스의 모든 작업을 수행할 +새 스레드를 만드는 것이 중요합니다. 서비스가 기본적으로 애플리케이션의 기본 스레드를 사용하기 +때문인데, 이로 인해 애플리케이션이 실행 중인 모든 액티비티의 성능이 +느려질 수 있기 때문입니다.</dd> + <dt>{@link android.app.IntentService}</dt> + <dd>이것은 {@link android.app.Service}의 하위 클래스로, 작업자 스레드를 +사용하여 모든 시작 요청을 처리하되 한 번에 하나씩 처리합니다. 서비스가 여러 개의 요청을 +동시에 처리하지 않아도 되는 경우 이것이 최선의 옵션입니다. 해야 할 일은 {@link +android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐으로, 이것이 각 시작 요청에 대한 인텐트를 수신하여 +개발자는 배경 작업을 수행할 수 있습니다.</dd> +</dl> + +<p>다음 섹션에서는 이와 같은 클래스 중 하나를 사용하여 서비스를 구현하는 방법을 +설명합니다.</p> + + +<h3 id="ExtendingIntentService">IntentService 클래스 확장하기</h3> + +<p>대부분의 시작된 서비스는 여러 개의 요청을 동시에 처리하지 않아도 되기 때문에 +(이는 사실 위험한 다중 스레딩 시나리오일 수 있습니다), 서비스를 구현할 때에는 +{@link android.app.IntentService} 클래스를 사용하는 것이 최선의 방안일 것입니다.</p> + +<p>{@link android.app.IntentService}는 다음과 같은 작업을 수행합니다.</p> + +<ul> + <li>애플리케이션의 기본 스레드와는 별도로 {@link +android.app.Service#onStartCommand onStartCommand()}에 전달된 모든 인텐트를 실행하는 기본 작업자 스레드를 +생성합니다.</li> + <li>한 번에 인텐트를 하나씩 {@link +android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 전달하는 작업 대기열을 생성하므로 다중 스레딩에 대해 염려할 필요가 +전혀 없습니다.</li> + <li>시작 요청이 모두 처리된 후 서비스를 중단하므로 개발자가 +{@link android.app.Service#stopSelf}를 호출할 필요가 전혀 없습니다.</li> + <li>{@link android.app.IntentService#onBind onBind()}의 기본 구현을 제공하여 null을 +반환하도록 합니다.</li> + <li>{@link android.app.IntentService#onStartCommand +onStartCommand()}의 기본 구현을 제공하여 인텐트를 작업 대기열에 보내고, 다음으로 {@link +android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 보내도록 합니다.</li> +</ul> + +<p>이 모든 것은 결론적으로 개발자가 직접 할 일은 클라이언트가 제공한 작업을 수행할 {@link +android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐이라는 사실로 +이어집니다. (다만, 서비스에 대해 작은 생성자를 제공해야 하기도 합니다.)</p> + +<p>다음은 {@link android.app.IntentService}의 구현을 예시로 나타낸 것입니다.</p> + +<pre> +public class HelloIntentService extends IntentService { + + /** + * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} + * constructor with a name for the worker thread. + */ + public HelloIntentService() { + super("HelloIntentService"); + } + + /** + * The IntentService calls this method from the default worker thread with + * the intent that started the service. When this method returns, IntentService + * stops the service, as appropriate. + */ + @Override + protected void onHandleIntent(Intent intent) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + } +} +</pre> + +<p>필요한 것은 이게 전부입니다. 생성자 하나와 {@link +android.app.IntentService#onHandleIntent onHandleIntent()} 구현뿐이죠.</p> + +<p>다른 콜백 메서드도 재정의하기로 결정하는 경우-예를 들어 {@link +android.app.IntentService#onCreate onCreate()}, {@link +android.app.IntentService#onStartCommand onStartCommand()} 또는 {@link +android.app.IntentService#onDestroy onDestroy()}-슈퍼 구현을 꼭 호출해야 합니다. +그래야 {@link android.app.IntentService}가 작업자 스레드의 수명을 적절하게 처리할 수 있습니다.</p> + +<p>예를 들어 {@link android.app.IntentService#onStartCommand onStartCommand()}는 반드시 +기본 구현을 반환해야 합니다(이로써 인텐트가 {@link +android.app.IntentService#onHandleIntent onHandleIntent()}로 전달되는 것입니다).</p> + +<pre> +@Override +public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + return super.onStartCommand(intent,flags,startId); +} +</pre> + +<p>{@link android.app.IntentService#onHandleIntent onHandleIntent()} 외에 슈퍼 클래스를 +호출하지 않아도 되는 유일한 메서드는 {@link android.app.IntentService#onBind +onBind()}입니다(다만 이를 구현하는 것은 서비스가 바인딩을 허용할 때에만 필요합니다).</p> + +<p>다음 섹션에서는 기본 {@link android.app.Service} +클래스를 확장할 때 같은 종류의 서비스를 구현하는 방법을 배우게 됩니다. 이때에는 코드가 훨씬 많이 필요하지만, +동시 시작 요청을 처리해야 하는 경우 이것이 적절할 수 있습니다.</p> + + +<h3 id="ExtendingService">서비스 클래스 확장하기</h3> + +<p>이전 섹션에서 본 것과 같이 {@link android.app.IntentService}를 사용하면 +시작된 서비스 구현이 매우 단순해집니다. 하지만 서비스가 다중 스레딩을 +수행해야 하는 경우(작업 대기열을 통해 시작 요청을 처리하는 대신), 그때는 +{@link android.app.Service} 클래스를 확장하여 각 인텐트를 처리하게 할 수 있습니다.</p> + +<p>비교를 위해 다음 예시의 코드를 보겠습니다. 이는 {@link +android.app.Service} 클래스의 구현으로, 위의 예시에서 {@link +android.app.IntentService}를 사용하여 수행한 것과 똑같은 작업을 수행합니다. 바꿔 말하면 각 시작 요청에 대해 +작업자 스레드를 사용하여 작업을 수행하고 한 번에 요청을 하나씩만 처리한다는 뜻입니다.</p> + +<pre> +public class HelloService extends Service { + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + + // Handler that receives messages from the thread + private final class ServiceHandler extends Handler { + public ServiceHandler(Looper looper) { + super(looper); + } + @Override + public void handleMessage(Message msg) { + // Normally we would do some work here, like download a file. + // For our sample, we just sleep for 5 seconds. + long endTime = System.currentTimeMillis() + 5*1000; + while (System.currentTimeMillis() < endTime) { + synchronized (this) { + try { + wait(endTime - System.currentTimeMillis()); + } catch (Exception e) { + } + } + } + // Stop the service using the startId, so that we don't stop + // the service in the middle of handling another job + stopSelf(msg.arg1); + } + } + + @Override + public void onCreate() { + // Start up the thread running the service. Note that we create a + // separate thread because the service normally runs in the process's + // main thread, which we don't want to block. We also make it + // background priority so CPU-intensive work will not disrupt our UI. + HandlerThread thread = new HandlerThread("ServiceStartArguments", + Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + + // Get the HandlerThread's Looper and use it for our Handler + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); + + // For each start request, send a message to start a job and deliver the + // start ID so we know which request we're stopping when we finish the job + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + mServiceHandler.sendMessage(msg); + + // If we get killed, after returning from here, restart + return START_STICKY; + } + + @Override + public IBinder onBind(Intent intent) { + // We don't provide binding, so return null + return null; + } + + @Override + public void onDestroy() { + Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); + } +} +</pre> + +<p>보시다시피 {@link android.app.IntentService}를 사용할 때보다 훨씬 손이 많이 갑니다.</p> + +<p>그러나, 각 호출을 {@link android.app.Service#onStartCommand +onStartCommand()}로 직접 처리할 수 있기 때문에 여러 개의 요청을 동시에 수행할 수 있습니다. 이 예시는 그것을 +보여주는 것은 아니지만, 그런 작업을 원하는 경우 각 요청에 대해 새 스레드를 +하나씩 생성한 다음 곧바로 실행하면 됩니다(이전 요청이 끝날 때까지 기다리는 대신).</p> + +<p>{@link android.app.Service#onStartCommand onStartCommand()} 메서드가 반드시 +정수를 반환해야 한다는 사실을 유의하십시오. 정수는 시스템이 서비스를 중단시킨 경우 시스템이 해당 서비스를 +계속하는 방법에 대해 설명하는 값입니다(위에서 논한 바와 같이 {@link +android.app.IntentService}의 기본 구현이 이것을 개발자 대신 처리해줍니다. 개발자가 이를 수정할 수도 있습니다). +{@link android.app.Service#onStartCommand onStartCommand()}로부터의 반환 값은 반드시 +다음 상수 중 하나여야 합니다.</p> + +<dl> + <dt>{@link android.app.Service#START_NOT_STICKY}</dt> + <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand +onStartCommand()} 반환 후에 중단시키면 서비스를 재생성하면 <em>안 됩니다.</em> 다만 전달할 +보류 인텐트가 있는 경우는 예외입니다. 이것은 서비스가 불필요하게 실행되는 일을 피할 수 있는 가장 안전한 옵션이며, +애플리케이션이 완료되지 않은 모든 작업을 단순히 재시작할 수 있을 때 좋습니다.</dd> + <dt>{@link android.app.Service#START_STICKY}</dt> + <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand +onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 {@link +android.app.Service#onStartCommand onStartCommand()}를 호출하되 마지막 인텐트를 다시 전달하지는 <em>마십시오.</em> +그 대신, 시스템이 null 인텐트로 {@link android.app.Service#onStartCommand onStartCommand()}를 +호출합니다. 다만 서비스를 시작할 보류 인텐트가 있는 경우만은 예외이며, 이럴 때에는 +그러한 인텐트를 전달합니다. 이것은 명령을 실행하지는 않지만 무기한으로 실행 중이며 작업을 기다리고 있는 +미디어 플레이어(또는 그와 비슷한 서비스)에 적합합니다.</dd> + <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt> + <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand +onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 서비스에 전달된 마지막 인텐트로 {@link +android.app.Service#onStartCommand onStartCommand()}를 +호출하십시오. 모든 보류 인텐트가 차례로 전달됩니다. 이것은 즉시 재개되어야 하는 작업을 +능동적으로 수행 중인 서비스(예를 들어 파일 다운로드 등)에 적합합니다.</dd> +</dl> +<p>이러한 반환 값에 대한 자세한 내용은 각 상수에 대해 링크로 연결된 참조 문서를 +확인하십시오.</p> + + + +<h3 id="StartingAService">서비스 시작</h3> + +<p>액티비티나 다른 구성 요소에서 서비스를 시작하려면 +{@link android.content.Intent}를(시작할 서비스를 나타냄) {@link +android.content.Context#startService startService()}에 전달하면 됩니다. Android 시스템이 서비스의 {@link +android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하여 여기에 {@link +android.content.Intent}를 전달합니다. ({@link android.app.Service#onStartCommand +onStartCommand()}를 직접 호출하면 절대로 안 됩니다.)</p> + +<p>예를 들어 이전 섹션의 예시 서비스({@code +HelloService})를 액티비티가 시작하려면 {@link android.content.Context#startService +startService()}로 명시적 인텐트를 사용하면 됩니다.</p> + +<pre> +Intent intent = new Intent(this, HelloService.class); +startService(intent); +</pre> + +<p>{@link android.content.Context#startService startService()} 메서드가 즉시 반환되며 +Android 시스템이 서비스의 {@link android.app.Service#onStartCommand +onStartCommand()} 메서드를 호출합니다. 서비스가 이미 실행 중이지 않은 경우, 시스템은 우선 {@link +android.app.Service#onCreate onCreate()}를 호출하고, 다음으로 {@link android.app.Service#onStartCommand +onStartCommand()}를 호출합니다.</p> + +<p>서비스가 바인딩도 제공하지 않는 경우, {@link +android.content.Context#startService startService()}와 함께 전달된 인텐트가 애플리케이션 구성 요소와 서비스 사이의 +유일한 통신 방법입니다. 그러나 서비스가 결과를 돌려보내기를 원하는 경우, 서비스를 시작한 +클라이언트가 브로드캐스트를 위해 {@link android.app.PendingIntent}를 +만들 수 있고({@link android.app.PendingIntent#getBroadcast getBroadcast()} 사용) 이를 서비스를 시작한 +{@link android.content.Intent} 내의 서비스에 전달할 수 있습니다. 그러면 서비스가 +이 브로드캐스트를 사용하여 결과를 전달할 수 있게 됩니다.</p> + +<p>서비스를 시작하기 위한 여러 개의 요청은 서비스의 +{@link android.app.Service#onStartCommand onStartCommand()}로의 상응하는 여러 개의 호출이라는 결과를 낳습니다. 하지만, 서비스를 중단하려면 +이를 중단하라는 요청 하나({@link android.app.Service#stopSelf stopSelf()} 또는 {@link +android.content.Context#stopService stopService()} 사용)만 있으면 됩니다.</p> + + +<h3 id="Stopping">서비스 중단</h3> + +<p>시작된 서비스는 자신만의 수명 주기를 직접 관리해야 합니다. 다시 말해, 시스템이 +서비스를 중단하거나 소멸시키지 않는다는 뜻입니다. 다만 시스템 메모리를 회복해야 하고 서비스가 +{@link android.app.Service#onStartCommand onStartCommand()} 반환 후에도 계속 실행되는 경우는 예외입니다. 따라서, +서비스는 {@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 중단시켜야 하고, 아니면 +다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 이를 중단시킬 수 있습니다.</p> + +<p>일단 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link +android.content.Context#stopService stopService()}로 중단하기를 요청하고 나면 시스템이 서비스를 가능한 한 빨리 +소멸시킵니다.</p> + +<p>그러나, 서비스가 {@link +android.app.Service#onStartCommand onStartCommand()}로의 요청을 동시에 여러 개 처리하기를 바라는 경우라면 시작 요청 처리를 완료한 뒤에도 +서비스를 중단하면 안 됩니다. 그 이후 새 시작 요청을 받았을 수 있기 +때문입니다(첫 요청 종료 시에 중단하면 두 번째 요청을 종료시킵니다). 이 문제를 +피하려면, {@link android.app.Service#stopSelf(int)}를 사용하여 서비스를 +중단시키라는 개발자의 요청이 항상 최신 시작 요청에 기반하도록 해야 합니다. 다시 말해, {@link +android.app.Service#stopSelf(int)}를 호출할 때면 시작 요청의 ID({@link android.app.Service#onStartCommand onStartCommand()}에 전달된 +<code>startId</code>)를 전달하게 됩니다. 여기에 중단 요청이 +부합됩니다. 그런 다음 개발자가 {@link +android.app.Service#stopSelf(int)}를 호출할 수 있기 전에 서비스가 새 시작 요청을 받은 경우, ID가 일치하지 않게 되고 서비스는 중단되지 않습니다.</p> + +<p class="caution"><strong>주의:</strong> 서비스가 작업을 완료한 다음 애플리케이션이 +소속 서비스를 중단할 수 있어야 한다는 점이 중요합니다. 그래야 시스템 리소스 낭비를 피하고 배터리 전력 소모를 줄일 수 있습니다. 필요한 경우 +다른 구성 요소도 서비스를 중단시킬 수 있습니다. {@link +android.content.Context#stopService stopService()}를 호출하면 됩니다. 서비스에 대해 바인딩을 활성화하더라도, +서비스가 {@link +android.app.Service#onStartCommand onStartCommand()}로의 호출을 한 번이라도 받았으면 항상 서비스를 직접 중단시켜야 합니다.</p> + +<p>서비스의 수명 주기에 대한 자세한 정보는 아래에 있는 <a href="#Lifecycle">서비스 수명 주기 관리</a>에 관한 섹션을 참고하세요.</p> + + + +<h2 id="CreatingBoundService">바인딩된 서비스 생성</h2> + +<p>바인딩된 서비스는 애플리케이션 구성 요소가 자신에게 바인딩될 수 있도록 허용하는 서비스로, 이때 {@link +android.content.Context#bindService bindService()}를 호출하여 오래 지속되는 연결을 생성합니다 +(또한 보통은 구성 요소가 {@link +android.content.Context#startService startService()}를 호출하여 서비스를 <em>시작</em>하는 것을 허용하지 않습니다).</p> + +<p>액티비티와 애플리케이션의 다른 구성 요소에서 서비스와 상호 작용하기를 원하는 경우 +바인딩된 서비스를 생성해야 합니다. 아니면 애플리케이션의 기능 몇 가지를 프로세스 간 통신(IPC)을 통해 +다른 애플리케이션에 노출하고자 하는 경우에도 좋습니다.</p> + +<p>바인딩된 서비스를 생성하려면 {@link +android.app.Service#onBind onBind()} 콜백 메서드를 구현하여 서비스와의 통신을 위한 인터페이스를 정의하는 +{@link android.os.IBinder}를 반환하도록 해야 합니다. 그러면 다른 애플리케이션 구성 요소가 +{@link android.content.Context#bindService bindService()}를 호출하여 해당 인터페이스를 검색하고, 서비스에 있는 메서드를 +호출하기 시작할 수 있습니다. 서비스는 자신에게 바인딩된 애플리케이션 구성 요소에게 도움이 되기 위해서만 +존재하는 것이므로, 서비스에 바인딩된 구성 요소가 없으면 시스템이 이를 소멸시킵니다(바인딩된 서비스는 시작된 서비스처럼 +{@link android.app.Service#onStartCommand onStartCommand()}를 통해 +중단시키지 <em>않아도</em> 됩니다).</p> + +<p>바인딩된 서비스를 생성하려면 가장 먼저 해야 할 일은 클라이언트가 서비스와 +통신할 수 있는 방법을 나타내는 인터페이스를 정의하는 것입니다. 서비스와 클라이언트 사이에서 쓰이는 이 인터페이스는 +반드시 {@link android.os.IBinder}의 구현이어야 하며 이를 +서비스가 {@link android.app.Service#onBind +onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@link android.os.IBinder}를 수신하면 해당 인터페이스를 통해 서비스와 +상호 작용을 시작할 수 있습니다.</p> + +<p>여러 클라이언트가 서비스에 한꺼번에 바인딩될 수 있습니다. 클라이언트가 서비스와의 상호 작용을 완료하면 이는 +{@link android.content.Context#unbindService unbindService()}를 호출하여 바인딩을 해제합니다. 서비스에 +바인딩된 클라이언트가 하나도 없으면 시스템이 해당 서비스를 소멸시킵니다.</p> + +<p>바인딩된 서비스를 구현하는 데에는 여러 가지 방법이 있으며 그러한 구현은 시작된 서비스보다 +훨씬 복잡합니다. 따라서 바인딩된 서비스 논의는 +<a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a>에 관한 별도의 문서에서 다룹니다.</p> + + + +<h2 id="Notifications">사용자에게 알림 전송</h2> + +<p>서비스는 일단 실행되고 나면 사용자에게 <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">알림 메시지</a> 또는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄 알림</a> 등을 사용해 이벤트를 알릴 수 있습니다.</p> + +<p>알림 메시지란 현재 창의 표면에 잠시 나타났다가 사라지는 메시지이고, +상태 표시줄 알림은 상태 표시줄에 메시지가 담긴 아이콘을 제공하여 사용자가 이를 선택하여 +조치를 취할 수 있게 하는 것입니다(예: 액티비티 시작).</p> + +<p>보통, 일종의 배경 작업이 완료되었고 +(예: 파일 다운로드 완료) 이제 사용자가 그에 대해 조치를 취할 수 있는 경우 상태 표시줄 알림이 +최선의 기법입니다. 사용자가 확장된 보기에서 알림을 선택하면, +해당 알림이 액티비티를 시작할 수 있습니다(예: 다운로드한 파일 보기).</p> + +<p>자세한 정보는 <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">알림 메시지</a> 또는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄 알림</a> +개발자 가이드를 참조하십시오.</p> + + + +<h2 id="Foreground">전경에서 서비스 실행하기</h2> + +<p>전경 서비스는 사용자가 능동적으로 인식하고 있으므로 메모리 부족 시에도 +시스템이 중단할 후보로 고려되지 않는 서비스를 말합니다. 전경 +서비스는 상태 표시줄에 대한 알림을 제공해야 합니다. 이것은 +"진행 중" 제목 아래에 배치되며, 이는 곧 해당 알림은 서비스가 중단되었거나 +전경에서 제거되지 않은 이상 무시할 수 없다는 뜻입니다.</p> + +<p>예를 들어 서비스에서 음악을 재생하는 음악 플레이어는 전경에서 +실행되도록 설정해야 합니다. 사용자가 이것의 작동을 분명히 인식하고 있기 +때문입니다. 상태 표시줄에 있는 알림은 현재 노래를 나타내고 +사용자로 하여금 음악 플레이어와 상호 작용할 액티비티를 시작하게 해줄 수도 있습니다.</p> + +<p>서비스가 전경에서 실행되도록 요청하려면 {@link +android.app.Service#startForeground startForeground()}를 호출하면 됩니다. 이 메서드는 두 개의 매개변수를 취합니다. +그 중 하나는 해당 알림을 고유하게 식별하는 정수이고 다른 하나는 상태 표시줄에 해당되는 {@link +android.app.Notification}입니다. 예:</p> + +<pre> +Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), + System.currentTimeMillis()); +Intent notificationIntent = new Intent(this, ExampleActivity.class); +PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); +notification.setLatestEventInfo(this, getText(R.string.notification_title), + getText(R.string.notification_message), pendingIntent); +startForeground(ONGOING_NOTIFICATION_ID, notification); +</pre> + +<p class="caution"><strong>주의:</strong> {@link +android.app.Service#startForeground startForeground()}에 부여하는 정수 ID가 0이면 안 됩니다.</p> + + +<p>서비스를 전경에서 제거하려면 {@link +android.app.Service#stopForeground stopForeground()}를 호출하면 됩니다. 이 메서드는 부울 값을 취하며, 이것이 +상태 표시줄 알림도 제거할지 여부를 나타냅니다. 이 메서드는 서비스를 중단시키지 <em>않습니다</em>. + 그러나, 서비스가 전경에서 실행 중인 동안 서비스를 중단시키면 +알림도 마찬가지로 제거됩니다.</p> + +<p>알림에 대한 자세한 정보는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄 +알림 생성</a>을 참조하십시오.</p> + + + +<h2 id="Lifecycle">서비스 수명 주기 관리</h2> + +<p>서비스의 수명 주기는 액티비티의 수명 주기보다 훨씬 간단합니다. 하지만, 서비스를 생성하고 +소멸시키는 방법에 특히 주의를 기울여야 한다는 면에서 중요도는 이쪽이 더 높습니다. 서비스는 사용자가 모르는 채로 +배경에서 실행될 수 있기 때문입니다.</p> + +<p>서비스 수명 주기—생성되었을 때부터 소멸될 때까지—는 두 가지 서로 다른 경로를 +따를 수 있습니다.</p> + +<ul> +<li>시작된 서비스 + <p>서비스는 또 다른 구성 요소가 {@link +android.content.Context#startService startService()}를 호출하면 생성됩니다. 그러면 서비스가 무기한으로 실행될 수 있으며 +스스로 알아서 중단되어야 합니다. 이때 {@link +android.app.Service#stopSelf() stopSelf()}를 호출하는 방법을 씁니다. 또 다른 구성 요소도 서비스를 중단시킬 수 +있습니다. {@link android.content.Context#stopService +stopService()}를 호출하면 됩니다. 서비스가 중단되면 시스템이 이를 소멸시킵니다.</p></li> + +<li>바인딩된 서비스 + <p>서비스는 또 다른 구성 요소(클라이언트)가 {@link +android.content.Context#bindService bindService()}를 호출하면 생성됩니다. 그러면 클라이언트가 +{@link android.os.IBinder} 인터페이스를 통해 서비스와 통신을 주고받을 수 있습니다. 클라이언트가 연결을 종료하려면 +{@link android.content.Context#unbindService unbindService()}를 호출하면 됩니다. 여러 클라이언트가 같은 서비스에 +바인딩될 수 있으며, 이 모두가 바인딩을 해제하면 시스템이 해당 서비스를 소멸시킵니다 (서비스가 스스로를 중단시키지 +<em>않아도</em> 됩니다).</p></li> +</ul> + +<p>이와 같은 두 가지 경로는 완전히 별개의 것은 아닙니다. 다시 말해, 이미 +{@link android.content.Context#startService startService()}로 시작된 서비스에 바인딩할 수도 있다는 뜻입니다. 예를 +들어, 배경 음악 서비스를 시작하려면 {@link android.content.Context#startService +startService()}를 호출하되 재생할 음악을 식별하는 {@link android.content.Intent}를 사용하면 됩니다. 나중에, +아마도 사용자가 플레이어에 좀 더 많은 통제권을 발휘하고자 하거나 +현재 노래에 대한 정보를 얻고자 할 때, 액티비티가 서비스에 바인딩될 수 있습니다. {@link +android.content.Context#bindService bindService()}를 사용하면 됩니다. 이런 경우에는 {@link +android.content.Context#stopService stopService()} 또는 {@link android.app.Service#stopSelf +stopSelf()}도 클라이언트가 모두 바인딩 해제될 때까지 실제로 서비스를 중단시키지 않습니다. </p> + + +<h3 id="LifecycleCallbacks">수명 주기 콜백 구현하기</h3> + +<p>액티비티와 마찬가지로 서비스에도 수명 주기 콜백 메서드가 있어 이를 구현하면 서비스의 +상태 변경 내용을 모니터링할 수 있고 적절한 시기에 작업을 수행할 수 있습니다. 다음의 골격 +서비스는 각 수명 주기 메서드를 설명한 것입니다.</p> + +<pre> +public class ExampleService extends Service { + int mStartMode; // indicates how to behave if the service is killed + IBinder mBinder; // interface for clients that bind + boolean mAllowRebind; // indicates whether onRebind should be used + + @Override + public void {@link android.app.Service#onCreate onCreate}() { + // The service is being created + } + @Override + public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { + // The service is starting, due to a call to {@link android.content.Context#startService startService()} + return <em>mStartMode</em>; + } + @Override + public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()} + return <em>mBinder</em>; + } + @Override + public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { + // All clients have unbound with {@link android.content.Context#unbindService unbindService()} + return <em>mAllowRebind</em>; + } + @Override + public void {@link android.app.Service#onRebind onRebind}(Intent intent) { + // A client is binding to the service with {@link android.content.Context#bindService bindService()}, + // after onUnbind() has already been called + } + @Override + public void {@link android.app.Service#onDestroy onDestroy}() { + // The service is no longer used and is being destroyed + } +} +</pre> + +<p class="note"><strong>참고:</strong> 액티비티 수명 주기 콜백 메서드와는 달리 이와 같은 콜백 메서드를 구현하는 데에는 +슈퍼클래스 구현을 호출하지 <em>않아도</em> 됩니다.</p> + +<img src="{@docRoot}images/service_lifecycle.png" alt="" /> +<p class="img-caption"><strong>그림 2.</strong> 서비스 수명 주기입니다. 왼쪽의 다이어그램은 +서비스가 {@link android.content.Context#startService +startService()}로 생성된 경우의 수명 주기를 나타내며 오른쪽의 다이어그램은 서비스가 +{@link android.content.Context#bindService bindService()}로 생성된 경우의 수명 주기를 나타낸 것입니다.</p> + +<p>이와 같은 메서드를 구현함으로써, 서비스 수명 주기의 두 가지 중첩된 루프를 모니터링할 수 있습니다. </p> + +<ul> +<li>서비스의 <strong>수명 주기 전체</strong>는 {@link +android.app.Service#onCreate onCreate()}가 호출된 시점과 {@link +android.app.Service#onDestroy}가 반환된 시점 사이에 일어납니다. 액티비티와 마찬가지로 서비스는 자신의 초기 설정을 +{@link android.app.Service#onCreate onCreate()}에서 수행하며 남은 리소스를 모두 {@link +android.app.Service#onDestroy onDestroy()}에 릴리스합니다. 예를 들어 +음악 재생 서비스의 경우 음악이 재생될 스레드를 {@link +android.app.Service#onCreate onCreate()}로 생성하고, 그럼 다음 해당 스레드를 중단할 때에는 {@link +android.app.Service#onDestroy onDestroy()}에서 할 수도 있습니다. + +<p>{@link android.app.Service#onCreate onCreate()}와 {@link android.app.Service#onDestroy +onDestroy()} 메서드는 모든 서비스에 대해 호출됩니다. 이는 서비스가 +{@link android.content.Context#startService startService()}로 생성되었든 {@link +android.content.Context#bindService bindService()}로 생성되었든 관계 없이 적용됩니다.</p></li> + +<li>서비스의 <strong>활성 수명 주기</strong>는 {@link +android.app.Service#onStartCommand onStartCommand()} 또는 {@link android.app.Service#onBind onBind()}로의 호출과 함께 시작됩니다. +각 메서드에 {@link +android.content.Intent}가 전달되는데 이것은 각각 {@link android.content.Context#startService +startService()} 또는 {@link android.content.Context#bindService bindService()} 중 하나에 전달된 것입니다. +<p>서비스가 시작되면 수명 주기 전체가 종료되는 것과 동시에 활성 수명 주기도 종료됩니다 +(서비스는 {@link android.app.Service#onStartCommand +onStartCommand()}가 반환된 뒤에도 여전히 활성 상태입니다). 서비스가 바인딩된 경우, 활성 수명 주기는 {@link +android.app.Service#onUnbind onUnbind()}가 반환되면 종료됩니다.</p> +</li> +</ul> + +<p class="note"><strong>참고:</strong> 시작된 서비스를 중단하려면 +{@link android.app.Service#stopSelf stopSelf()} 또는 {@link +android.content.Context#stopService stopService()}를 호출하면 되지만, 서비스에 대한 상응하는 콜백은 +없습니다(즉 {@code onStop()} 콜백이 없습니다). 그러므로, 서비스가 클라이언트에 바인딩되어 있지 않은 한 +시스템은 서비스가 중단되면 이를 소멸시킵니다. 수신되는 콜백은 {@link +android.app.Service#onDestroy onDestroy()}가 유일합니다.</p> + +<p>그림 2는 서비스에 대한 일반적인 콜백 메서드를 나타낸 것입니다. 이 그림에서는 +{@link android.content.Context#startService startService()}로 생성된 서비스와 +{@link android.content.Context#bindService bindService()}로 생성된 서비스를 +구분하고 있지만, 어떤 식으로 시작되었든 모든 서비스는 클라이언트가 자신에 바인딩되도록 허용할 수 있다는 점을 명심하십시오. +말하자면, {@link android.app.Service#onStartCommand +onStartCommand()}로 처음 시작된 서비스(클라이언트가 {@link android.content.Context#startService startService()}를 호출해서)라고 해도 +여전히 {@link android.app.Service#onBind onBind()}로의 호출을 받을 수 있습니다(클라이언트가 +{@link android.content.Context#bindService bindService()}를 호출하는 경우).</p> + +<p>바인딩을 제공하는 서비스 생성에 대한 자세한 내용은 <a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a> 문서를 참조하십시오. 이 안에는 {@link android.app.Service#onRebind onRebind()} +콜백 메서드에 대한 자세한 정보가 <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">바인딩된 서비스의 +수명 주기 관리</a>에 관한 섹션에 +담겨 있습니다.</p> + + +<!-- +<h2>Beginner's Path</h2> + +<p>To learn how to query data from the system or other applications (such as contacts or media +stored on the device), continue with the <b><a +href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b> +document.</p> +--> |