Когда мне следует использовать unbindService () и как правильно использовать его для отсоединения от удаленного сервиса, использующего интерфейс AIDL? - PullRequest
4 голосов
/ 11 июля 2011

Я пишу простой музыкальный проигрыватель, и я создал службу воспроизведения, которая реализует интерфейс AIDL для связи с клиентами, один - простой браузер дорожек, а другой - еще более простую активность проигрывателя. Служба управляет объектом MediaPlayer, в то время как эти два действия используют ServiceConnections для получения подключений к службе.

Это включено в методы onStart () обоих действий:

@Override
public void onStart()
{
  super.onStart();
  Intent i = new Intent(this, PureService.class);
  startService(i);
  bindService(i, mConnection, 0);
}

Я сделал это, чтобы служба не остановилась сразу после отмены привязки. Конечно, это на самом деле не было проблемой, потому что моя деятельность вообще отказывается от сервиса. Каждый раз, когда мое приложение получает unbindService в любом из этих действий, unbindService каждый раз без исключения генерирует IllegalArgumentException (хе-хе).

В методах onStop:

@Override
public void onStop()
{
  super.onStop();

  if (mBound) {
    try {
      unbindService(mConnection);
    } catch (java.lang.IllegalArgumentException e)
    {
      //Print to log or make toast that it failed
    }
  }
  mBound = false;
}

Что мне интересно, так это:

  • Должен ли я вызывать unbindService () в методе onStop ()? Или вообще?
  • Правильно ли я это называю?
  • Есть ли что-то особенное в том, как я запускаю / привязываю службу, о которой я должен знать?
  • Я что-то делаю совершенно, совершенно неправильно? Я новичок в программировании Android, так что об этом точно не может быть и речи.

Заранее спасибо.

РЕДАКТИРОВАТЬ: Вот переопределения ServiceConnection

public void onServiceConnected(ComponentName className, IBinder service) {
  mBound = true;
  mService = IPureService.Stub.asInterface(service);
}
public void onServiceDisconnected(ComponentName arg0) {
  mBound = false;
}

В активности игрока есть дополнительный код, но он не связан с самой привязкой.

Ответы [ 3 ]

4 голосов
/ 11 июля 2011

Во-первых, если вам действительно не нужно делать вызовы к этой службе между процессами (то есть из других .apks, или вы используете Android: процесс, чтобы по какой-то причине разделить свой собственный .apk на несколько процессов), затем яочень рекомендую просто отказаться от помощи.Это больше сложности без выгоды.«Пример локального сервиса» в документации по сервису показывает, как это сделать: http://developer.android.com/reference/android/app/Service.html

Во-вторых, выполнение связывания одновременно со стартом является ярким свидетельством некоторого основного недостатка в проекте.Запуск службы и привязка к службе семантически очень различаются, поэтому будут выполняться в разных местах на основе этой различной семантики.То есть, если и то, и другое вообще сделано ... на самом деле это необычная ситуация, когда вы используете как start, так и bind с одним и тем же сервисом.

В реализации класса сервиса для воспроизведения музыки, он будет использовать start, когда он активно выполняет воспроизведение (поэтому его процесс не будет убит системой, когда пользователь больше не будет активно взаимодействовать с пользовательским интерфейсом приложения).Запуск службы, когда пользователь входит в пользовательский интерфейс, может вызвать проблемы, поскольку теперь состояние запуска / остановки службы не определено четко - его можно запустить либо потому, что он выполняет воспроизведение, либо потому, что пользователь вошел впользовательский интерфейс приложения, и теперь, когда подходящее время, чтобы остановить его?Это будет хлопотно.

Теперь, когда нужно отменить привязку - вам просто нужно убедиться, что вы всегда сопоставляете unbindService () с предыдущим bindService ().Из ваших фрагментов кода похоже, что вы делаете это, но есть странные вещи, такие как mBound, который никогда не устанавливается.На самом деле, если вы последовательно связываете в onStart () и отменяете привязку в onStop (), вам никогда не нужно иметь mBound, чтобы решить, отменять ли связывание, потому что onStop () всегда вызывается после onStart ().

Так что с кодом, который вы даете здесь, не похоже, что есть проблема.Если вы получаете исключения, тем не менее, очевидно, что это может быть в другом месте в вашем приложении.Чтобы помочь сузить проблему, вы можете использовать этот флаг при вызове bindService () для получения дополнительной информации в журнале при возникновении сбоя: http://developer.android.com/reference/android/content/Context.html#BIND_DEBUG_UNBIND

0 голосов
/ 14 марта 2012

У меня тоже была странная ошибка. Затем я попытался выполнить привязку к сервису в onResume () вместо onStart () в Activity, и вуаля, больше никаких исключений! Я все еще немного не понимаю, почему это работает. Если бы кто-то мог объяснить, я был бы одним счастливым кодером. :)

0 голосов
/ 11 июля 2011

Пара баллов:

  1. Возврат START_STICKY в onStartCommand , если вы хотите, чтобы ваша служба проживала дольше, чем связанные действия.
  2. unbindService () в onStop хорошо: это то, где я вызываю его в нескольких приложениях, и я никогда не видел этой конкретной ошибки. Я ожидаю, что у вас есть другая проблема с ServiceConnection: покажите код для вашего mConnection объекта, и мы, возможно, сможем выяснить, что с ним не так.
...