| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 1 | page.title=Services |
| 2 | @jd:body |
| 3 | |
| 4 | <div id="qv-wrapper"> |
| 5 | <ol id="qv"> |
| 6 | <h2>Quickview</h2> |
| 7 | <ul> |
| 8 | <li>A service can run in the background to perform work even while the user is in a different |
| 9 | application</li> |
| 10 | <li>A service can allow other components to bind to it, in order to interact with it and |
| 11 | perform interprocess communication</li> |
| 12 | <li>A service runs in the main thread of the application that hosts it, by default</li> |
| 13 | </ul> |
| 14 | <h2>In this document</h2> |
| 15 | <ol> |
| 16 | <li><a href="#Basics">The Basics</a></li> |
| 17 | <ol> |
| 18 | <li><a href="#Declaring">Declaring a service in the manifest</a></li> |
| 19 | </ol> |
| 20 | <li><a href="#CreatingAService">Creating a Started Service</a> |
| 21 | <ol> |
| 22 | <li><a href="#ExtendingIntentService">Extending the IntentService class</a></li> |
| 23 | <li><a href="#ExtendingService">Extending the Service class</a></li> |
| 24 | <li><a href="#StartingAService">Starting a service</a></li> |
| 25 | <li><a href="#Stopping">Stopping a service</a></li> |
| 26 | </ol> |
| 27 | </li> |
| 28 | <li><a href="#CreatingBoundService">Creating a Bound Service</a></li> |
| 29 | <li><a href="#Notifications">Sending Notifications to the User</a></li> |
| 30 | <li><a href="#Foreground">Running a Service in the Foreground</a></li> |
| 31 | <li><a href="#Lifecycle">Managing the Lifecycle of a Service</a> |
| 32 | <ol> |
| 33 | <li><a href="#LifecycleCallbacks">Implementing the lifecycle callbacks</a></li> |
| 34 | </ol> |
| 35 | </li> |
| 36 | </ol> |
| 37 | |
| 38 | <h2>Key classes</h2> |
| 39 | <ol> |
| 40 | <li>{@link android.app.Service}</li> |
| 41 | <li>{@link android.app.IntentService}</li> |
| 42 | </ol> |
| 43 | |
| 44 | <h2>Samples</h2> |
| 45 | <ol> |
| 46 | <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/ServiceStartArguments.html">{@code |
| 47 | ServiceStartArguments}</a></li> |
| 48 | <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code |
| 49 | LocalService}</a></li> |
| 50 | </ol> |
| 51 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 52 | <h2>See also</h2> |
| 53 | <ol> |
| 54 | <li><a href="{@docRoot}guide/components/bound-services.html">Bound Services</a></li> |
| 55 | </ol> |
| 56 | |
| 57 | </div> |
| 58 | |
| 59 | |
| 60 | <p>A {@link android.app.Service} is an application component that can perform |
| 61 | long-running operations in the background and does not provide a user interface. Another |
| 62 | application component can start a service and it will continue to run in the background even if the |
| 63 | user switches to another application. Additionally, a component can bind to a service to |
| 64 | interact with it and even perform interprocess communication (IPC). For example, a service might |
| 65 | handle network transactions, play music, perform file I/O, or interact with a content provider, all |
| 66 | from the background.</p> |
| 67 | |
| 68 | <p>A service can essentially take two forms:</p> |
| 69 | |
| 70 | <dl> |
| 71 | <dt>Started</dt> |
| 72 | <dd>A service is "started" when an application component (such as an activity) starts it by |
| 73 | calling {@link android.content.Context#startService startService()}. Once started, a service |
| 74 | can run in the background indefinitely, even if the component that started it is destroyed. Usually, |
| 75 | a started service performs a single operation and does not return a result to the caller. |
| 76 | For example, it might download or upload a file over the network. When the operation is done, the |
| 77 | service should stop itself.</dd> |
| 78 | <dt>Bound</dt> |
| 79 | <dd>A service is "bound" when an application component binds to it by calling {@link |
| 80 | android.content.Context#bindService bindService()}. A bound service offers a client-server |
| 81 | interface that allows components to interact with the service, send requests, get results, and even |
| 82 | do so across processes with interprocess communication (IPC). A bound service runs only as long as |
| 83 | another application component is bound to it. Multiple components can bind to the service at once, |
| 84 | but when all of them unbind, the service is destroyed.</dd> |
| 85 | </dl> |
| 86 | |
| 87 | <p>Although this documentation generally discusses these two types of services separately, your |
| 88 | service can work both ways—it can be started (to run indefinitely) and also allow binding. |
| 89 | It's simply a matter of whether you implement a couple callback methods: {@link |
| 90 | android.app.Service#onStartCommand onStartCommand()} to allow components to start it and {@link |
| 91 | android.app.Service#onBind onBind()} to allow binding.</p> |
| 92 | |
| 93 | <p>Regardless of whether your application is started, bound, or both, any application component |
| 94 | can use the service (even from a separate application), in the same way that any component can use |
| 95 | an activity—by starting it with an {@link android.content.Intent}. However, you can declare |
| 96 | the service as private, in the manifest file, and block access from other applications. This is |
| 97 | discussed more in the section about <a href="#Declaring">Declaring the service in the |
| 98 | manifest</a>.</p> |
| 99 | |
| 100 | <p class="caution"><strong>Caution:</strong> A service runs in the |
| 101 | main thread of its hosting process—the service does <strong>not</strong> create its own thread |
| 102 | and does <strong>not</strong> run in a separate process (unless you specify otherwise). This means |
| 103 | that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 |
| 104 | playback or networking), you should create a new thread within the service to do that work. By using |
| 105 | a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the |
| 106 | application's main thread can remain dedicated to user interaction with your activities.</p> |
| 107 | |
| 108 | |
| 109 | <h2 id="Basics">The Basics</h2> |
| 110 | |
| 111 | <div class="sidebox-wrapper"> |
| 112 | <div class="sidebox"> |
| 113 | <h3>Should you use a service or a thread?</h3> |
| 114 | <p>A service is simply a component that can run in the background even when the user is not |
| 115 | interacting with your application. Thus, you should create a service only if that is what you |
| 116 | need.</p> |
| 117 | <p>If you need to perform work outside your main thread, but only while the user is interacting |
| 118 | with your application, then you should probably instead create a new thread and not a service. For |
| 119 | example, if you want to play some music, but only while your activity is running, you might create |
| 120 | a thread in {@link android.app.Activity#onCreate onCreate()}, start running it in {@link |
| 121 | android.app.Activity#onStart onStart()}, then stop it in {@link android.app.Activity#onStop |
| 122 | onStop()}. Also consider using {@link android.os.AsyncTask} or {@link android.os.HandlerThread}, |
| 123 | instead of the traditional {@link java.lang.Thread} class. See the <a |
| 124 | href="{@docRoot}guide/components/processes-and-threads.html#Threads">Processes and |
| 125 | Threading</a> document for more information about threads.</p> |
| 126 | <p>Remember that if you do use a service, it still runs in your application's main thread by |
| 127 | default, so you should still create a new thread within the service if it performs intensive or |
| 128 | blocking operations.</p> |
| 129 | </div> |
| 130 | </div> |
| 131 | |
| 132 | <p>To create a service, you must create a subclass of {@link android.app.Service} (or one |
| 133 | of its existing subclasses). In your implementation, you need to override some callback methods that |
| 134 | handle key aspects of the service lifecycle and provide a mechanism for components to bind to |
| 135 | the service, if appropriate. The most important callback methods you should override are:</p> |
| 136 | |
| 137 | <dl> |
| 138 | <dt>{@link android.app.Service#onStartCommand onStartCommand()}</dt> |
| 139 | <dd>The system calls this method when another component, such as an activity, |
| 140 | requests that the service be started, by calling {@link android.content.Context#startService |
| 141 | startService()}. Once this method executes, the service is started and can run in the |
| 142 | background indefinitely. If you implement this, it is your responsibility to stop the service when |
| 143 | its work is done, by calling {@link android.app.Service#stopSelf stopSelf()} or {@link |
| 144 | android.content.Context#stopService stopService()}. (If you only want to provide binding, you don't |
| 145 | need to implement this method.)</dd> |
| 146 | <dt>{@link android.app.Service#onBind onBind()}</dt> |
| 147 | <dd>The system calls this method when another component wants to bind with the |
| 148 | service (such as to perform RPC), by calling {@link android.content.Context#bindService |
| 149 | bindService()}. In your implementation of this method, you must provide an interface that clients |
| 150 | use to communicate with the service, by returning an {@link android.os.IBinder}. You must always |
| 151 | implement this method, but if you don't want to allow binding, then you should return null.</dd> |
| 152 | <dt>{@link android.app.Service#onCreate()}</dt> |
| 153 | <dd>The system calls this method when the service is first created, to perform one-time setup |
| 154 | procedures (before it calls either {@link android.app.Service#onStartCommand onStartCommand()} or |
| 155 | {@link android.app.Service#onBind onBind()}). If the service is already running, this method is not |
| 156 | called.</dd> |
| 157 | <dt>{@link android.app.Service#onDestroy()}</dt> |
| 158 | <dd>The system calls this method when the service is no longer used and is being destroyed. |
| 159 | Your service should implement this to clean up any resources such as threads, registered |
| 160 | listeners, receivers, etc. This is the last call the service receives.</dd> |
| 161 | </dl> |
| 162 | |
| 163 | <p>If a component starts the service by calling {@link |
| 164 | android.content.Context#startService startService()} (which results in a call to {@link |
| 165 | android.app.Service#onStartCommand onStartCommand()}), then the service |
| 166 | remains running until it stops itself with {@link android.app.Service#stopSelf()} or another |
| 167 | component stops it by calling {@link android.content.Context#stopService stopService()}.</p> |
| 168 | |
| 169 | <p>If a component calls |
| 170 | {@link android.content.Context#bindService bindService()} to create the service (and {@link |
| 171 | android.app.Service#onStartCommand onStartCommand()} is <em>not</em> called), then the service runs |
| 172 | only as long as the component is bound to it. Once the service is unbound from all clients, the |
| 173 | system destroys it.</p> |
| 174 | |
| 175 | <p>The Android system will force-stop a service only when memory is low and it must recover system |
| 176 | resources for the activity that has user focus. If the service is bound to an activity that has user |
| 177 | focus, then it's less likely to be killed, and if the service is declared to <a |
| 178 | href="#Foreground">run in the foreground</a> (discussed later), then it will almost never be killed. |
| 179 | Otherwise, if the service was started and is long-running, then the system will lower its position |
| 180 | in the list of background tasks over time and the service will become highly susceptible to |
| 181 | killing—if your service is started, then you must design it to gracefully handle restarts |
| 182 | by the system. If the system kills your service, it restarts it as soon as resources become |
| 183 | available again (though this also depends on the value you return from {@link |
| 184 | android.app.Service#onStartCommand onStartCommand()}, as discussed later). For more information |
| 185 | about when the system might destroy a service, see the <a |
| 186 | href="{@docRoot}guide/components/processes-and-threads.html">Processes and Threading</a> |
| 187 | document.</p> |
| 188 | |
| 189 | <p>In the following sections, you'll see how you can create each type of service and how to use |
| 190 | it from other application components.</p> |
| 191 | |
| 192 | |
| 193 | |
| 194 | <h3 id="Declaring">Declaring a service in the manifest</h3> |
| 195 | |
| 196 | <p>Like activities (and other components), you must declare all services in your application's |
| 197 | manifest file.</p> |
| 198 | |
| 199 | <p>To declare your service, add a <a |
| 200 | href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element |
| 201 | as a child of the <a |
| 202 | href="{@docRoot}guide/topics/manifest/application-element.html">{@code <application>}</a> |
| 203 | element. For example:</p> |
| 204 | |
| 205 | <pre> |
| 206 | <manifest ... > |
| 207 | ... |
| 208 | <application ... > |
| 209 | <service android:name=".ExampleService" /> |
| 210 | ... |
| 211 | </application> |
| 212 | </manifest> |
| 213 | </pre> |
| 214 | |
| 215 | <p>There are other attributes you can include in the <a |
| 216 | href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element to |
| 217 | define properties such as permissions required to start the service and the process in |
| 218 | which the service should run. The <a |
| 219 | href="{@docRoot}guide/topics/manifest/service-element.html#nm">{@code android:name}</a> |
| 220 | attribute is the only required attribute—it specifies the class name of the service. Once |
| 221 | you publish your application, you should not change this name, because if you do, you might break |
| 222 | some functionality where explicit intents are used to reference your service (read the blog post, <a |
| 223 | href="http://android-developers.blogspot.com/2011/06/things-that-cannot-change.html">Things |
| 224 | That Cannot Change</a>). |
| 225 | |
| 226 | <p>See the <a |
| 227 | href="{@docRoot}guide/topics/manifest/service-element.html">{@code <service>}</a> element |
| 228 | reference for more information about declaring your service in the manifest.</p> |
| 229 | |
| 230 | <p>Just like an activity, a service can define intent filters that allow other components to |
| 231 | invoke the service using implicit intents. By declaring intent filters, components |
| 232 | from any application installed on the user's device can potentially start your service if your |
| 233 | service declares an intent filter that matches the intent another application passes to {@link |
| 234 | android.content.Context#startService startService()}.</p> |
| 235 | |
| 236 | <p>If you plan on using your service only locally (other applications do not use it), then you |
| 237 | don't need to (and should not) supply any intent filters. Without any intent filters, you must |
| 238 | start the service using an intent that explicitly names the service class. More information |
| 239 | about <a href="#StartingAService">starting a service</a> is discussed below.</p> |
| 240 | |
| 241 | <p>Additionally, you can ensure that your service is private to your application only if |
| 242 | you include the <a |
| 243 | href="{@docRoot}guide/topics/manifest/service-element.html#exported">{@code android:exported}</a> |
| 244 | attribute and set it to {@code "false"}. This is effective even if your service supplies intent |
| 245 | filters.</p> |
| 246 | |
| 247 | <p>For more information about creating intent filters for your service, see the <a |
| 248 | href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a> |
| 249 | document.</p> |
| 250 | |
| 251 | |
| 252 | |
| 253 | <h2 id="CreatingStartedService">Creating a Started Service</h2> |
| 254 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 255 | <p>A started service is one that another component starts by calling {@link |
| 256 | android.content.Context#startService startService()}, resulting in a call to the service's |
| 257 | {@link android.app.Service#onStartCommand onStartCommand()} method.</p> |
| 258 | |
| 259 | <p>When a service is started, it has a lifecycle that's independent of the |
| 260 | component that started it and the service can run in the background indefinitely, even if |
| 261 | the component that started it is destroyed. As such, the service should stop itself when its job |
| 262 | is done by calling {@link android.app.Service#stopSelf stopSelf()}, or another component can stop it |
| 263 | by calling {@link android.content.Context#stopService stopService()}.</p> |
| 264 | |
| 265 | <p>An application component such as an activity can start the service by calling {@link |
| 266 | android.content.Context#startService startService()} and passing an {@link android.content.Intent} |
| 267 | that specifies the service and includes any data for the service to use. The service receives |
| 268 | this {@link android.content.Intent} in the {@link android.app.Service#onStartCommand |
| 269 | onStartCommand()} method.</p> |
| 270 | |
| 271 | <p>For instance, suppose an activity needs to save some data to an online database. The activity can |
| 272 | start a companion service and deliver it the data to save by passing an intent to {@link |
| 273 | android.content.Context#startService startService()}. The service receives the intent in {@link |
| 274 | android.app.Service#onStartCommand onStartCommand()}, connects to the Internet and performs the |
| 275 | database transaction. When the transaction is done, the service stops itself and it is |
| 276 | destroyed.</p> |
| 277 | |
| 278 | <p class="caution"><strong>Caution:</strong> A services runs in the same process as the application |
| 279 | in which it is declared and in the main thread of that application, by default. So, if your service |
| 280 | performs intensive or blocking operations while the user interacts with an activity from the same |
| 281 | application, the service will slow down activity performance. To avoid impacting application |
| 282 | performance, you should start a new thread inside the service.</p> |
| 283 | |
| 284 | <p>Traditionally, there are two classes you can extend to create a started service:</p> |
| 285 | <dl> |
| 286 | <dt>{@link android.app.Service}</dt> |
| 287 | <dd>This is the base class for all services. When you extend this class, it's important that |
| 288 | you create a new thread in which to do all the service's work, because the service uses your |
| 289 | application's main thread, by default, which could slow the performance of any activity your |
| 290 | application is running.</dd> |
| 291 | <dt>{@link android.app.IntentService}</dt> |
| 292 | <dd>This is a subclass of {@link android.app.Service} that uses a worker thread to handle all |
| 293 | start requests, one at a time. This is the best option if you don't require that your service |
| 294 | handle multiple requests simultaneously. All you need to do is implement {@link |
| 295 | android.app.IntentService#onHandleIntent onHandleIntent()}, which receives the intent for each |
| 296 | start request so you can do the background work.</dd> |
| 297 | </dl> |
| 298 | |
| 299 | <p>The following sections describe how you can implement your service using either one for these |
| 300 | classes.</p> |
| 301 | |
| 302 | |
| 303 | <h3 id="ExtendingIntentService">Extending the IntentService class</h3> |
| 304 | |
| 305 | <p>Because most started services don't need to handle multiple requests simultaneously |
| 306 | (which can actually be a dangerous multi-threading scenario), it's probably best if you |
| 307 | implement your service using the {@link android.app.IntentService} class.</p> |
| 308 | |
| 309 | <p>The {@link android.app.IntentService} does the following:</p> |
| 310 | |
| 311 | <ul> |
| 312 | <li>Creates a default worker thread that executes all intents delivered to {@link |
| 313 | android.app.Service#onStartCommand onStartCommand()} separate from your application's main |
| 314 | thread.</li> |
| 315 | <li>Creates a work queue that passes one intent at a time to your {@link |
| 316 | android.app.IntentService#onHandleIntent onHandleIntent()} implementation, so you never have to |
| 317 | worry about multi-threading.</li> |
| 318 | <li>Stops the service after all start requests have been handled, so you never have to call |
| 319 | {@link android.app.Service#stopSelf}.</li> |
| 320 | <li>Provides default implementation of {@link android.app.IntentService#onBind onBind()} that |
| 321 | returns null.</li> |
| 322 | <li>Provides a default implementation of {@link android.app.IntentService#onStartCommand |
| 323 | onStartCommand()} that sends the intent to the work queue and then to your {@link |
| 324 | android.app.IntentService#onHandleIntent onHandleIntent()} implementation.</li> |
| 325 | </ul> |
| 326 | |
| 327 | <p>All this adds up to the fact that all you need to do is implement {@link |
| 328 | android.app.IntentService#onHandleIntent onHandleIntent()} to do the work provided by the |
| 329 | client. (Though, you also need to provide a small constructor for the service.)</p> |
| 330 | |
| 331 | <p>Here's an example implementation of {@link android.app.IntentService}:</p> |
| 332 | |
| 333 | <pre> |
| 334 | public class HelloIntentService extends IntentService { |
| 335 | |
| 336 | /** |
| 337 | * A constructor is required, and must call the super {@link android.app.IntentService#IntentService} |
| 338 | * constructor with a name for the worker thread. |
| 339 | */ |
| 340 | public HelloIntentService() { |
| 341 | super("HelloIntentService"); |
| 342 | } |
| 343 | |
| 344 | /** |
| 345 | * The IntentService calls this method from the default worker thread with |
| 346 | * the intent that started the service. When this method returns, IntentService |
| 347 | * stops the service, as appropriate. |
| 348 | */ |
| 349 | @Override |
| 350 | protected void onHandleIntent(Intent intent) { |
| 351 | // Normally we would do some work here, like download a file. |
| 352 | // For our sample, we just sleep for 5 seconds. |
| 353 | long endTime = System.currentTimeMillis() + 5*1000; |
| 354 | while (System.currentTimeMillis() < endTime) { |
| 355 | synchronized (this) { |
| 356 | try { |
| 357 | wait(endTime - System.currentTimeMillis()); |
| 358 | } catch (Exception e) { |
| 359 | } |
| 360 | } |
| 361 | } |
| 362 | } |
| 363 | } |
| 364 | </pre> |
| 365 | |
| 366 | <p>That's all you need: a constructor and an implementation of {@link |
| 367 | android.app.IntentService#onHandleIntent onHandleIntent()}.</p> |
| 368 | |
| 369 | <p>If you decide to also override other callback methods, such as {@link |
| 370 | android.app.IntentService#onCreate onCreate()}, {@link |
| 371 | android.app.IntentService#onStartCommand onStartCommand()}, or {@link |
| 372 | android.app.IntentService#onDestroy onDestroy()}, be sure to call the super implementation, so |
| 373 | that the {@link android.app.IntentService} can properly handle the life of the worker thread.</p> |
| 374 | |
| 375 | <p>For example, {@link android.app.IntentService#onStartCommand onStartCommand()} must return |
| 376 | the default implementation (which is how the intent gets delivered to {@link |
| 377 | android.app.IntentService#onHandleIntent onHandleIntent()}):</p> |
| 378 | |
| 379 | <pre> |
| 380 | @Override |
| 381 | public int onStartCommand(Intent intent, int flags, int startId) { |
| 382 | Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); |
| 383 | return super.onStartCommand(intent,flags,startId); |
| 384 | } |
| 385 | </pre> |
| 386 | |
| 387 | <p>Besides {@link android.app.IntentService#onHandleIntent onHandleIntent()}, the only method |
| 388 | from which you don't need to call the super class is {@link android.app.IntentService#onBind |
| 389 | onBind()} (but you only need to implement that if your service allows binding).</p> |
| 390 | |
| 391 | <p>In the next section, you'll see how the same kind of service is implemented when extending |
| 392 | the base {@link android.app.Service} class, which is a lot more code, but which might be |
| 393 | appropriate if you need to handle simultaneous start requests.</p> |
| 394 | |
| 395 | |
| 396 | <h3 id="ExtendingService">Extending the Service class</h3> |
| 397 | |
| 398 | <p>As you saw in the previous section, using {@link android.app.IntentService} makes your |
| 399 | implementation of a started service very simple. If, however, you require your service to |
| 400 | perform multi-threading (instead of processing start requests through a work queue), then you |
| 401 | can extend the {@link android.app.Service} class to handle each intent.</p> |
| 402 | |
| 403 | <p>For comparison, the following example code is an implementation of the {@link |
| 404 | android.app.Service} class that performs the exact same work as the example above using {@link |
| 405 | android.app.IntentService}. That is, for each start request, it uses a worker thread to perform the |
| 406 | job and processes only one request at a time.</p> |
| 407 | |
| 408 | <pre> |
| 409 | public class HelloService extends Service { |
| 410 | private Looper mServiceLooper; |
| 411 | private ServiceHandler mServiceHandler; |
| 412 | |
| 413 | // Handler that receives messages from the thread |
| 414 | private final class ServiceHandler extends Handler { |
| 415 | public ServiceHandler(Looper looper) { |
| 416 | super(looper); |
| 417 | } |
| 418 | @Override |
| 419 | public void handleMessage(Message msg) { |
| 420 | // Normally we would do some work here, like download a file. |
| 421 | // For our sample, we just sleep for 5 seconds. |
| 422 | long endTime = System.currentTimeMillis() + 5*1000; |
| 423 | while (System.currentTimeMillis() < endTime) { |
| 424 | synchronized (this) { |
| 425 | try { |
| 426 | wait(endTime - System.currentTimeMillis()); |
| 427 | } catch (Exception e) { |
| 428 | } |
| 429 | } |
| 430 | } |
| 431 | // Stop the service using the startId, so that we don't stop |
| 432 | // the service in the middle of handling another job |
| 433 | stopSelf(msg.arg1); |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | @Override |
| 438 | public void onCreate() { |
| 439 | // Start up the thread running the service. Note that we create a |
| 440 | // separate thread because the service normally runs in the process's |
| 441 | // main thread, which we don't want to block. We also make it |
| 442 | // background priority so CPU-intensive work will not disrupt our UI. |
| 443 | HandlerThread thread = new HandlerThread("ServiceStartArguments", |
| 444 | Process.THREAD_PRIORITY_BACKGROUND); |
| 445 | thread.start(); |
| 446 | |
| 447 | // Get the HandlerThread's Looper and use it for our Handler |
| 448 | mServiceLooper = thread.getLooper(); |
| 449 | mServiceHandler = new ServiceHandler(mServiceLooper); |
| 450 | } |
| 451 | |
| 452 | @Override |
| 453 | public int onStartCommand(Intent intent, int flags, int startId) { |
| 454 | Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show(); |
| 455 | |
| 456 | // For each start request, send a message to start a job and deliver the |
| 457 | // start ID so we know which request we're stopping when we finish the job |
| 458 | Message msg = mServiceHandler.obtainMessage(); |
| 459 | msg.arg1 = startId; |
| 460 | mServiceHandler.sendMessage(msg); |
| 461 | |
| 462 | // If we get killed, after returning from here, restart |
| 463 | return START_STICKY; |
| 464 | } |
| 465 | |
| 466 | @Override |
| 467 | public IBinder onBind(Intent intent) { |
| 468 | // We don't provide binding, so return null |
| 469 | return null; |
| 470 | } |
| 471 | |
| 472 | @Override |
| 473 | public void onDestroy() { |
| 474 | Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show(); |
| 475 | } |
| 476 | } |
| 477 | </pre> |
| 478 | |
| 479 | <p>As you can see, it's a lot more work than using {@link android.app.IntentService}.</p> |
| 480 | |
| 481 | <p>However, because you handle each call to {@link android.app.Service#onStartCommand |
| 482 | onStartCommand()} yourself, you can perform multiple requests simultaneously. That's not what |
| 483 | this example does, but if that's what you want, then you can create a new thread for each |
| 484 | request and run them right away (instead of waiting for the previous request to finish).</p> |
| 485 | |
| 486 | <p>Notice that the {@link android.app.Service#onStartCommand onStartCommand()} method must return an |
| 487 | integer. The integer is a value that describes how the system should continue the service in the |
| 488 | event that the system kills it (as discussed above, the default implementation for {@link |
| 489 | android.app.IntentService} handles this for you, though you are able to modify it). The return value |
| 490 | from {@link android.app.Service#onStartCommand onStartCommand()} must be one of the following |
| 491 | constants:</p> |
| 492 | |
| 493 | <dl> |
| 494 | <dt>{@link android.app.Service#START_NOT_STICKY}</dt> |
| 495 | <dd>If the system kills the service after {@link android.app.Service#onStartCommand |
| 496 | onStartCommand()} returns, <em>do not</em> recreate the service, unless there are pending |
| 497 | intents to deliver. This is the safest option to avoid running your service when not necessary |
| 498 | and when your application can simply restart any unfinished jobs.</dd> |
| 499 | <dt>{@link android.app.Service#START_STICKY}</dt> |
| 500 | <dd>If the system kills the service after {@link android.app.Service#onStartCommand |
| 501 | onStartCommand()} returns, recreate the service and call {@link |
| 502 | android.app.Service#onStartCommand onStartCommand()}, but <em>do not</em> redeliver the last intent. |
| 503 | Instead, the system calls {@link android.app.Service#onStartCommand onStartCommand()} with a |
| 504 | null intent, unless there were pending intents to start the service, in which case, |
| 505 | those intents are delivered. This is suitable for media players (or similar services) that are not |
| 506 | executing commands, but running indefinitely and waiting for a job.</dd> |
| 507 | <dt>{@link android.app.Service#START_REDELIVER_INTENT}</dt> |
| 508 | <dd>If the system kills the service after {@link android.app.Service#onStartCommand |
| 509 | onStartCommand()} returns, recreate the service and call {@link |
| 510 | android.app.Service#onStartCommand onStartCommand()} with the last intent that was delivered to the |
| 511 | service. Any pending intents are delivered in turn. This is suitable for services that are |
| 512 | actively performing a job that should be immediately resumed, such as downloading a file.</dd> |
| 513 | </dl> |
| 514 | <p>For more details about these return values, see the linked reference documentation for each |
| 515 | constant.</p> |
| 516 | |
| 517 | |
| 518 | |
| 519 | <h3 id="StartingAService">Starting a Service</h3> |
| 520 | |
| 521 | <p>You can start a service from an activity or other application component by passing an |
| 522 | {@link android.content.Intent} (specifying the service to start) to {@link |
| 523 | android.content.Context#startService startService()}. The Android system calls the service's {@link |
| 524 | android.app.Service#onStartCommand onStartCommand()} method and passes it the {@link |
| 525 | android.content.Intent}. (You should never call {@link android.app.Service#onStartCommand |
| 526 | onStartCommand()} directly.)</p> |
| 527 | |
| 528 | <p>For example, an activity can start the example service in the previous section ({@code |
| 529 | HelloSevice}) using an explicit intent with {@link android.content.Context#startService |
| 530 | startService()}:</p> |
| 531 | |
| 532 | <pre> |
| 533 | Intent intent = new Intent(this, HelloService.class); |
| 534 | startService(intent); |
| 535 | </pre> |
| 536 | |
| 537 | <p>The {@link android.content.Context#startService startService()} method returns immediately and |
| 538 | the Android system calls the service's {@link android.app.Service#onStartCommand |
| 539 | onStartCommand()} method. If the service is not already running, the system first calls {@link |
| 540 | android.app.Service#onCreate onCreate()}, then calls {@link android.app.Service#onStartCommand |
| 541 | onStartCommand()}.</p> |
| 542 | |
| 543 | <p>If the service does not also provide binding, the intent delivered with {@link |
| 544 | android.content.Context#startService startService()} is the only mode of communication between the |
| 545 | application component and the service. However, if you want the service to send a result back, then |
| 546 | the client that starts the service can create a {@link android.app.PendingIntent} for a broadcast |
| 547 | (with {@link android.app.PendingIntent#getBroadcast getBroadcast()}) and deliver it to the service |
| 548 | in the {@link android.content.Intent} that starts the service. The service can then use the |
| 549 | broadcast to deliver a result.</p> |
| 550 | |
| 551 | <p>Multiple requests to start the service result in multiple corresponding calls to the service's |
| 552 | {@link android.app.Service#onStartCommand onStartCommand()}. However, only one request to stop |
| 553 | the service (with {@link android.app.Service#stopSelf stopSelf()} or {@link |
| 554 | android.content.Context#stopService stopService()}) is required to stop it.</p> |
| 555 | |
| 556 | |
| 557 | <h3 id="Stopping">Stopping a service</h3> |
| 558 | |
| 559 | <p>A started service must manage its own lifecycle. That is, the system does not stop or |
| 560 | destroy the service unless it must recover system memory and the service |
| 561 | continues to run after {@link android.app.Service#onStartCommand onStartCommand()} returns. So, |
| 562 | the service must stop itself by calling {@link android.app.Service#stopSelf stopSelf()} or another |
| 563 | component can stop it by calling {@link android.content.Context#stopService stopService()}.</p> |
| 564 | |
| 565 | <p>Once requested to stop with {@link android.app.Service#stopSelf stopSelf()} or {@link |
| 566 | android.content.Context#stopService stopService()}, the system destroys the service as soon as |
| 567 | possible.</p> |
| 568 | |
| 569 | <p>However, if your service handles multiple requests to {@link |
| 570 | android.app.Service#onStartCommand onStartCommand()} concurrently, then you shouldn't stop the |
| 571 | service when you're done processing a start request, because you might have since received a new |
| 572 | start request (stopping at the end of the first request would terminate the second one). To avoid |
| 573 | this problem, you can use {@link android.app.Service#stopSelf(int)} to ensure that your request to |
| 574 | stop the service is always based on the most recent start request. That is, when you call {@link |
| 575 | android.app.Service#stopSelf(int)}, you pass the ID of the start request (the <code>startId</code> |
| 576 | delivered to {@link android.app.Service#onStartCommand onStartCommand()}) to which your stop request |
| 577 | corresponds. Then if the service received a new start request before you were able to call {@link |
| 578 | android.app.Service#stopSelf(int)}, then the ID will not match and the service will not stop.</p> |
| 579 | |
| 580 | <p class="caution"><strong>Caution:</strong> It's important that your application stops its services |
| 581 | when it's done working, to avoid wasting system resources and consuming battery power. If necessary, |
| 582 | other components can stop the service by calling {@link |
| 583 | android.content.Context#stopService stopService()}. Even if you enable binding for the service, |
| 584 | you must always stop the service yourself if it ever received a call to {@link |
| 585 | android.app.Service#onStartCommand onStartCommand()}.</p> |
| 586 | |
| 587 | <p>For more information about the lifecycle of a service, see the section below about <a |
| 588 | href="#Lifecycle">Managing the Lifecycle of a Service</a>.</p> |
| 589 | |
| 590 | |
| 591 | |
| 592 | <h2 id="CreatingBoundService">Creating a Bound Service</h2> |
| 593 | |
| 594 | <p>A bound service is one that allows application components to bind to it by calling {@link |
| 595 | android.content.Context#bindService bindService()} in order to create a long-standing connection |
| 596 | (and generally does not allow components to <em>start</em> it by calling {@link |
| 597 | android.content.Context#startService startService()}).</p> |
| 598 | |
| 599 | <p>You should create a bound service when you want to interact with the service from activities |
| 600 | and other components in your application or to expose some of your application's functionality to |
| 601 | other applications, through interprocess communication (IPC).</p> |
| 602 | |
| 603 | <p>To create a bound service, you must implement the {@link |
| 604 | android.app.Service#onBind onBind()} callback method to return an {@link android.os.IBinder} that |
| 605 | defines the interface for communication with the service. Other application components can then call |
| 606 | {@link android.content.Context#bindService bindService()} to retrieve the interface and |
| 607 | begin calling methods on the service. The service lives only to serve the application component that |
| 608 | is bound to it, so when there are no components bound to the service, the system destroys it |
| 609 | (you do <em>not</em> need to stop a bound service in the way you must when the service is started |
| 610 | through {@link android.app.Service#onStartCommand onStartCommand()}).</p> |
| 611 | |
| 612 | <p>To create a bound service, the first thing you must do is define the interface that specifies |
| 613 | how a client can communicate with the service. This interface between the service |
| 614 | and a client must be an implementation of {@link android.os.IBinder} and is what your service must |
| 615 | return from the {@link android.app.Service#onBind |
| 616 | onBind()} callback method. Once the client receives the {@link android.os.IBinder}, it can begin |
| 617 | interacting with the service through that interface.</p> |
| 618 | |
| 619 | <p>Multiple clients can bind to the service at once. When a client is done interacting with the |
| 620 | service, it calls {@link android.content.Context#unbindService unbindService()} to unbind. Once |
| 621 | there are no clients bound to the service, the system destroys the service.</p> |
| 622 | |
| 623 | <p>There are multiple ways to implement a bound service and the implementation is more |
| 624 | complicated than a started service, so the bound service discussion appears in a separate |
| 625 | document about <a |
| 626 | href="{@docRoot}guide/components/bound-services.html">Bound Services</a>.</p> |
| 627 | |
| 628 | |
| 629 | |
| 630 | <h2 id="Notifications">Sending Notifications to the User</h2> |
| 631 | |
| 632 | <p>Once running, a service can notify the user of events using <a |
| 633 | href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a |
| 634 | href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a>.</p> |
| 635 | |
| 636 | <p>A toast notification is a message that appears on the surface of the current window for a |
| 637 | moment then disappears, while a status bar notification provides an icon in the status bar with a |
| 638 | message, which the user can select in order to take an action (such as start an activity).</p> |
| 639 | |
| 640 | <p>Usually, a status bar notification is the best technique when some background work has completed |
| 641 | (such as a file completed |
| 642 | downloading) and the user can now act on it. When the user selects the notification from the |
| 643 | expanded view, the notification can start an activity (such as to view the downloaded file).</p> |
| 644 | |
| 645 | <p>See the <a |
| 646 | href="{@docRoot}guide/topics/ui/notifiers/toasts.html">Toast Notifications</a> or <a |
| 647 | href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Status Bar Notifications</a> |
| 648 | developer guides for more information.</p> |
| 649 | |
| 650 | |
| 651 | |
| 652 | <h2 id="Foreground">Running a Service in the Foreground</h2> |
| 653 | |
| 654 | <p>A foreground service is a service that's considered to be something the |
| 655 | user is actively aware of and thus not a candidate for the system to kill when low on memory. A |
| 656 | foreground service must provide a notification for the status bar, which is placed under the |
| 657 | "Ongoing" heading, which means that the notification cannot be dismissed unless the service is |
| 658 | either stopped or removed from the foreground.</p> |
| 659 | |
| 660 | <p>For example, a music player that plays music from a service should be set to run in the |
| 661 | foreground, because the user is explicitly aware |
| 662 | of its operation. The notification in the status bar might indicate the current song and allow |
| 663 | the user to launch an activity to interact with the music player.</p> |
| 664 | |
| 665 | <p>To request that your service run in the foreground, call {@link |
| 666 | android.app.Service#startForeground startForeground()}. This method takes two parameters: an integer |
| 667 | that uniquely identifies the notification and the {@link |
| 668 | android.app.Notification} for the status bar. For example:</p> |
| 669 | |
| 670 | <pre> |
| 671 | Notification notification = new Notification(R.drawable.icon, getText(R.string.ticker_text), |
| 672 | System.currentTimeMillis()); |
| 673 | Intent notificationIntent = new Intent(this, ExampleActivity.class); |
| 674 | PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); |
| 675 | notification.setLatestEventInfo(this, getText(R.string.notification_title), |
| 676 | getText(R.string.notification_message), pendingIntent); |
| Scott Main | 2e6de8f | 2013-04-30 10:51:12 -0700 | [diff] [blame] | 677 | startForeground(ONGOING_NOTIFICATION_ID, notification); |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 678 | </pre> |
| 679 | |
| Scott Main | 2e6de8f | 2013-04-30 10:51:12 -0700 | [diff] [blame] | 680 | <p class="caution"><strong>Caution:</strong> The integer ID you give to {@link |
| 681 | android.app.Service#startForeground startForeground()} must not be 0.</p> |
| 682 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 683 | |
| 684 | <p>To remove the service from the foreground, call {@link |
| 685 | android.app.Service#stopForeground stopForeground()}. This method takes a boolean, indicating |
| 686 | whether to remove the status bar notification as well. This method does <em>not</em> stop the |
| 687 | service. However, if you stop the service while it's still running in the foreground, then the |
| 688 | notification is also removed.</p> |
| 689 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 690 | <p>For more information about notifications, see <a |
| 691 | href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Creating Status Bar |
| 692 | Notifications</a>.</p> |
| 693 | |
| 694 | |
| 695 | |
| 696 | <h2 id="Lifecycle">Managing the Lifecycle of a Service</h2> |
| 697 | |
| 698 | <p>The lifecycle of a service is much simpler than that of an activity. However, it's even more important |
| 699 | that you pay close attention to how your service is created and destroyed, because a service |
| 700 | can run in the background without the user being aware.</p> |
| 701 | |
| 702 | <p>The service lifecycle—from when it's created to when it's destroyed—can follow two |
| 703 | different paths:</p> |
| 704 | |
| 705 | <ul> |
| 706 | <li>A started service |
| 707 | <p>The service is created when another component calls {@link |
| 708 | android.content.Context#startService startService()}. The service then runs indefinitely and must |
| 709 | stop itself by calling {@link |
| 710 | android.app.Service#stopSelf() stopSelf()}. Another component can also stop the |
| 711 | service by calling {@link android.content.Context#stopService |
| 712 | stopService()}. When the service is stopped, the system destroys it..</p></li> |
| 713 | |
| 714 | <li>A bound service |
| 715 | <p>The service is created when another component (a client) calls {@link |
| 716 | android.content.Context#bindService bindService()}. The client then communicates with the service |
| 717 | through an {@link android.os.IBinder} interface. The client can close the connection by calling |
| 718 | {@link android.content.Context#unbindService unbindService()}. Multiple clients can bind to |
| 719 | the same service and when all of them unbind, the system destroys the service. (The service |
| 720 | does <em>not</em> need to stop itself.)</p></li> |
| 721 | </ul> |
| 722 | |
| 723 | <p>These two paths are not entirely separate. That is, you can bind to a service that was already |
| 724 | started with {@link android.content.Context#startService startService()}. For example, a background |
| 725 | music service could be started by calling {@link android.content.Context#startService |
| 726 | startService()} with an {@link android.content.Intent} that identifies the music to play. Later, |
| 727 | possibly when the user wants to exercise some control over the player or get information about the |
| 728 | current song, an activity can bind to the service by calling {@link |
| 729 | android.content.Context#bindService bindService()}. In cases like this, {@link |
| 730 | android.content.Context#stopService stopService()} or {@link android.app.Service#stopSelf |
| 731 | stopSelf()} does not actually stop the service until all clients unbind. </p> |
| 732 | |
| 733 | |
| 734 | <h3 id="LifecycleCallbacks">Implementing the lifecycle callbacks</h3> |
| 735 | |
| 736 | <p>Like an activity, a service has lifecycle callback methods that you can implement to monitor |
| 737 | changes in the service's state and perform work at the appropriate times. The following skeleton |
| 738 | service demonstrates each of the lifecycle methods:</p> |
| 739 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 740 | <pre> |
| 741 | public class ExampleService extends Service { |
| 742 | int mStartMode; // indicates how to behave if the service is killed |
| 743 | IBinder mBinder; // interface for clients that bind |
| 744 | boolean mAllowRebind; // indicates whether onRebind should be used |
| 745 | |
| 746 | @Override |
| 747 | public void {@link android.app.Service#onCreate onCreate}() { |
| 748 | // The service is being created |
| 749 | } |
| 750 | @Override |
| 751 | public int {@link android.app.Service#onStartCommand onStartCommand}(Intent intent, int flags, int startId) { |
| 752 | // The service is starting, due to a call to {@link android.content.Context#startService startService()} |
| 753 | return <em>mStartMode</em>; |
| 754 | } |
| 755 | @Override |
| 756 | public IBinder {@link android.app.Service#onBind onBind}(Intent intent) { |
| 757 | // A client is binding to the service with {@link android.content.Context#bindService bindService()} |
| 758 | return <em>mBinder</em>; |
| 759 | } |
| 760 | @Override |
| 761 | public boolean {@link android.app.Service#onUnbind onUnbind}(Intent intent) { |
| 762 | // All clients have unbound with {@link android.content.Context#unbindService unbindService()} |
| 763 | return <em>mAllowRebind</em>; |
| 764 | } |
| 765 | @Override |
| 766 | public void {@link android.app.Service#onRebind onRebind}(Intent intent) { |
| 767 | // A client is binding to the service with {@link android.content.Context#bindService bindService()}, |
| 768 | // after onUnbind() has already been called |
| 769 | } |
| 770 | @Override |
| 771 | public void {@link android.app.Service#onDestroy onDestroy}() { |
| 772 | // The service is no longer used and is being destroyed |
| 773 | } |
| 774 | } |
| 775 | </pre> |
| 776 | |
| 777 | <p class="note"><strong>Note:</strong> Unlike the activity lifecycle callback methods, you are |
| 778 | <em>not</em> required to call the superclass implementation of these callback methods.</p> |
| 779 | |
| Scott Main | cb0b2df | 2012-08-09 11:49:50 -0700 | [diff] [blame] | 780 | <img src="{@docRoot}images/service_lifecycle.png" alt="" /> |
| 781 | <p class="img-caption"><strong>Figure 2.</strong> The service lifecycle. The diagram on the left |
| 782 | shows the lifecycle when the service is created with {@link android.content.Context#startService |
| 783 | startService()} and the diagram on the right shows the lifecycle when the service is created |
| 784 | with {@link android.content.Context#bindService bindService()}.</p> |
| 785 | |
| Scott Main | 50e990c | 2012-06-21 17:14:39 -0700 | [diff] [blame] | 786 | <p>By implementing these methods, you can monitor two nested loops of the service's lifecycle: </p> |
| 787 | |
| 788 | <ul> |
| 789 | <li>The <strong>entire lifetime</strong> of a service happens between the time {@link |
| 790 | android.app.Service#onCreate onCreate()} is called and the time {@link |
| 791 | android.app.Service#onDestroy} returns. Like an activity, a service does its initial setup in |
| 792 | {@link android.app.Service#onCreate onCreate()} and releases all remaining resources in {@link |
| 793 | android.app.Service#onDestroy onDestroy()}. For example, a |
| 794 | music playback service could create the thread where the music will be played in {@link |
| 795 | android.app.Service#onCreate onCreate()}, then stop the thread in {@link |
| 796 | android.app.Service#onDestroy onDestroy()}. |
| 797 | |
| 798 | <p>The {@link android.app.Service#onCreate onCreate()} and {@link android.app.Service#onDestroy |
| 799 | onDestroy()} methods are called for all services, whether |
| 800 | they're created by {@link android.content.Context#startService startService()} or {@link |
| 801 | android.content.Context#bindService bindService()}.</p></li> |
| 802 | |
| 803 | <li>The <strong>active lifetime</strong> of a service begins with a call to either {@link |
| 804 | android.app.Service#onStartCommand onStartCommand()} or {@link android.app.Service#onBind onBind()}. |
| 805 | Each method is handed the {@link |
| 806 | android.content.Intent} that was passed to either {@link android.content.Context#startService |
| 807 | startService()} or {@link android.content.Context#bindService bindService()}, respectively. |
| 808 | <p>If the service is started, the active lifetime ends the same time that the entire lifetime |
| 809 | ends (the service is still active even after {@link android.app.Service#onStartCommand |
| 810 | onStartCommand()} returns). If the service is bound, the active lifetime ends when {@link |
| 811 | android.app.Service#onUnbind onUnbind()} returns.</p> |
| 812 | </li> |
| 813 | </ul> |
| 814 | |
| 815 | <p class="note"><strong>Note:</strong> Although a started service is stopped by a call to |
| 816 | either {@link android.app.Service#stopSelf stopSelf()} or {@link |
| 817 | android.content.Context#stopService stopService()}, there is not a respective callback for the |
| 818 | service (there's no {@code onStop()} callback). So, unless the service is bound to a client, |
| 819 | the system destroys it when the service is stopped—{@link |
| 820 | android.app.Service#onDestroy onDestroy()} is the only callback received.</p> |
| 821 | |
| 822 | <p>Figure 2 illustrates the typical callback methods for a service. Although the figure separates |
| 823 | services that are created by {@link android.content.Context#startService startService()} from those |
| 824 | created by {@link android.content.Context#bindService bindService()}, keep |
| 825 | in mind that any service, no matter how it's started, can potentially allow clients to bind to it. |
| 826 | So, a service that was initially started with {@link android.app.Service#onStartCommand |
| 827 | onStartCommand()} (by a client calling {@link android.content.Context#startService startService()}) |
| 828 | can still receive a call to {@link android.app.Service#onBind onBind()} (when a client calls |
| 829 | {@link android.content.Context#bindService bindService()}).</p> |
| 830 | |
| 831 | <p>For more information about creating a service that provides binding, see the <a |
| 832 | href="{@docRoot}guide/components/bound-services.html">Bound Services</a> document, |
| 833 | which includes more information about the {@link android.app.Service#onRebind onRebind()} |
| 834 | callback method in the section about <a |
| 835 | href="{@docRoot}guide/components/bound-services.html#Lifecycle">Managing the Lifecycle of |
| 836 | a Bound Service</a>.</p> |
| 837 | |
| 838 | |
| 839 | <!-- |
| 840 | <h2>Beginner's Path</h2> |
| 841 | |
| 842 | <p>To learn how to query data from the system or other applications (such as contacts or media |
| 843 | stored on the device), continue with the <b><a |
| 844 | href="{@docRoot}guide/topics/providers/content-providers.html">Content Providers</a></b> |
| 845 | document.</p> |
| 846 | --> |