1page.title=Привязанные службы 2parent.title=Службы 3parent.link=services.html 4@jd:body 5 6 7<div id="qv-wrapper"> 8<ol id="qv"> 9<h2>Содержание документа</h2> 10<ol> 11 <li><a href="#Basics">Основы</a></li> 12 <li><a href="#Creating">Создание привязанной службы</a> 13 <ol> 14 <li><a href="#Binder">Расширение класса Binder</a></li> 15 <li><a href="#Messenger">Использование объекта Messenger</a></li> 16 </ol> 17 </li> 18 <li><a href="#Binding">Привязка к службе</a></li> 19 <li><a href="#Lifecycle">Управление жизненным циклом привязанной службы</a></li> 20</ol> 21 22<h2>Ключевые классы</h2> 23<ol> 24 <li>{@link android.app.Service}</li> 25 <li>{@link android.content.ServiceConnection}</li> 26 <li>{@link android.os.IBinder}</li> 27</ol> 28 29<h2>Примеры</h2> 30<ol> 31 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code 32 RemoteService}</a></li> 33 <li><a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code 34 LocalService}</a></li> 35</ol> 36 37<h2>См. также:</h2> 38<ol> 39 <li><a href="{@docRoot}guide/components/services.html">Службы</a></li> 40</ol> 41</div> 42 43 44<p>Привязанная служба предоставляет интерфейс типа клиент-сервер. Привязанная служба позволяет компонентам приложения 45(например, операциям) взаимодействовать со службой, отправлять запросы, получать результаты и даже делать то же самое с другими процессами через 46IPC. Привязанная служба обычно работает, пока другой компонент приложения 47привязан к ней. Она не работает постоянно в фоновом режиме.</p> 48 49<p>В этом документе рассказывается, как создать привязанную службу, включая привязку 50службы к другим компонентам приложения. Также рекомендуем обратиться к статье <a href="{@docRoot}guide/components/services.html">Службы</a>, чтобы узнать подробнее 51о службах, например, об организации отправки уведомлений от службы, настройке службы 52на работу на переднем плане и т. д.</p> 53 54 55<h2 id="Basics">Основы</h2> 56 57<p>Привязанная служба представляет собой реализацию класса {@link android.app.Service}, которая позволяет 58другим приложениям привязываться к нему и взаимодействовать с ним. Чтобы обеспечить привязку службы 59, сначала необходимо реализовать метод обратного вызова {@link android.app.Service#onBind onBind()}. Этот 60метод возвращает объект {@link android.os.IBinder}. Он определяет программный интерфейс, 61с помощью которого клиенты могут взаимодействовать со службой.</p> 62 63<div class="sidebox-wrapper"> 64<div class="sidebox"> 65 <h3>Привязка к запущенной службе</h3> 66 67<p>Как указано в статье <a href="{@docRoot}guide/components/services.html">Службы</a>, 68можно создать службу, которая одновременно и запущена, и привязана. Это означает, что службу можно запустить 69путем вызова метода {@link android.content.Context#startService startService()}, который позволяет службе 70работать неограниченное время, а также позволяет клиентам привязываться к ней с помощью вызова метода {@link 71android.content.Context#bindService bindService()}. 72 <p>Если разрешить запуск и привязку службы, то после ее запуска 73система <em>не</em> уничтожает ее после отмены всех привязок клиентов. Вместо этого необходимо 74явным образом остановить службу, вызвав метод {@link android.app.Service#stopSelf stopSelf()} или {@link 75android.content.Context#stopService stopService()}.</p> 76 77<p>Несмотря на то, что обычно необходимо реализовывать либо метод {@link android.app.Service#onBind onBind()}, 78<em>либо метод</em> {@link android.app.Service#onStartCommand onStartCommand()}, в некоторых случаях требуется 79реализовать оба этих метода. Например, в музыкальном проигрывателе может оказаться полезным разрешить выполнение службы в течение 80неограниченного времени, а также обеспечить ее привязку. Таким образом, операция может запустить службу для воспроизведения музыки 81, которая будет воспроизводиться даже после выхода пользователя из приложения. После того возвращения 82пользователя к приложению операция может отменить привязку к службе, чтобы вернуть управление воспроизведением.</p> 83 84<p>Обязательно ознакомьтесь с разделом, посвященным <a href="#Lifecycle">управлению жизненным циклом привязанной 85службы</a>. В нем представлены подробные сведения о жизненном цикле службы, привязанной к уже 86запущенной службе.</p> 87</div> 88</div> 89 90<p>Для привязки к службе клиент может вызвать метод {@link android.content.Context#bindService 91bindService()}. После привязки он должен предоставить реализацию метода {@link 92android.content.ServiceConnection}, который служит для отслеживания подключения к службе. Метод {@link 93android.content.Context#bindService bindService()} возвращается незамедлительно без значения, однако 94, когда система Android устанавливает подключение 95клиент-служба, она вызывает метод {@link 96android.content.ServiceConnection#onServiceConnected onServiceConnected()} для {@link 97android.content.ServiceConnection}, чтобы выдать объект {@link android.os.IBinder}, который 98клиент может использовать для взаимодействия со службой.</p> 99 100<p>Одновременно к службе могут подключиться сразу несколько клиентов. Однако система вызывает метод 101{@link android.app.Service#onBind onBind()} вашей службы для получения объекта {@link android.os.IBinder} 102только при первой привязке клиента. После чего система выдает такой же объект {@link android.os.IBinder} для любых 103дополнительных клиентов, которые выполняют привязку, без повторного вызова метода {@link android.app.Service#onBind onBind()}.</p> 104 105<p>Когда отменяется привязка последнего клиента от службы, система уничтожает службу (если только 106служба не была так же запущена методом {@link android.content.Context#startService startService()}).</p> 107 108<p>Самую важную роль в реализации привязанной службы играет определение интерфейса, 109который возвращает ваш метод обратного вызова {@link android.app.Service#onBind onBind()}. Существует несколько 110различных способов определения интерфейса {@link android.os.IBinder} службы. Каждый из них рассматривается в следующем 111разделе.</p> 112 113 114 115<h2 id="Creating">Создание привязанной службы</h2> 116 117<p>При создании службы, обеспечивающей привязку, требуется объект {@link android.os.IBinder}, 118который обеспечивает программный интерфейс, с помощью которого клиенты могут взаимодействовать со службой. Существует 119три способа определения такого интерфейса:</p> 120 121<dl> 122 <dt><a href="#Binder">Расширение класса Binder</a></dt> 123 <dd>Если служба является частной и предоставляется в рамках вашего собственного приложения, а также выполняется в том же процессе, что и клиент 124(общий процесс), создавать интерфейс следует путем расширения класса {@link android.os.Binder} 125и возврата его экземпляра из метода 126{@link android.app.Service#onBind onBind()}. Клиент получает объект {@link android.os.Binder}, 127после чего он может использовать его для получения прямого доступа к общедоступным методам, имеющимся либо в реализации {@link android.os.Binder}, 128либо даже в {@link android.app.Service}. 129 <p>Этот способ является предпочтительным, когда служба просто выполняется в фоновом режиме для 130вашего приложения. Этот способ не подходит для создания интерфейса только тогда, 131когда ваша служба используется другими приложениями или в отдельных процессах.</dd> 132 133 <dt><a href="#Messenger">Использование объекта Messenger</a></dt> 134 <dd>Если необходимо, чтобы интерфейс службы был доступен для разных процессов, его можно создать 135с помощью объекта {@link android.os.Messenger}. Таким образом, служба 136определяет объект {@link android.os.Handler}, соответствующий различным типам объектов {@link 137android.os.Message}. Этот объект {@link android.os.Handler} 138является основой для объекта {@link android.os.Messenger}, который, в свою очередь, предоставляет клиенту объект {@link android.os.IBinder}, 139благодаря чему последний может отправлять команды в службу с помощью объектов {@link 140android.os.Message}. Кроме того, клиент может определить объект {@link android.os.Messenger} для самого 141себя, что позволяет службе возвращать сообщения клиенту. 142 <p>Это самый простой способ организовать взаимодействие процессов, поскольку {@link 143android.os.Messenger} организует очередь всех запросов в рамках одного потока, поэтому вам не нужно делать 144свою службу потокобезопасной.</p> 145 </dd> 146 147 <dt>Использование языка AIDL</dt> 148 <dd>AIDL (Android Interface Definition Language) выполняет всю работу по разделению объектов на 149примитивы, которые операционная система может распознать и распределить по процессам для организации 150взаимодействия между ними (IPC). Предыдущий способ с использованием объекта {@link android.os.Messenger} фактически основан на AIDL, поскольку это его 151базовая структура. Как уже упоминалось выше, объект {@link android.os.Messenger} создает очередь из всех 152запросов клиентов в рамках одного потока, поэтому служба одновременно получает только один запрос. Однако, 153если необходимо, чтобы служба обрабатывала одновременно сразу несколько запросов, можно использовать AIDL 154напрямую. В таком случае ваша служба должна поддерживать многопоточность и должна быть потокобезопасной. 155 <p>Чтобы использовать AIDL напрямую, необходимо 156создать файл {@code .aidl}, который определяет программный интерфейс. Этот файл используется инструментами SDK Android для 157создания абстрактного класса, который реализует интерфейс и обеспечивает взаимодействие процессов, и который 158в дальнейшем можно расширить в службе.</p> 159 </dd> 160</dl> 161 162 <p class="note"><strong>Примечание.</strong> В большинстве приложений <strong>не следует</strong> использовать AIDL для 163создания и привязки службы, поскольку для этого может потребоваться поддержка многопоточности, что, в свою очередь, может привести 164к более сложной реализации. Поэтому AIDL не подходит для большинства приложений, 165и в этой статье мы не будем рассматривать использование этого способа для вашей службы. Если же вы точно уверены, что 166вам необходимо использовать AIDL напрямую, обратитесь к статье 167<a href="{@docRoot}guide/components/aidl.html">AIDL</a>.</p> 168 169 170 171 172<h3 id="Binder">Расширение класса Binder</h3> 173 174<p>Если ваша служба используется только локальным приложением и не взаимодействует с разными процессами, 175можно реализовать собственный класс {@link android.os.Binder}, с помощью которого клиент получает прямой 176доступ к общедоступным методам в службе.</p> 177 178<p class="note"><strong>Примечание.</strong> Этот вариант подходит только в том случае, если клиент и служба выполняются внутри 179одного приложения и процесса, что является наиболее распространенной ситуацией. Например, расширение класса отлично подойдет для 180музыкального приложения, в котором необходимо привязать операцию к собственной службе приложения, которая 181воспроизводит музыку в фоновом режиме.</p> 182 183<p>Вот как это сделать:</p> 184<ol> 185 <li>Создайте в вашей службе экземпляр класса {@link android.os.Binder} со следующими характеристиками: 186 <ul> 187 <li>экземпляр содержит общедоступные методы, которые может вызывать клиент; либо</li> 188 <li>экземпляр возвращает текущий экземпляр класса {@link android.app.Service}, содержащий 189общедоступные методы, которые может вызывать клиент; или</li> 190 <li>экземпляр возвращает экземпляр другого класса, размещенного в службе, содержащий общедоступные методы, 191которые может вызывать клиент.</li> 192 </ul> 193 <li>Верните этот экземпляр класса {@link android.os.Binder} из метода обратного вызова {@link 194android.app.Service#onBind onBind()}.</li> 195 <li>В клиенте получите класс {@link android.os.Binder} от метода обратного вызова {@link 196android.content.ServiceConnection#onServiceConnected onServiceConnected()} и 197выполните вызовы к привязанной службе с помощью предоставленных методов.</li> 198</ol> 199 200<p class="note"><strong>Примечание.</strong> Служба и клиент должны выполняться в одном и том же приложении 201, поскольку в этом случае клиент может транслировать возвращенный объект и надлежащим образом вызывать его API-интерфейсы. Кроме того, служба 202и клиент должны выполняться в рамках одного и того же процесса, поскольку этот способ не подразумевает какого-либо 203распределения по процессам.</p> 204 205<p>Ниже представлен пример службы, которая предоставляет клиентам доступ к методам посредством реализации класса 206{@link android.os.Binder}:</p> 207 208<pre> 209public class LocalService extends Service { 210 // Binder given to clients 211 private final IBinder mBinder = new LocalBinder(); 212 // Random number generator 213 private final Random mGenerator = new Random(); 214 215 /** 216 * Class used for the client Binder. Because we know this service always 217 * runs in the same process as its clients, we don't need to deal with IPC. 218 */ 219 public class LocalBinder extends Binder { 220 LocalService getService() { 221 // Return this instance of LocalService so clients can call public methods 222 return LocalService.this; 223 } 224 } 225 226 @Override 227 public IBinder onBind(Intent intent) { 228 return mBinder; 229 } 230 231 /** method for clients */ 232 public int getRandomNumber() { 233 return mGenerator.nextInt(100); 234 } 235} 236</pre> 237 238<p>Объект {@code LocalBinder} предоставляет для клиентов метод {@code getService()}, чтобы они могли получить 239текущий экземпляр класса {@code LocalService}. Благодаря этому клиенты могут вызывать общедоступные методы в 240службе. Например, клиенты могут вызвать метод {@code getRandomNumber()} из службы.</p> 241 242<p>Ниже представлен пример операции, которая выполняет привязку к классу {@code LocalService} и вызывает метод {@code getRandomNumber()} 243при нажатии кнопки:</p> 244 245<pre> 246public class BindingActivity extends Activity { 247 LocalService mService; 248 boolean mBound = false; 249 250 @Override 251 protected void onCreate(Bundle savedInstanceState) { 252 super.onCreate(savedInstanceState); 253 setContentView(R.layout.main); 254 } 255 256 @Override 257 protected void onStart() { 258 super.onStart(); 259 // Bind to LocalService 260 Intent intent = new Intent(this, LocalService.class); 261 bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 262 } 263 264 @Override 265 protected void onStop() { 266 super.onStop(); 267 // Unbind from the service 268 if (mBound) { 269 unbindService(mConnection); 270 mBound = false; 271 } 272 } 273 274 /** Called when a button is clicked (the button in the layout file attaches to 275 * this method with the android:onClick attribute) */ 276 public void onButtonClick(View v) { 277 if (mBound) { 278 // Call a method from the LocalService. 279 // However, if this call were something that might hang, then this request should 280 // occur in a separate thread to avoid slowing down the activity performance. 281 int num = mService.getRandomNumber(); 282 Toast.makeText(this, "number: " + num, Toast.LENGTH_SHORT).show(); 283 } 284 } 285 286 /** Defines callbacks for service binding, passed to bindService() */ 287 private ServiceConnection mConnection = new ServiceConnection() { 288 289 @Override 290 public void onServiceConnected(ComponentName className, 291 IBinder service) { 292 // We've bound to LocalService, cast the IBinder and get LocalService instance 293 LocalBinder binder = (LocalBinder) service; 294 mService = binder.getService(); 295 mBound = true; 296 } 297 298 @Override 299 public void onServiceDisconnected(ComponentName arg0) { 300 mBound = false; 301 } 302 }; 303} 304</pre> 305 306<p>В примере выше показано, как клиент привязывается к службе с помощью реализации 307{@link android.content.ServiceConnection} и обратного вызова {@link 308android.content.ServiceConnection#onServiceConnected onServiceConnected()}. В 309следующем разделе представлена более подробная информация об этом процессе привязки к службе.</p> 310 311<p class="note"><strong>Примечание.</strong> В примере выше не выполняется явная отмена привязки к службе, 312однако всем клиентам следует отменять привязку в соответствующие сроки (например, когда операция приостанавливается).</p> 313 314<p>Примеры кода представлены в статьях, посвященных классам <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalService.html">{@code 315LocalService.java}</a> и <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/LocalServiceActivities.html">{@code 316LocalServiceActivities.java}</a>, в <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> 317 318 319 320 321 322<h3 id="Messenger">Использование объекта Messenger</h3> 323 324<div class="sidebox-wrapper"> 325<div class="sidebox"> 326 <h4>Сравнение с AIDL</h4> 327 <p>Когда необходимо организовать взаимодействие между процессами, использование объекта {@link android.os.Messenger} для интерфейса 328намного проще реализации с помощью AIDL, поскольку объект {@link android.os.Messenger} помещает 329в очередь все запросы к службе, тогда как интерфейс, основанный исключительно на AIDL, отправляет службе несколько запросов одновременно, 330для чего требуется поддержка многопоточности.</p> 331 <p>В большинстве приложений служба не должна поддерживать многопоточность, поэтому при использовании объекта {@link 332android.os.Messenger} служба может одновременно обрабатывать один запрос. Если вам важно, 333чтобы служба была многопоточной, для определения интерфейса следует использовать <a href="{@docRoot}guide/components/aidl.html">AIDL</a>.</p> 334</div> 335</div> 336 337<p>Если необходимо, чтобы служба взаимодействовала с удаленными процессами, для предоставления интерфейса службы можно воспользоваться объектом 338{@link android.os.Messenger}. Такой подход 339позволяет организовать взаимодействие между процессами (IPC) без необходимости использовать AIDL.</p> 340 341<p>Вот краткий обзор того, как следует использовать объект {@link android.os.Messenger}:</p> 342 343<ul> 344 <li>Служба реализует объект {@link android.os.Handler}, который получает обратный вызов для каждого 345вызова от клиента.</li> 346 <li>Объект {@link android.os.Handler} используется для создания объекта {@link android.os.Messenger} 347(который является ссылкой на объект {@link android.os.Handler}).</li> 348 <li>Объект {@link android.os.Messenger} создает объект {@link android.os.IBinder}, который служба 349возвращает клиентам из метода {@link android.app.Service#onBind onBind()}.</li> 350 <li>Клиенты используют полученный объект {@link android.os.IBinder} для создания экземпляра объекта {@link android.os.Messenger} 351(который ссылается на объект {@link android.os.Handler} службы), используемого клиентом для отправки объектов 352{@link android.os.Message} в службу.</li> 353 <li>Служба получает каждый объект {@link android.os.Message} в своем объекте {@link 354android.os.Handler} — в частности, в методе {@link android.os.Handler#handleMessage 355handleMessage()}.</li> 356</ul> 357 358 359<p>Таким образом, для клиента отсутствуют «методы» для отправки вызова службе. Вместо этого 360клиент отправляет «сообщения» (объекты {@link android.os.Message}), которые служба получает в 361своем объекте {@link android.os.Handler}.</p> 362 363<p>Ниже представлен пример службы, которая использует интерфейс {@link android.os.Messenger}:</p> 364 365<pre> 366public class MessengerService extends Service { 367 /** Command to the service to display a message */ 368 static final int MSG_SAY_HELLO = 1; 369 370 /** 371 * Handler of incoming messages from clients. 372 */ 373 class IncomingHandler extends Handler { 374 @Override 375 public void handleMessage(Message msg) { 376 switch (msg.what) { 377 case MSG_SAY_HELLO: 378 Toast.makeText(getApplicationContext(), "hello!", Toast.LENGTH_SHORT).show(); 379 break; 380 default: 381 super.handleMessage(msg); 382 } 383 } 384 } 385 386 /** 387 * Target we publish for clients to send messages to IncomingHandler. 388 */ 389 final Messenger mMessenger = new Messenger(new IncomingHandler()); 390 391 /** 392 * When binding to the service, we return an interface to our messenger 393 * for sending messages to the service. 394 */ 395 @Override 396 public IBinder onBind(Intent intent) { 397 Toast.makeText(getApplicationContext(), "binding", Toast.LENGTH_SHORT).show(); 398 return mMessenger.getBinder(); 399 } 400} 401</pre> 402 403<p>Обратите внимание, что метод {@link android.os.Handler#handleMessage handleMessage()} в объекте 404{@link android.os.Handler} — это место, где служба получает входящие объекты {@link android.os.Message} 405и решает, что делать дальше, руководствуясь элементом {@link android.os.Message#what}.</p> 406 407<p>Клиенту требуется лишь создать объект {@link android.os.Messenger} на основе объекта {@link 408android.os.IBinder}, возвращенного службой, и отправить сообщение с помощью метода {@link 409android.os.Messenger#send send()}. Ниже представлен пример того, как простая операция выполняет привязку к 410службе и отправляет ей сообщение {@code MSG_SAY_HELLO}:</p> 411 412<pre> 413public class ActivityMessenger extends Activity { 414 /** Messenger for communicating with the service. */ 415 Messenger mService = null; 416 417 /** Flag indicating whether we have called bind on the service. */ 418 boolean mBound; 419 420 /** 421 * Class for interacting with the main interface of the service. 422 */ 423 private ServiceConnection mConnection = new ServiceConnection() { 424 public void onServiceConnected(ComponentName className, IBinder service) { 425 // This is called when the connection with the service has been 426 // established, giving us the object we can use to 427 // interact with the service. We are communicating with the 428 // service using a Messenger, so here we get a client-side 429 // representation of that from the raw IBinder object. 430 mService = new Messenger(service); 431 mBound = true; 432 } 433 434 public void onServiceDisconnected(ComponentName className) { 435 // This is called when the connection with the service has been 436 // unexpectedly disconnected -- that is, its process crashed. 437 mService = null; 438 mBound = false; 439 } 440 }; 441 442 public void sayHello(View v) { 443 if (!mBound) return; 444 // Create and send a message to the service, using a supported 'what' value 445 Message msg = Message.obtain(null, MessengerService.MSG_SAY_HELLO, 0, 0); 446 try { 447 mService.send(msg); 448 } catch (RemoteException e) { 449 e.printStackTrace(); 450 } 451 } 452 453 @Override 454 protected void onCreate(Bundle savedInstanceState) { 455 super.onCreate(savedInstanceState); 456 setContentView(R.layout.main); 457 } 458 459 @Override 460 protected void onStart() { 461 super.onStart(); 462 // Bind to the service 463 bindService(new Intent(this, MessengerService.class), mConnection, 464 Context.BIND_AUTO_CREATE); 465 } 466 467 @Override 468 protected void onStop() { 469 super.onStop(); 470 // Unbind from the service 471 if (mBound) { 472 unbindService(mConnection); 473 mBound = false; 474 } 475 } 476} 477</pre> 478 479<p>Обратите внимание, что в этом примере не показано, как служба отвечает клиенту. Если требуется, 480чтобы служба реагировала, необходимо создать объект {@link android.os.Messenger} и в клиенте. Затем, 481когда клиент получает обратный вызов {@link android.content.ServiceConnection#onServiceConnected 482onServiceConnected()}, она отправляет в службу объект {@link android.os.Message}, который включает объект 483{@link android.os.Messenger} клиента в качестве значения параметра {@link android.os.Message#replyTo} 484метода {@link android.os.Messenger#send send()}.</p> 485 486<p>Пример организации двустороннего обмена сообщениями приведен в примерах кода <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerService.html">{@code 487MessengerService.java}</a> (служба) и <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/MessengerServiceActivities.html">{@code 488MessengerServiceActivities.java}</a> (клиент).</p> 489 490 491 492 493 494<h2 id="Binding">Привязка к службе</h2> 495 496<p>Для привязки к службе компоненты приложения (клиенты) могут использовать метод 497{@link android.content.Context#bindService bindService()}. После этого система Android 498вызывает метод {@link android.app.Service#onBind 499onBind()} службы, который возвращает объект {@link android.os.IBinder} для взаимодействия со службой.</p> 500 501<p>Привязка выполняется асинхронно. {@link android.content.Context#bindService 502bindService()} возвращается сразу же и <em>не</em> возвращает клиенту объект 503{@link android.os.IBinder}. Для получения объекта {@link android.os.IBinder} клиенту необходимо создать экземпляр {@link 504android.content.ServiceConnection} и передать его в метод {@link android.content.Context#bindService 505bindService()}. Интерфейс {@link android.content.ServiceConnection} включает метод обратного вызова, 506который система использует для того, чтобы выдать объект {@link android.os.IBinder}.</p> 507 508<p class="note"><strong>Примечание.</strong> Выполнить привязку к службе могут только операции, другие службы и поставщики контента 509— вы <strong>не можете</strong> самостоятельно выполнить привязку к службе из ресивера.</p> 510 511<p>Поэтому для привязки к службе из клиента необходимо выполнить указанные ниже действия. </p> 512<ol> 513 <li>Реализуйте интерфейс {@link android.content.ServiceConnection}. 514 <p>Ваша реализация должна переопределять два метода обратного вызова:</p> 515 <dl> 516 <dt>{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}</dt> 517 <dd>Система вызывает этот метод, чтобы выдать объект {@link android.os.IBinder}, возвращенный методом 518{@link android.app.Service#onBind onBind()}службы.</dd> 519 <dt>{@link android.content.ServiceConnection#onServiceDisconnected 520onServiceDisconnected()}</dt> 521 <dd>Система Android вызывает этот метод в случае непредвиденной потери 522подключения к службе, например при сбое в работе службы или в случае ее завершения. Этот метод <em>не</em> вызывается, когда клиент 523отменяет привязку.</dd> 524 </dl> 525 </li> 526 <li>Вызовите метод {@link 527android.content.Context#bindService bindService()}, передав в него реализацию интерфейса {@link 528android.content.ServiceConnection}. </li> 529 <li>Когда система вызывает ваш метод обратного вызова {@link android.content.ServiceConnection#onServiceConnected 530onServiceConnected()}, вы можете приступить к выполнению вызовов к службе с помощью 531методов, определенных интерфейсом.</li> 532 <li>Чтобы отключиться от службы, вызовите метод {@link 533android.content.Context#unbindService unbindService()}. 534 <p>В случае уничтожения клиента выполняется отмена его привязки к службе, однако вам всегда следует отменять 535привязку по завершении взаимодействия со службой или в случае приостановки операции, чтобы служба 536могла завершить свою работу, когда она не используется. (Более подробно подходящее время для привязки и ее отмены 537рассматриваются далее в этом документе).</p> 538 </li> 539</ol> 540 541<p>Ниже представлен пример фрагмента кода для подключения клиента к созданной выше службе путем 542<a href="#Binder">расширения класса Binder</a> — клиенту нужно лишь передать возвращенный объект 543{@link android.os.IBinder} в класс {@code LocalService} и запросить экземпляр {@code 544LocalService}:</p> 545 546<pre> 547LocalService mService; 548private ServiceConnection mConnection = new ServiceConnection() { 549 // Called when the connection with the service is established 550 public void onServiceConnected(ComponentName className, IBinder service) { 551 // Because we have bound to an explicit 552 // service that is running in our own process, we can 553 // cast its IBinder to a concrete class and directly access it. 554 LocalBinder binder = (LocalBinder) service; 555 mService = binder.getService(); 556 mBound = true; 557 } 558 559 // Called when the connection with the service disconnects unexpectedly 560 public void onServiceDisconnected(ComponentName className) { 561 Log.e(TAG, "onServiceDisconnected"); 562 mBound = false; 563 } 564}; 565</pre> 566 567<p>С помощью этого интерфейса {@link android.content.ServiceConnection} клиент может выполнить привязку к службе, передав ее в 568метод {@link android.content.Context#bindService bindService()}. Например:</p> 569 570<pre> 571Intent intent = new Intent(this, LocalService.class); 572bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 573</pre> 574 575<ul> 576 <li>Первый параметр в методе {@link android.content.Context#bindService bindService()} представляет собой объект 577{@link android.content.Intent}, который явным образом именует службу для привязки (хотя переход может быть 578и неявным).</li> 579<li>Второй параметр — это объект {@link android.content.ServiceConnection}.</li> 580<li>Третий параметр представляет собой флаг, указывающий параметры привязки. Обычно им является {@link 581android.content.Context#BIND_AUTO_CREATE}, создающий службу, если она уже не выполняется. 582Другие возможные значения: {@link android.content.Context#BIND_DEBUG_UNBIND} 583и {@link android.content.Context#BIND_NOT_FOREGROUND} или {@code 0}, если значение отсутствует.</li> 584</ul> 585 586 587<h3>Дополнительные примечания</h3> 588 589<p>Ниже представлены некоторые важные замечания о привязке к службе.</p> 590<ul> 591 <li>Всегда отлавливайте исключения {@link android.os.DeadObjectException}, которые выдаются 592при возникновении сбоя подключения. Это единственное исключение, которое выдается удаленными методами.</li> 593 <li>Для объектов всегда учитываются ссылки на них в процессах. </li> 594 <li>Обычно необходимо связать привязку и ее отмену во время 595сопоставления моментов подключения и отключения в жизненном цикле клиента. Например: 596 <ul> 597 <li>Если взаимодействие со службой требуется лишь в то время, когда операция отображается, привязку 598необходимо выполнить во время метода {@link android.app.Activity#onStart onStart()}, а отмену привязки — во время выполнения метода {@link 599android.app.Activity#onStop onStop()}.</li> 600 <li>Если необходимо, чтобы операция получала ответы даже в случае ее остановки во время работы в фоновом режиме, 601то привязку можно выполнить во время {@link android.app.Activity#onCreate onCreate()}, а отмену привязки 602 — во время выполнения {@link android.app.Activity#onDestroy onDestroy()}. Однако следует помнить, что такой способ подразумевает, 603что вашей операции необходимо использовать службу все время, пока она выполняется (даже если она выполняется в фоновом режиме). Поэтому, 604если служба находится в другом процессе, вы тем самым утяжеляете процесс, а это 605повышает вероятность того, что система завершит его.</li> 606 </ul> 607 <p class="note"><strong>Примечание.</strong> Обычно <strong>не</strong> следует выполнять привязку или отменять ее 608во время выполнения методов {@link android.app.Activity#onResume onResume()} и {@link 609android.app.Activity#onPause onPause()} вашей операции, поскольку такие обратные вызовы происходят при каждом переходе из одного состояния в другое, 610 а обработка данных, выполняемая при таких переходах, должна быть минимальной. Кроме того, если к одной и той же 611службе привязано несколько операций в вашем приложении, и имеется переход между 612двумя этими операциями, служба может быть уничтожена и создана повторно, поскольку текущая операция выполняет отмену привязки 613(во время приостановки) до того, как следующая служба выполнит привязку (во время возобновления). (Подробные сведения о согласовании жизненных циклов операций при таких переходах 614представлены в статье 615<a href="{@docRoot}guide/components/activities.html#CoordinatingActivities">Операции</a>.)</p> 616</ul> 617 618<p>Пример кода, в котором показан порядок привязки к службе, см. в статье, посвященной классу <a href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/app/RemoteService.html">{@code 619RemoteService.java}</a>, в <a href="{@docRoot}resources/samples/ApiDemos/index.html">ApiDemos</a>.</p> 620 621 622 623 624 625<h2 id="Lifecycle">Управление жизненным циклом привязанной службы</h2> 626 627<p>Когда выполняется отмена привязки службы ко всем клиентам, система Android уничтожает такую службу (если она не была запущена 628вместе с {@link android.app.Service#onStartCommand onStartCommand()}). В таком случае вам не нужно 629управлять жизненным циклом своей службы, если она исключительно привязанная служба 630— система Android управляет ей за вас на основании привязки службы к любым другим клиентам.</p> 631 632<p>Однако, если вы решите реализовать метод обратного вызова {@link android.app.Service#onStartCommand 633onStartCommand()}, вам необходимо явным образом остановить службу, поскольку в 634этом случае она считается <em>запущенной</em>. В таком случае служба выполняется до тех пор, пока 635сама не остановит свою работу с помощью метода {@link android.app.Service#stopSelf()} или до тех пор, пока другой компонент не вызовет метод {@link 636android.content.Context#stopService stopService()}, независимо от привязки службы к каким-либо 637клиентам.</p> 638 639<p>Кроме того, если ваша служба запущена и принимает привязку, то при вызове системой 640вашего метода {@link android.app.Service#onUnbind onUnbind()} вы также можете вернуть 641{@code true}, если желаете получить вызов к {@link android.app.Service#onRebind 642onRebind()} при следующей привязке к службе (вместо получения вызова к методу {@link 643android.app.Service#onBind onBind()}). Метод {@link android.app.Service#onRebind 644onRebind()} возвращает значение void, однако клиент по-прежнему получает объект {@link android.os.IBinder} в своем методе обратного вызова 645{@link android.content.ServiceConnection#onServiceConnected onServiceConnected()}. 646На рисунке 1 ниже иллюстрируется логика жизненного цикла такого рода.</p> 647 648 649<img src="{@docRoot}images/fundamentals/service_binding_tree_lifecycle.png" alt="" /> 650<p class="img-caption"><strong>Рисунок 1.</strong> Жизненный цикл запущенной службы, 651для которой выполняется привязка.</p> 652 653 654<p>Дополнительные сведения о жизненном цикле уже запущенной службы представлены в статье <a href="{@docRoot}guide/components/services.html#Lifecycle">Службы</a>.</p> 655 656 657 658 659