• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1page.title=서비스
2@jd:body
3
4<div id="qv-wrapper">
5<ol id="qv">
6<h2>이 문서의 내용</h2>
7<ol>
8<li><a href="#Basics">기본 정보</a></li>
9<ol>
10  <li><a href="#Declaring">매니페스트에서 서비스 선언하기</a></li>
11</ol>
12<li><a href="#CreatingAService">시작된 서비스 생성하기</a>
13  <ol>
14    <li><a href="#ExtendingIntentService">IntentService 클래스 확장하기</a></li>
15    <li><a href="#ExtendingService">서비스 클래스 확장하기</a></li>
16    <li><a href="#StartingAService">서비스 시작</a></li>
17    <li><a href="#Stopping">서비스 중단</a></li>
18  </ol>
19</li>
20<li><a href="#CreatingBoundService">바인딩된 서비스 생성</a></li>
21<li><a href="#Notifications">사용자에게 알림 전송</a></li>
22<li><a href="#Foreground">전경에서 서비스 실행하기</a></li>
23<li><a href="#Lifecycle">서비스 수명 주기 관리</a>
24<ol>
25  <li><a href="#LifecycleCallbacks">수명 주기 콜백 구현하기</a></li>
26</ol>
27</li>
28</ol>
29
30<h2>Key 클래스</h2>
31<ol>
32  <li>{@link android.app.Service}</li>
33  <li>{@link android.app.IntentService}</li>
34</ol>
35
36<h2>샘플</h2>
37<ol>
38  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code
39      ServiceStartArguments}</a></li>
40  <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code
41      LocalService}</a></li>
42</ol>
43
44<h2>참고 항목</h2>
45<ol>
46<li><a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a></li>
47</ol>
48
49</div>
50
51
52<p>{@link android.app.Service}는 배경에서 오래 실행되는 작업을
53수행할 수 있는 애플리케이션 구성 요소이며 사용자 인터페이스를 제공하지 않습니다. 또 다른
54애플리케이션 구성 요소가 서비스를 시작할 수 있으며, 이는 사용자가 또 다른
55애플리케이션으로 전환하더라도 배경에서 계속해서 실행됩니다. 이외에도, 구성 요소를 서비스에 바인딩하여
56서비스와 상호 작용할 수 있으며, 심지어는 프로세스 간 통신(IPC)도 수행할 수 있습니다. 예를 들어 한 서비스는
57네트워크 트랜잭션을 처리하고, 음악을 재생하고 파일 I/O를 수행하거나 콘텐츠 제공자와 상호 작용할 수 있으며
58이 모든 것을 배경에서 수행할 수 있습니다.</p>
59
60<p>서비스는 본질적으로 두 가지 형식을 취합니다.</p>
61
62<dl>
63  <dt>시작됨</dt>
64  <dd>서비스가 "시작된" 상태가 되려면 애플리케이션 구성 요소(예: 액티비티)가
65{@link android.content.Context#startService startService()}를 호출하여 시작하면 됩니다. 서비스는 한 번 시작되고 나면
66배경에서 무기한으로 실행될 수 있으며, 이는 해당 서비스를 시작한 구성 요소가 소멸되었더라도 무관합니다. 보통,
67시작된 서비스는 한 작업을 수행하고 결과를 발신자에게 반환하지 않습니다.
68예를 들어 네트워크에서 파일을 다운로드하거나 업로드할 수 있습니다. 작업을 완료하면, 해당 서비스는
69알아서 중단되는 것이 정상입니다.</dd>
70  <dt>바인딩됨</dt>
71  <dd>서비스가 "바인딩된" 상태가 되려면 애플리케이션 구성 요소가 {@link
72android.content.Context#bindService bindService()}를 사용하여 해당 서비스에 바인딩되면 됩니다. 바인딩된 서비스는 클라이언트-서버
73인터페이스를 제공하여 구성 요소가 서비스와 상호 작용할 수 있도록 해주며, 결과를 가져올 수도 있고 심지어
74이와 같은 작업을 여러 프로세스에 걸쳐 프로세스 간 통신(IPC)으로 수행할 수도 있습니다. 바인딩된 서비스는 또 다른 애플리케이션 구성 요소가
75이에 바인딩되어 있는 경우에만 실행됩니다. 여러 개의 구성 요소가 서비스에 한꺼번에 바인딩될 수 있지만,
76이 모든 것이 바인딩을 해제하면 해당 서비스는 소멸됩니다.</dd>
77</dl>
78
79<p>이 문서는 주로 이러한 두 가지 유형의 서비스를 따로따로 논하지만, 서비스는
80두 가지 방식 모두로 작동할 수 있습니다. 즉 서비스가 시작될 수도 있고(나아가 무기한으로 실행되고) 바인딩도 허용할 수 있다는 뜻입니다.
81이는 그저 두어 가지 콜백 메서드의 구현 여부에 달린 문제입니다. {@link
82android.app.Service#onStartCommand onStartCommand()}를 사용하면 구성 요소가 서비스를 시작할 수 있게 허용하고, {@link
83android.app.Service#onBind onBind()}를 사용하면 바인딩을 허용합니다.</p>
84
85<p>애플리케이션이 시작되었든, 바인딩되었든 아니면 양쪽 모두이든 모든 애플리케이션 구성 요소가
86해당 서비스를 사용할 수 있으며(별도의 애플리케이션에서라도), 이는 어느 구성 요소든 액티비티를
87사용할 수 있는 것과 같습니다. 이를 {@link android.content.Intent}로 시작하면 됩니다. 그러나,
88매니페스트에서 서비스를 비공개로 선언하고 다른 애플리케이션으로부터의 액세스를 차단할 수도 있습니다. 이것은
89<a href="#Declaring">매니페스트에서 서비스
90선언하기</a>에 관한 섹션에서 더 자세히 이야기합니다.</p>
91
92<p class="caution"><strong>주의:</strong> 서비스는 자신의 호스팅 프로세스의
93기본 스레드에서 실행됩니다. 서비스는 자신의 스레드를 직접 생성하지 <strong>않으며</strong>,
94별도의 프로세스에서 실행되지도 <strong>않습니다</strong>(별도로 지정하는 경우는 예외). 이것은 즉,
95서비스가 CPU 집약적인 작업을 수행할 예정이거나 차단적인 작업을 수행할 예정인 경우(예를 들어 MP3
96재생 또는 네트워킹 등), 서비스 내에 새 스레드를 생성하여 해당 작업을 수행하도록 해야 한다는 뜻입니다. 별도의 스레드를 사용하면
97'애플리케이션이 응답하지 않습니다(ANR)' 오류가 일어날 위험을 줄일 수 있으며
98애플리케이션의 기본 스레드는 액티비티와 사용자 상호 작용 전용으로 유지될 수 있습니다.</p>
99
100
101<h2 id="Basics">기본 정보</h2>
102
103<div class="sidebox-wrapper">
104<div class="sidebox">
105  <h3>서비스와 스레드 중 어느 것을 사용해야 할까요?</h3>
106  <p>서비스는 그저 배경에서 실행될 수 있는 구성 요소일 뿐입니다. 이는 사용자가
107애플리케이션과 상호 작용하지 않아도 관계 없이 해당됩니다. 따라서, 서비스를 생성하는 것은 꼭 그것이 필요할 때만으로 국한되어야
108합니다.</p>
109  <p>기본 스레드 외부에서 작업을 수행해야 하지만 사용자가 애플리케이션과 상호 작용 중인
110동안에만 수행하면 되는 경우라면, 서비스가 아니라 그 대신 새 스레드를 생성해야 합니다. 예를 들어
111액티비티가 실행되는 중에만 음악을 재생하고자 하는 경우,
112{@link android.app.Activity#onCreate onCreate()} 안에 스레드를 생성하고 이를 {@link
113android.app.Activity#onStart onStart()}에서 실행하기 시작한 다음 {@link android.app.Activity#onStop
114onStop()}에서 중단하면 됩니다. 또한, 기존의 {@link java.lang.Thread} 클래스 대신
115{@link android.os.AsyncTask} 또는 {@link android.os.HandlerThread}를 사용하는 방안도 고려하십시오. 스레드에 관한 자세한 정보는 <a href="{@docRoot}guide/components/processes-and-threads.html#Threads">프로세스 및
116스레딩</a> 문서를 참조하십시오.</p>
117  <p>서비스를 사용하는 경우 기본적으로 애플리케이션의 기본 스레드에서
118계속 실행되므로 서비스가 집약적이거나 차단적인 작업을 수행하는 경우 여전히 서비스 내에
119새 스레드를 생성해야 한다는 점을 명심하십시오.</p>
120</div>
121</div>
122
123<p>서비스를 생성하려면 {@link android.app.Service}의 하위 클래스를 생성해야 합니다(아니면 이의
124기존 하위 클래스 중 하나). 구현에서는 서비스 수명 주기의 주요 측면을 처리하는 콜백 메서드를
125몇 가지 재정의해야 하며 서비스에 바인딩할 구성 요소에 대한 메커니즘을
126제공해야 합니다(해당되는 경우). 재정의해야 하는 가장 중요한 콜백 메서드는 다음과 같습니다.</p>
127
128<dl>
129  <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt>
130    <dd>시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소(예: 액티비티)가 서비스를
131시작하도록 요청하는 경우입니다. 이때 {@link android.content.Context#startService
132startService()}를 호출하는 방법을 씁니다. 이 메서드가 실행되면 서비스가 시작되고 배경에서 무기한으로 실행될 수
133있습니다. 이것을 구성하면 서비스의 작업이 완료되었을 때 해당 서비스를 중단하는 것은
134개발자 본인의 책임입니다. 이때 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link
135android.content.Context#stopService stopService()}를 호출하면 됩니다 (바인딩만 제공하고자 하는 경우, 이 메서드를 구현하지
136않아도 됩니다).</dd>
137  <dt>{@link android.app.Service#onBind onBind()}</dt>
138    <dd>시스템이 이 메서드를 호출하는 것은 또 다른 구성 요소가 해당 서비스에 바인딩되고자 하는 경우
139(예를 들어 RPC를 수행하기 위해)입니다. 이때 {@link android.content.Context#bindService
140bindService()}를 호출하는 방법을 씁니다. 이 메서드를 구현할 때에는 클라이언트가 서비스와 통신을 주고받기 위해 사용할
141인터페이스를 제공해야 합니다. 이때 {@link android.os.IBinder}를 반환하면 됩니다. 이 메서드는 항상
142구현해야 하지만, 바인딩을 허용하지 않고자 하면 null을 반환해야 합니다.</dd>
143  <dt>{@link android.app.Service#onCreate()}</dt>
144    <dd>시스템이 이 메서드를 호출하는 것은 서비스가 처음 생성되어 일회성 설정
145절차를 수행하는 경우입니다({@link android.app.Service#onStartCommand onStartCommand()} 또는
146{@link android.app.Service#onBind onBind()}를 호출하기 전에). 서비스가 이미 실행 중인 경우, 이 메서드는 호출되지
147않습니다.</dd>
148  <dt>{@link android.app.Service#onDestroy()}</dt>
149    <dd>시스템이 이 메서드를 호출하는 것은 해당 서비스를 더 이상 사용하지 않고 소멸시키는 경우입니다.
150서비스에 이것을 구현해야 스레드, 등록된 각종 수신기(listener, receiver) 등
151모든 리소스를 정리할 수 있습니다. 이것이 서비스가 수신하는 마지막 호출입니다.</dd>
152</dl>
153
154<p>한 구성 요소가 {@link
155android.content.Context#startService startService()}를 호출하여 서비스를 시작하면({@link
156android.app.Service#onStartCommand onStartCommand()}로의 호출을 초래함), 해당 서비스는
157알아서 {@link android.app.Service#stopSelf()}로 스스로를 중단할 때까지 또는
158또 다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 서비스를 중단시킬 때까지 실행 중인 상태로 유지됩니다.</p>
159
160<p>한 구성 요소가
161{@link android.content.Context#bindService bindService()}를 호출하여 서비스를 생성하는 경우(그리고 {@link
162android.app.Service#onStartCommand onStartCommand()}를 호출하지 <em>않은</em> 경우), 해당 서비스는
163해당 구성 요소가 바인딩되어 있는 경우에만 실행됩니다. 서비스가 모든 클라이언트로부터 바인딩 해제되면 시스템이 이를
164소멸시킵니다.</p>
165
166<p>Android 시스템이 서비스를 강제 중단시키는 것은 메모리가 부족하여 사용자가 초점을 집중하고 있는
167액티비티를 위해 시스템 리소스를 회복해야만 하는 경우로만 국한됩니다. 해당 서비스가 사용자의 주목을
168끌고 있는 액티비티에 바인딩되어 있다면 중단될 가능성이 낮고, 서비스가 <a href="#Foreground">전경에서 실행</a>된다고 선언된 경우(나중에 자세히 논함), 거의 절대 중단되지 않습니다.
169그렇지 않으면, 서비스가 시작되었고 오랫동안 실행되는 경우
170시간이 지나면서 시스템이 배경 작업 목록에서의 이 서비스의 위치를 점점 낮추고
171서비스는 중단되기 매우 쉬워집니다. 서비스가 시작되었다면 이를 시스템에 의한 재시작을 정상적으로
172처리하도록 디자인해야 합니다. 시스템이 서비스를 중단시키는 경우, 리소스를 다시 사용할 수 있게 되면
173시스템이 가능한 한 빨리 이를 다시 시작합니다(다만 이것은 개발자가 {@link
174android.app.Service#onStartCommand onStartCommand()}에서 반환하는 값에도 좌우됩니다. 이 내용은 나중에 논합니다). 시스템이 서비스를
175소멸시킬 수 있는 경우에 대한 자세한 정보는 <a href="{@docRoot}guide/components/processes-and-threads.html">프로세스 및 스레딩</a>
176문서를 참조하십시오.</p>
177
178<p>다음 섹션에서는 각 유형의 서비스를 생성하는 방법과 다른 애플리케이션 구성 요소에서
179이를 사용하는 방법을 배우게 됩니다.</p>
180
181
182
183<h3 id="Declaring">매니페스트에서 서비스 선언하기</h3>
184
185<p>액티비티(및 다른 구성 요소)와 마찬가지로, 서비스는 모두 애플리케이션의 매니페스트
186파일에서 선언해야 합니다.</p>
187
188<p>서비스를 선언하려면 <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> 요소를
189<a href="{@docRoot}guide/topics/manifest/application-element.html">{@code &lt;application&gt;}</a>
190 요소의 하위로 추가하면 됩니다. 예:</p>
191
192<pre>
193&lt;manifest ... &gt;
194  ...
195  &lt;application ... &gt;
196      &lt;service android:name=".ExampleService" /&gt;
197      ...
198  &lt;/application&gt;
199&lt;/manifest&gt;
200</pre>
201
202<p>매니페스트에서 서비스를 선언하는 데 대한 자세한 정보는 <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a>
203요소 참조를 확인하십시오.</p>
204
205<p><a href="{@docRoot}guide/topics/manifest/service-element.html">{@code &lt;service&gt;}</a> 요소에 포함시킬 수 있는 다른 속성도 있습니다.
206이를 포함시켜 서비스를 시작하는 데 필요한 권한과 서비스가 실행되어야 하는 프로세스 등의
207속성을 정의할 수 있습니다. <a href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a>
208속성이 유일한 필수 속성입니다. 이것은 서비스의 클래스 이름을 나타냅니다. 일단 애플리케이션을
209게시하고 나면 이 이름을 변경해서는 안 됩니다. 이름을 변경하면
210서비스를 시작하거나 바인딩할 명시적 인텐트에 대한 종속성으로 인해 코드를 단절시킬 위험이 있기 때문입니다(블로그 게시물의 <a href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">
211바꿀 수 없는 항목</a>을 참조하십시오).
212
213<p>앱의 보안을 보장하려면 <strong>
214{@link android.app.Service}을 시작하거나 바인딩할 때 항상 명시적 인텐트를 사용하고</strong> 서비스에 대한 인텐트 필터는 선언하지 마십시오. 어느
215서비스를 시작할지 어느 정도 모호성을 허용하는 것이 중요한 경우, 서비스에 대해
216인텐트 필터를 제공하고 구성 요소 이름을 {@link
217android.content.Intent}에서 배제할 수 있지만, 그러면 해당 인텐트에 대한 패키지를 {@link
218android.content.Intent#setPackage setPackage()}로 설정하여 대상 서비스에 대해 충분한 명확화를
219제공하도록 해야 합니다.</p>
220
221<p>이외에도 서비스를 본인의 앱에만 사용 가능하도록 보장할 수도 있습니다.
222<a href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a>
223 속성을 포함시킨 뒤 이를 {@code "false"}로 설정하면 됩니다. 이렇게 하면 다른 앱이 여러분의 서비스를 시작하지 못하도록 효과적으로 방지해주며,
224이는 명시적 인텐트를 사용하는 경우에도 문제 없이 적용됩니다.</p>
225
226
227
228
229<h2 id="CreatingStartedService">시작된 서비스 생성하기</h2>
230
231<p>시작된 서비스란 다른 구성 요소가 {@link
232android.content.Context#startService startService()}를 호출하여 시작하고, 그 결과 서비스의
233{@link android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하는 결과를 초래한 것을 말합니다.</p>
234
235<p>서비스가 시작되면 이를 시작한 구성 요소와 독립된 자신만의
236수명 주기를 가지며 해당 서비스는 배경에서 무기한으로 실행될 수 있습니다. 이는 해당 서비스를
237시작한 구성 요소가 소멸되었더라도 무관합니다. 따라서, 서비스는 작업이 완료되면
238{@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 알아서 중단되는 것이 정상이며 아니면 다른 구성 요소가
239{@link android.content.Context#stopService stopService()}를 호출하여 중단시킬 수도 있습니다.</p>
240
241<p>애플리케이션 구성 요소(예: 액티비티)가 서비스를 시작하려면 {@link
242android.content.Context#startService startService()}를 호출하고, {@link android.content.Intent}를
243전달하면 됩니다. 이것은 서비스를 나타내고 서비스가 사용할 모든 데이터를 포함합니다. 서비스는 이
244{@link android.content.Intent}를 {@link android.app.Service#onStartCommand
245onStartCommand()} 메서드에서 수신합니다.</p>
246
247<p>예를 들어 어느 액티비티가 온라인 데이터베이스에 데이터를 약간 저장해야 한다고 가정합니다. 액티비티가
248동반자 서비스를 시작하여 저장할 데이터를 이에 전달할 수 있습니다. 이때 인텐트를 {@link
249android.content.Context#startService startService()}에 전달하면 됩니다. 서비스는 이 인텐트를 {@link
250android.app.Service#onStartCommand onStartCommand()}에서 수신하고 인터넷에 연결한 다음 데이터베이스
251트랜잭션을 수행합니다. 작업을 완료하면, 해당 서비스는 알아서 스스로 중단되고
252소멸됩니다.</p>
253
254<p class="caution"><strong>주의:</strong> 서비스는 기본적으로 자신이 선언된 애플리케이션의 같은
255프로세스에서 실행되기도 하고 해당 애플리케이션의 기본 스레드에서 실행되기도 합니다. 따라서, 사용자가
256같은 애플리케이션의 액티비티와 상호 작용하는 동안 서비스가 집약적이거나 차단적인 작업을 수행하는 경우,
257해당 서비스 때문에 액티비티 성능이 느려지게 됩니다. 애플리케이션 성능에 영향을 미치는 것을 방지하려면,
258서비스 내에서 새 스레드를 시작해야 합니다.</p>
259
260<p>기존에는 시작된 서비스를 생성하기 위해 확장할 수 있는 클래스가 두 개 있었습니다.</p>
261<dl>
262  <dt>{@link android.app.Service}</dt>
263  <dd>이것이 모든 서비스의 기본 클래스입니다. 이 클래스를 확장하는 경우, 서비스의 모든 작업을 수행할
264새 스레드를 만드는 것이 중요합니다. 서비스가 기본적으로 애플리케이션의 기본 스레드를 사용하기
265때문인데, 이로 인해 애플리케이션이 실행 중인 모든 액티비티의 성능이
266느려질 수 있기 때문입니다.</dd>
267  <dt>{@link android.app.IntentService}</dt>
268  <dd>이것은 {@link android.app.Service}의 하위 클래스로, 작업자 스레드를
269사용하여 모든 시작 요청을 처리하되 한 번에 하나씩 처리합니다. 서비스가 여러 개의 요청을
270동시에 처리하지 않아도 되는 경우 이것이 최선의 옵션입니다. 해야 할 일은 {@link
271android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐으로, 이것이 각 시작 요청에 대한 인텐트를 수신하여
272개발자는 배경 작업을 수행할 수 있습니다.</dd>
273</dl>
274
275<p>다음 섹션에서는 이와 같은 클래스 중 하나를 사용하여 서비스를 구현하는 방법을
276설명합니다.</p>
277
278
279<h3 id="ExtendingIntentService">IntentService 클래스 확장하기</h3>
280
281<p>대부분의 시작된 서비스는 여러 개의 요청을 동시에 처리하지 않아도 되기 때문에
282(이는 사실 위험한 다중 스레딩 시나리오일 수 있습니다), 서비스를 구현할 때에는
283{@link android.app.IntentService} 클래스를 사용하는 것이 최선의 방안일 것입니다.</p>
284
285<p>{@link android.app.IntentService}는 다음과 같은 작업을 수행합니다.</p>
286
287<ul>
288  <li>애플리케이션의 기본 스레드와는 별도로 {@link
289android.app.Service#onStartCommand onStartCommand()}에 전달된 모든 인텐트를 실행하는 기본 작업자 스레드를
290생성합니다.</li>
291  <li>한 번에 인텐트를 하나씩 {@link
292android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 전달하는 작업 대기열을 생성하므로 다중 스레딩에 대해 염려할 필요가
293전혀 없습니다.</li>
294  <li>시작 요청이 모두 처리된 후 서비스를 중단하므로 개발자가
295{@link android.app.Service#stopSelf}를 호출할 필요가 전혀 없습니다.</li>
296  <li>{@link android.app.IntentService#onBind onBind()}의 기본 구현을 제공하여 null을
297반환하도록 합니다.</li>
298  <li>{@link android.app.IntentService#onStartCommand
299onStartCommand()}의 기본 구현을 제공하여 인텐트를 작업 대기열에 보내고, 다음으로 {@link
300android.app.IntentService#onHandleIntent onHandleIntent()} 구현에 보내도록 합니다.</li>
301</ul>
302
303<p>이 모든 것은 결론적으로 개발자가 직접 할 일은 클라이언트가 제공한 작업을 수행할 {@link
304android.app.IntentService#onHandleIntent onHandleIntent()}를 구현하는 것뿐이라는 사실로
305이어집니다. (다만, 서비스에 대해 작은 생성자를 제공해야 하기도 합니다.)</p>
306
307<p>다음은 {@link android.app.IntentService}의 구현을 예시로 나타낸 것입니다.</p>
308
309<pre>
310public class HelloIntentService extends IntentService {
311
312  /**
313   * A constructor is required, and must call the super {@link android.app.IntentService#IntentService}
314   * constructor with a name for the worker thread.
315   */
316  public HelloIntentService() {
317      super("HelloIntentService");
318  }
319
320  /**
321   * The IntentService calls this method from the default worker thread with
322   * the intent that started the service. When this method returns, IntentService
323   * stops the service, as appropriate.
324   */
325  &#64;Override
326  protected void onHandleIntent(Intent intent) {
327      // Normally we would do some work here, like download a file.
328      // For our sample, we just sleep for 5 seconds.
329      long endTime = System.currentTimeMillis() + 5*1000;
330      while (System.currentTimeMillis() &lt; endTime) {
331          synchronized (this) {
332              try {
333                  wait(endTime - System.currentTimeMillis());
334              } catch (Exception e) {
335              }
336          }
337      }
338  }
339}
340</pre>
341
342<p>필요한 것은 이게 전부입니다. 생성자 하나와 {@link
343android.app.IntentService#onHandleIntent onHandleIntent()} 구현뿐이죠.</p>
344
345<p>다른 콜백 메서드도 재정의하기로 결정하는 경우-예를 들어 {@link
346android.app.IntentService#onCreate onCreate()}, {@link
347android.app.IntentService#onStartCommand onStartCommand()} 또는 {@link
348android.app.IntentService#onDestroy onDestroy()}-슈퍼 구현을 꼭 호출해야 합니다.
349그래야 {@link android.app.IntentService}가 작업자 스레드의 수명을 적절하게 처리할 수 있습니다.</p>
350
351<p>예를 들어 {@link android.app.IntentService#onStartCommand onStartCommand()}는 반드시
352기본 구현을 반환해야 합니다(이로써 인텐트가 {@link
353android.app.IntentService#onHandleIntent onHandleIntent()}로 전달되는 것입니다).</p>
354
355<pre>
356&#64;Override
357public int onStartCommand(Intent intent, int flags, int startId) {
358    Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
359    return super.onStartCommand(intent,flags,startId);
360}
361</pre>
362
363<p>{@link android.app.IntentService#onHandleIntent onHandleIntent()} 외에 슈퍼 클래스를
364호출하지 않아도 되는 유일한 메서드는 {@link android.app.IntentService#onBind
365onBind()}입니다(다만 이를 구현하는 것은 서비스가 바인딩을 허용할 때에만 필요합니다).</p>
366
367<p>다음 섹션에서는 기본 {@link android.app.Service}
368클래스를 확장할 때 같은 종류의 서비스를 구현하는 방법을 배우게 됩니다. 이때에는 코드가 훨씬 많이 필요하지만,
369동시 시작 요청을 처리해야 하는 경우 이것이 적절할 수 있습니다.</p>
370
371
372<h3 id="ExtendingService">서비스 클래스 확장하기</h3>
373
374<p>이전 섹션에서 본 것과 같이 {@link android.app.IntentService}를 사용하면
375시작된 서비스 구현이 매우 단순해집니다. 하지만 서비스가 다중 스레딩을
376수행해야 하는 경우(작업 대기열을 통해 시작 요청을 처리하는 대신), 그때는
377{@link android.app.Service} 클래스를 확장하여 각 인텐트를 처리하게 할 수 있습니다.</p>
378
379<p>비교를 위해 다음 예시의 코드를 보겠습니다. 이는 {@link
380android.app.Service} 클래스의 구현으로, 위의 예시에서 {@link
381android.app.IntentService}를 사용하여 수행한 것과 똑같은 작업을 수행합니다. 바꿔 말하면 각 시작 요청에 대해
382작업자 스레드를 사용하여 작업을 수행하고 한 번에 요청을 하나씩만 처리한다는 뜻입니다.</p>
383
384<pre>
385public class HelloService extends Service {
386  private Looper mServiceLooper;
387  private ServiceHandler mServiceHandler;
388
389  // Handler that receives messages from the thread
390  private final class ServiceHandler extends Handler {
391      public ServiceHandler(Looper looper) {
392          super(looper);
393      }
394      &#64;Override
395      public void handleMessage(Message msg) {
396          // Normally we would do some work here, like download a file.
397          // For our sample, we just sleep for 5 seconds.
398          long endTime = System.currentTimeMillis() + 5*1000;
399          while (System.currentTimeMillis() &lt; endTime) {
400              synchronized (this) {
401                  try {
402                      wait(endTime - System.currentTimeMillis());
403                  } catch (Exception e) {
404                  }
405              }
406          }
407          // Stop the service using the startId, so that we don't stop
408          // the service in the middle of handling another job
409          stopSelf(msg.arg1);
410      }
411  }
412
413  &#64;Override
414  public void onCreate() {
415    // Start up the thread running the service.  Note that we create a
416    // separate thread because the service normally runs in the process's
417    // main thread, which we don't want to block.  We also make it
418    // background priority so CPU-intensive work will not disrupt our UI.
419    HandlerThread thread = new HandlerThread("ServiceStartArguments",
420            Process.THREAD_PRIORITY_BACKGROUND);
421    thread.start();
422
423    // Get the HandlerThread's Looper and use it for our Handler
424    mServiceLooper = thread.getLooper();
425    mServiceHandler = new ServiceHandler(mServiceLooper);
426  }
427
428  &#64;Override
429  public int onStartCommand(Intent intent, int flags, int startId) {
430      Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
431
432      // For each start request, send a message to start a job and deliver the
433      // start ID so we know which request we're stopping when we finish the job
434      Message msg = mServiceHandler.obtainMessage();
435      msg.arg1 = startId;
436      mServiceHandler.sendMessage(msg);
437
438      // If we get killed, after returning from here, restart
439      return START_STICKY;
440  }
441
442  &#64;Override
443  public IBinder onBind(Intent intent) {
444      // We don't provide binding, so return null
445      return null;
446  }
447
448  &#64;Override
449  public void onDestroy() {
450    Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
451  }
452}
453</pre>
454
455<p>보시다시피 {@link android.app.IntentService}를 사용할 때보다 훨씬 손이 많이 갑니다.</p>
456
457<p>그러나, 각 호출을 {@link android.app.Service#onStartCommand
458onStartCommand()}로 직접 처리할 수 있기 때문에 여러 개의 요청을 동시에 수행할 수 있습니다. 이 예시는 그것을
459보여주는 것은 아니지만, 그런 작업을 원하는 경우 각 요청에 대해 새 스레드를
460하나씩 생성한 다음 곧바로 실행하면 됩니다(이전 요청이 끝날 때까지 기다리는 대신).</p>
461
462<p>{@link android.app.Service#onStartCommand onStartCommand()} 메서드가 반드시
463정수를 반환해야 한다는 사실을 유의하십시오. 정수는 시스템이 서비스를 중단시킨 경우 시스템이 해당 서비스를
464계속하는 방법에 대해 설명하는 값입니다(위에서 논한 바와 같이 {@link
465android.app.IntentService}의 기본 구현이 이것을 개발자 대신 처리해줍니다. 개발자가 이를 수정할 수도 있습니다).
466{@link android.app.Service#onStartCommand onStartCommand()}로부터의 반환 값은 반드시
467다음 상수 중 하나여야 합니다.</p>
468
469<dl>
470  <dt>{@link android.app.Service#START_NOT_STICKY}</dt>
471    <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand
472onStartCommand()} 반환 후에 중단시키면 서비스를 재생성하면 <em>안 됩니다.</em> 다만 전달할
473보류 인텐트가 있는 경우는 예외입니다. 이것은 서비스가 불필요하게 실행되는 일을 피할 수 있는 가장 안전한 옵션이며,
474애플리케이션이 완료되지 않은 모든 작업을 단순히 재시작할 수 있을 때 좋습니다.</dd>
475  <dt>{@link android.app.Service#START_STICKY}</dt>
476    <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand
477onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 {@link
478android.app.Service#onStartCommand onStartCommand()}를 호출하되 마지막 인텐트를 다시 전달하지는 <em>마십시오.</em>
479그 대신, 시스템이 null 인텐트로 {@link android.app.Service#onStartCommand onStartCommand()}를
480호출합니다. 다만 서비스를 시작할 보류 인텐트가 있는 경우만은 예외이며, 이럴 때에는
481그러한 인텐트를 전달합니다. 이것은 명령을 실행하지는 않지만 무기한으로 실행 중이며 작업을 기다리고 있는
482미디어 플레이어(또는 그와 비슷한 서비스)에 적합합니다.</dd>
483  <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt>
484    <dd>시스템이 서비스를 {@link android.app.Service#onStartCommand
485onStartCommand()} 반환 후에 중단시키는 경우, 서비스를 재생성하고 서비스에 전달된 마지막 인텐트로 {@link
486android.app.Service#onStartCommand onStartCommand()}를
487호출하십시오. 모든 보류 인텐트가 차례로 전달됩니다. 이것은 즉시 재개되어야 하는 작업을
488능동적으로 수행 중인 서비스(예를 들어 파일 다운로드 등)에 적합합니다.</dd>
489</dl>
490<p>이러한 반환 값에 대한 자세한 내용은 각 상수에 대해 링크로 연결된 참조 문서를
491확인하십시오.</p>
492
493
494
495<h3 id="StartingAService">서비스 시작</h3>
496
497<p>액티비티나 다른 구성 요소에서 서비스를 시작하려면
498{@link android.content.Intent}를(시작할 서비스를 나타냄) {@link
499android.content.Context#startService startService()}에 전달하면 됩니다. Android 시스템이 서비스의 {@link
500android.app.Service#onStartCommand onStartCommand()} 메서드를 호출하여 여기에 {@link
501android.content.Intent}를 전달합니다. ({@link android.app.Service#onStartCommand
502onStartCommand()}를 직접 호출하면 절대로 안 됩니다.)</p>
503
504<p>예를 들어 이전 섹션의 예시 서비스({@code
505HelloService})를 액티비티가 시작하려면 {@link android.content.Context#startService
506startService()}로 명시적 인텐트를 사용하면 됩니다.</p>
507
508<pre>
509Intent intent = new Intent(this, HelloService.class);
510startService(intent);
511</pre>
512
513<p>{@link android.content.Context#startService startService()} 메서드가 즉시 반환되며
514Android 시스템이 서비스의 {@link android.app.Service#onStartCommand
515onStartCommand()} 메서드를 호출합니다. 서비스가 이미 실행 중이지 않은 경우, 시스템은 우선 {@link
516android.app.Service#onCreate onCreate()}를 호출하고, 다음으로 {@link android.app.Service#onStartCommand
517onStartCommand()}를 호출합니다.</p>
518
519<p>서비스가 바인딩도 제공하지 않는 경우, {@link
520android.content.Context#startService startService()}와 함께 전달된 인텐트가 애플리케이션 구성 요소와 서비스 사이의
521유일한 통신 방법입니다. 그러나 서비스가 결과를 돌려보내기를 원하는 경우, 서비스를 시작한
522클라이언트가 브로드캐스트를 위해 {@link android.app.PendingIntent}를
523만들 수 있고({@link android.app.PendingIntent#getBroadcast getBroadcast()} 사용) 이를 서비스를 시작한
524{@link android.content.Intent} 내의 서비스에 전달할 수 있습니다. 그러면 서비스가
525이 브로드캐스트를 사용하여 결과를 전달할 수 있게 됩니다.</p>
526
527<p>서비스를 시작하기 위한 여러 개의 요청은 서비스의
528{@link android.app.Service#onStartCommand onStartCommand()}로의 상응하는 여러 개의 호출이라는 결과를 낳습니다. 하지만, 서비스를 중단하려면
529이를 중단하라는 요청 하나({@link android.app.Service#stopSelf stopSelf()} 또는 {@link
530android.content.Context#stopService stopService()} 사용)만 있으면 됩니다.</p>
531
532
533<h3 id="Stopping">서비스 중단</h3>
534
535<p>시작된 서비스는 자신만의 수명 주기를 직접 관리해야 합니다. 다시 말해, 시스템이
536서비스를 중단하거나 소멸시키지 않는다는 뜻입니다. 다만 시스템 메모리를 회복해야 하고 서비스가
537{@link android.app.Service#onStartCommand onStartCommand()} 반환 후에도 계속 실행되는 경우는 예외입니다. 따라서,
538서비스는 {@link android.app.Service#stopSelf stopSelf()}를 호출하여 스스로 중단시켜야 하고, 아니면
539다른 구성 요소가 {@link android.content.Context#stopService stopService()}를 호출하여 이를 중단시킬 수 있습니다.</p>
540
541<p>일단 {@link android.app.Service#stopSelf stopSelf()} 또는 {@link
542android.content.Context#stopService stopService()}로 중단하기를 요청하고 나면 시스템이 서비스를 가능한 한 빨리
543소멸시킵니다.</p>
544
545<p>그러나, 서비스가 {@link
546android.app.Service#onStartCommand onStartCommand()}로의 요청을 동시에 여러 개 처리하기를 바라는 경우라면 시작 요청 처리를 완료한 뒤에도
547서비스를 중단하면 안 됩니다. 그 이후 새 시작 요청을 받았을 수 있기
548때문입니다(첫 요청 종료 시에 중단하면 두 번째 요청을 종료시킵니다). 이 문제를
549피하려면, {@link android.app.Service#stopSelf(int)}를 사용하여 서비스를
550중단시키라는 개발자의 요청이 항상 최신 시작 요청에 기반하도록 해야 합니다. 다시 말해, {@link
551android.app.Service#stopSelf(int)}를 호출할 때면 시작 요청의 ID({@link android.app.Service#onStartCommand onStartCommand()}에 전달된
552<code>startId</code>)를 전달하게 됩니다. 여기에 중단 요청이
553부합됩니다. 그런 다음 개발자가 {@link
554android.app.Service#stopSelf(int)}를 호출할 수 있기 전에 서비스가 새 시작 요청을 받은 경우, ID가 일치하지 않게 되고 서비스는 중단되지 않습니다.</p>
555
556<p class="caution"><strong>주의:</strong> 서비스가 작업을 완료한 다음 애플리케이션이
557소속 서비스를 중단할 수 있어야 한다는 점이 중요합니다. 그래야 시스템 리소스 낭비를 피하고 배터리 전력 소모를 줄일 수 있습니다. 필요한 경우
558다른 구성 요소도 서비스를 중단시킬 수 있습니다. {@link
559android.content.Context#stopService stopService()}를 호출하면 됩니다. 서비스에 대해 바인딩을 활성화하더라도,
560서비스가 {@link
561android.app.Service#onStartCommand onStartCommand()}로의 호출을 한 번이라도 받았으면 항상 서비스를 직접 중단시켜야 합니다.</p>
562
563<p>서비스의 수명 주기에 대한 자세한 정보는 아래에 있는 <a href="#Lifecycle">서비스 수명 주기 관리</a>에 관한 섹션을 참고하세요.</p>
564
565
566
567<h2 id="CreatingBoundService">바인딩된 서비스 생성</h2>
568
569<p>바인딩된 서비스는 애플리케이션 구성 요소가 자신에게 바인딩될 수 있도록 허용하는 서비스로, 이때 {@link
570android.content.Context#bindService bindService()}를 호출하여 오래 지속되는 연결을 생성합니다
571(또한 보통은 구성 요소가 {@link
572android.content.Context#startService startService()}를 호출하여 서비스를 <em>시작</em>하는 것을 허용하지 않습니다).</p>
573
574<p>액티비티와 애플리케이션의 다른 구성 요소에서 서비스와 상호 작용하기를 원하는 경우
575바인딩된 서비스를 생성해야 합니다. 아니면 애플리케이션의 기능 몇 가지를 프로세스 간 통신(IPC)을 통해
576다른 애플리케이션에 노출하고자 하는 경우에도 좋습니다.</p>
577
578<p>바인딩된 서비스를 생성하려면 {@link
579android.app.Service#onBind onBind()} 콜백 메서드를 구현하여 서비스와의 통신을 위한 인터페이스를 정의하는
580{@link android.os.IBinder}를 반환하도록 해야 합니다. 그러면 다른 애플리케이션 구성 요소가
581{@link android.content.Context#bindService bindService()}를 호출하여 해당 인터페이스를 검색하고, 서비스에 있는 메서드를
582호출하기 시작할 수 있습니다. 서비스는 자신에게 바인딩된 애플리케이션 구성 요소에게 도움이 되기 위해서만
583존재하는 것이므로, 서비스에 바인딩된 구성 요소가 없으면 시스템이 이를 소멸시킵니다(바인딩된 서비스는 시작된 서비스처럼
584{@link android.app.Service#onStartCommand onStartCommand()}를 통해
585중단시키지 <em>않아도</em> 됩니다).</p>
586
587<p>바인딩된 서비스를 생성하려면 가장 먼저 해야 할 일은 클라이언트가 서비스와
588통신할 수 있는 방법을 나타내는 인터페이스를 정의하는 것입니다. 서비스와 클라이언트 사이에서 쓰이는 이 인터페이스는
589반드시 {@link android.os.IBinder}의 구현이어야 하며 이를
590서비스가 {@link android.app.Service#onBind
591onBind()} 콜백 메서드에서 반환해야 합니다. 클라이언트가 {@link android.os.IBinder}를 수신하면 해당 인터페이스를 통해 서비스와
592상호 작용을 시작할 수 있습니다.</p>
593
594<p>여러 클라이언트가 서비스에 한꺼번에 바인딩될 수 있습니다. 클라이언트가 서비스와의 상호 작용을 완료하면 이는
595{@link android.content.Context#unbindService unbindService()}를 호출하여 바인딩을 해제합니다. 서비스에
596바인딩된 클라이언트가 하나도 없으면 시스템이 해당 서비스를 소멸시킵니다.</p>
597
598<p>바인딩된 서비스를 구현하는 데에는 여러 가지 방법이 있으며 그러한 구현은 시작된 서비스보다
599훨씬 복잡합니다. 따라서 바인딩된 서비스 논의는
600<a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a>에 관한 별도의 문서에서 다룹니다.</p>
601
602
603
604<h2 id="Notifications">사용자에게 알림 전송</h2>
605
606<p>서비스는 일단 실행되고 나면 사용자에게 <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">알림 메시지</a> 또는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄 알림</a> 등을 사용해 이벤트를 알릴 수 있습니다.</p>
607
608<p>알림 메시지란 현재 창의 표면에 잠시 나타났다가 사라지는 메시지이고,
609상태 표시줄 알림은 상태 표시줄에 메시지가 담긴 아이콘을 제공하여 사용자가 이를 선택하여
610조치를 취할 수 있게 하는 것입니다(예: 액티비티 시작).</p>
611
612<p>보통, 일종의 배경 작업이 완료되었고
613(예: 파일 다운로드 완료) 이제 사용자가 그에 대해 조치를 취할 수 있는 경우 상태 표시줄 알림이
614최선의 기법입니다. 사용자가 확장된 보기에서 알림을 선택하면,
615해당 알림이 액티비티를 시작할 수 있습니다(예: 다운로드한 파일 보기).</p>
616
617<p>자세한 정보는 <a href="{@docRoot}guide/topics/ui/notifiers/toasts.html">알림 메시지</a> 또는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄 알림</a>
618개발자 가이드를 참조하십시오.</p>
619
620
621
622<h2 id="Foreground">전경에서 서비스 실행하기</h2>
623
624<p>전경 서비스는 사용자가 능동적으로 인식하고 있으므로 메모리 부족 시에도
625시스템이 중단할 후보로 고려되지 않는 서비스를 말합니다. 전경
626서비스는 상태 표시줄에 대한 알림을 제공해야 합니다. 이것은
627"진행 중" 제목 아래에 배치되며, 이는 곧 해당 알림은 서비스가 중단되었거나
628전경에서 제거되지 않은 이상 무시할 수 없다는 뜻입니다.</p>
629
630<p>예를 들어 서비스에서 음악을 재생하는 음악 플레이어는 전경에서
631실행되도록 설정해야 합니다. 사용자가 이것의 작동을 분명히 인식하고 있기
632때문입니다. 상태 표시줄에 있는 알림은 현재 노래를 나타내고
633사용자로 하여금 음악 플레이어와 상호 작용할 액티비티를 시작하게 해줄 수도 있습니다.</p>
634
635<p>서비스가 전경에서 실행되도록 요청하려면 {@link
636android.app.Service#startForeground startForeground()}를 호출하면 됩니다. 이 메서드는 두 개의 매개변수를 취합니다.
637그 중 하나는 해당 알림을 고유하게 식별하는 정수이고 다른 하나는 상태 표시줄에 해당되는 {@link
638android.app.Notification}입니다. 예:</p>
639
640<pre>
641Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text),
642        System.currentTimeMillis());
643Intent notificationIntent = new Intent(this, ExampleActivity.class);
644PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
645notification.setLatestEventInfo(this, getText(R.string.notification_title),
646        getText(R.string.notification_message), pendingIntent);
647startForeground(ONGOING_NOTIFICATION_ID, notification);
648</pre>
649
650<p class="caution"><strong>주의:</strong> {@link
651android.app.Service#startForeground startForeground()}에 부여하는 정수 ID가 0이면 안 됩니다.</p>
652
653
654<p>서비스를 전경에서 제거하려면 {@link
655android.app.Service#stopForeground stopForeground()}를 호출하면 됩니다. 이 메서드는 부울 값을 취하며, 이것이
656상태 표시줄 알림도 제거할지 여부를 나타냅니다. 이 메서드는 서비스를 중단시키지 <em>않습니다</em>.
657 그러나, 서비스가 전경에서 실행 중인 동안 서비스를 중단시키면
658알림도 마찬가지로 제거됩니다.</p>
659
660<p>알림에 대한 자세한 정보는 <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">상태 표시줄
661알림 생성</a>을 참조하십시오.</p>
662
663
664
665<h2 id="Lifecycle">서비스 수명 주기 관리</h2>
666
667<p>서비스의 수명 주기는 액티비티의 수명 주기보다 훨씬 간단합니다. 하지만, 서비스를 생성하고
668소멸시키는 방법에 특히 주의를 기울여야 한다는 면에서 중요도는 이쪽이 더 높습니다. 서비스는 사용자가 모르는 채로
669배경에서 실행될 수 있기 때문입니다.</p>
670
671<p>서비스 수명 주기&mdash;생성되었을 때부터 소멸될 때까지&mdash;는 두 가지 서로 다른 경로를
672따를 수 있습니다.</p>
673
674<ul>
675<li>시작된 서비스
676  <p>서비스는 또 다른 구성 요소가 {@link
677android.content.Context#startService startService()}를 호출하면 생성됩니다. 그러면 서비스가 무기한으로 실행될 수 있으며
678스스로 알아서 중단되어야 합니다. 이때 {@link
679android.app.Service#stopSelf() stopSelf()}를 호출하는 방법을 씁니다. 또 다른 구성 요소도 서비스를 중단시킬 수
680있습니다. {@link android.content.Context#stopService
681stopService()}를 호출하면 됩니다. 서비스가 중단되면 시스템이 이를 소멸시킵니다.</p></li>
682
683<li>바인딩된 서비스
684  <p>서비스는 또 다른 구성 요소(클라이언트)가 {@link
685android.content.Context#bindService bindService()}를 호출하면 생성됩니다. 그러면 클라이언트가
686{@link android.os.IBinder} 인터페이스를 통해 서비스와 통신을 주고받을 수 있습니다. 클라이언트가 연결을 종료하려면
687{@link android.content.Context#unbindService unbindService()}를 호출하면 됩니다. 여러 클라이언트가 같은 서비스에
688바인딩될 수 있으며, 이 모두가 바인딩을 해제하면 시스템이 해당 서비스를 소멸시킵니다 (서비스가 스스로를 중단시키지
689<em>않아도</em> 됩니다).</p></li>
690</ul>
691
692<p>이와 같은 두 가지 경로는 완전히 별개의 것은 아닙니다. 다시 말해, 이미
693{@link android.content.Context#startService startService()}로 시작된 서비스에 바인딩할 수도 있다는 뜻입니다. 예를
694들어, 배경 음악 서비스를 시작하려면 {@link android.content.Context#startService
695startService()}를 호출하되 재생할 음악을 식별하는 {@link android.content.Intent}를 사용하면 됩니다. 나중에,
696아마도 사용자가 플레이어에 좀 더 많은 통제권을 발휘하고자 하거나
697현재 노래에 대한 정보를 얻고자 할 때, 액티비티가 서비스에 바인딩될 수 있습니다. {@link
698android.content.Context#bindService bindService()}를 사용하면 됩니다. 이런 경우에는 {@link
699android.content.Context#stopService stopService()} 또는 {@link android.app.Service#stopSelf
700stopSelf()}도 클라이언트가 모두 바인딩 해제될 때까지 실제로 서비스를 중단시키지 않습니다. </p>
701
702
703<h3 id="LifecycleCallbacks">수명 주기 콜백 구현하기</h3>
704
705<p>액티비티와 마찬가지로 서비스에도 수명 주기 콜백 메서드가 있어 이를 구현하면 서비스의
706상태 변경 내용을 모니터링할 수 있고 적절한 시기에 작업을 수행할 수 있습니다. 다음의 골격
707서비스는 각 수명 주기 메서드를 설명한 것입니다.</p>
708
709<pre>
710public class ExampleService extends Service {
711    int mStartMode;       // indicates how to behave if the service is killed
712    IBinder mBinder;      // interface for clients that bind
713    boolean mAllowRebind; // indicates whether onRebind should be used
714
715    &#64;Override
716    public void {@link android.app.Service#onCreate onCreate}() {
717        // The service is being created
718    }
719    &#64;Override
720    public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) {
721        // The service is starting, due to a call to {@link android.content.Context#startService startService()}
722        return <em>mStartMode</em>;
723    }
724    &#64;Override
725    public IBinder {@link android.app.Service#onBind onBind}(Intent intent) {
726        // A client is binding to the service with {@link android.content.Context#bindService bindService()}
727        return <em>mBinder</em>;
728    }
729    &#64;Override
730    public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) {
731        // All clients have unbound with {@link android.content.Context#unbindService unbindService()}
732        return <em>mAllowRebind</em>;
733    }
734    &#64;Override
735    public void {@link android.app.Service#onRebind onRebind}(Intent intent) {
736        // A client is binding to the service with {@link android.content.Context#bindService bindService()},
737        // after onUnbind() has already been called
738    }
739    &#64;Override
740    public void {@link android.app.Service#onDestroy onDestroy}() {
741        // The service is no longer used and is being destroyed
742    }
743}
744</pre>
745
746<p class="note"><strong>참고:</strong> 액티비티 수명 주기 콜백 메서드와는 달리 이와 같은 콜백 메서드를 구현하는 데에는
747슈퍼클래스 구현을 호출하지 <em>않아도</em> 됩니다.</p>
748
749<img src="{@docRoot}images/service_lifecycle.png" alt="" />
750<p class="img-caption"><strong>그림 2.</strong> 서비스 수명 주기입니다. 왼쪽의 다이어그램은
751서비스가 {@link android.content.Context#startService
752startService()}로 생성된 경우의 수명 주기를 나타내며 오른쪽의 다이어그램은 서비스가
753{@link android.content.Context#bindService bindService()}로 생성된 경우의 수명 주기를 나타낸 것입니다.</p>
754
755<p>이와 같은 메서드를 구현함으로써, 서비스 수명 주기의 두 가지 중첩된 루프를 모니터링할 수 있습니다. </p>
756
757<ul>
758<li>서비스의 <strong>수명 주기 전체</strong>는 {@link
759android.app.Service#onCreate onCreate()}가 호출된 시점과 {@link
760android.app.Service#onDestroy}가 반환된 시점 사이에 일어납니다. 액티비티와 마찬가지로 서비스는 자신의 초기 설정을
761{@link android.app.Service#onCreate onCreate()}에서 수행하며 남은 리소스를 모두 {@link
762android.app.Service#onDestroy onDestroy()}에 릴리스합니다.  예를 들어
763음악 재생 서비스의 경우 음악이 재생될 스레드를 {@link
764android.app.Service#onCreate onCreate()}로 생성하고, 그럼 다음 해당 스레드를 중단할 때에는 {@link
765android.app.Service#onDestroy onDestroy()}에서 할 수도 있습니다.
766
767<p>{@link android.app.Service#onCreate onCreate()}와 {@link android.app.Service#onDestroy
768onDestroy()} 메서드는 모든 서비스에 대해 호출됩니다. 이는 서비스가
769{@link android.content.Context#startService startService()}로 생성되었든 {@link
770android.content.Context#bindService bindService()}로 생성되었든 관계 없이 적용됩니다.</p></li>
771
772<li>서비스의 <strong>활성 수명 주기</strong>는 {@link
773android.app.Service#onStartCommand onStartCommand()} 또는 {@link android.app.Service#onBind onBind()}로의 호출과 함께 시작됩니다.
774각 메서드에 {@link
775android.content.Intent}가 전달되는데 이것은 각각 {@link android.content.Context#startService
776startService()} 또는 {@link android.content.Context#bindService bindService()} 중 하나에 전달된 것입니다.
777<p>서비스가 시작되면 수명 주기 전체가 종료되는 것과 동시에 활성 수명 주기도 종료됩니다
778(서비스는 {@link android.app.Service#onStartCommand
779onStartCommand()}가 반환된 뒤에도 여전히 활성 상태입니다). 서비스가 바인딩된 경우, 활성 수명 주기는 {@link
780android.app.Service#onUnbind onUnbind()}가 반환되면 종료됩니다.</p>
781</li>
782</ul>
783
784<p class="note"><strong>참고:</strong> 시작된 서비스를 중단하려면
785{@link android.app.Service#stopSelf stopSelf()} 또는 {@link
786android.content.Context#stopService stopService()}를 호출하면 되지만, 서비스에 대한 상응하는 콜백은
787없습니다(즉 {@code onStop()} 콜백이 없습니다). 그러므로, 서비스가 클라이언트에 바인딩되어 있지 않은 한
788시스템은 서비스가 중단되면 이를 소멸시킵니다. 수신되는 콜백은 {@link
789android.app.Service#onDestroy onDestroy()}가 유일합니다.</p>
790
791<p>그림 2는 서비스에 대한 일반적인 콜백 메서드를 나타낸 것입니다. 이 그림에서는
792{@link android.content.Context#startService startService()}로 생성된 서비스와
793{@link android.content.Context#bindService bindService()}로 생성된 서비스를
794구분하고 있지만, 어떤 식으로 시작되었든 모든 서비스는 클라이언트가 자신에 바인딩되도록 허용할 수 있다는 점을 명심하십시오.
795말하자면, {@link android.app.Service#onStartCommand
796onStartCommand()}로 처음 시작된 서비스(클라이언트가 {@link android.content.Context#startService startService()}를 호출해서)라고 해도
797여전히 {@link android.app.Service#onBind onBind()}로의 호출을 받을 수 있습니다(클라이언트가
798{@link android.content.Context#bindService bindService()}를 호출하는 경우).</p>
799
800<p>바인딩을 제공하는 서비스 생성에 대한 자세한 내용은 <a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a> 문서를 참조하십시오. 이 안에는 {@link android.app.Service#onRebind onRebind()}
801콜백 메서드에 대한 자세한 정보가 <a href="{@docRoot}guide/components/bound-services.html#Lifecycle">바인딩된 서비스의
802수명 주기 관리</a>에 관한 섹션에
803담겨 있습니다.</p>
804
805
806<!--
807<h2>Beginner's Path</h2>
808
809<p>To learn how to query data from the system or other applications (such as contacts or media
810stored on the device), continue with the <b><a
811href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b>
812document.</p>
813-->
814