BindService () devuelve false pero unbindService () necesita ser llamado?

Mi aplicación utiliza un servicio proporcionado por otra (de mis) aplicaciones. Estoy usando un servicio vinculado con un Messenger para acceder y comunicarse con él (y como es una aplicación diferente, también es un servicio remoto).

Cuando llamo a bindService con una intención correcta, y la llamada devuelve false (como se esperaba cuando el APK que proporciona el servicio no está a su alrededor), asumí de la documentación y el código de ejemplo, que no necesito unbind la ServiceConnection . Sin embargo, al hacerlo en mi dispositivo Galaxy Nexus (Jelly Bean), recibo el conocido mensaje ServiceConnectionLeaked al finalizar la Activity .

He recuperado esto haciendo

 if (!ctxt.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)) { try { ctxt.unbindService(serviceConnection); } catch (Throwable t) {} // Clean up return; } // Store serviceConnection for future use 

Soy curioso: ¿Acabo de extrañar algo en la documentación y se supone que funciona de esta manera? He añadido el try ... catch para asegurarse de que incluso si este comportamiento es de hecho diferente en otros dispositivos o versiones de Android mi aplicación no es (negativamente) afectados por ella.

Generalmente, ServiceConnection siempre es asignado y registrado por el framework, independientemente de si la llamada a bindService() devuelve true o false. Vea la implementación de bindService () en android.app.ContextImpl :

 public boolean bindService(Intent service, ServiceConnection conn, int flags, int userHandle) { IServiceConnection sd; if (conn == null) { throw new IllegalArgumentException("connection is null"); } if (mPackageInfo != null) { // A new ServiceDispatcher will be created and registered along with // ServiceConnection in LoadedApk.mService for your application context. sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), mMainThread.getHandler(), flags); } else { throw new RuntimeException("Not supported in system context"); } try { ... ... return res != 0; } catch (RemoteException e) { return false; } } 

Siempre debe desvincular el servicio cuando haya terminado con él, como sugiere la guía oficial de dev , como una buena forma de programación:

  • Para desconectarse del servicio, llame a unbindService ().

    Cuando se destruye su cliente, se desvinculará del servicio, pero siempre debe desvincularse cuando haya terminado de interactuar con el servicio o cuando su actividad se detiene para que el servicio pueda apagarse mientras no se está utilizando. (Los tiempos apropiados para unir y desenlazar se discuten más abajo.)

ServiceConnectionLeaked se levanta cuando el marco inicia la realización de una limpieza final (por ejemplo, cuando se cierra la aplicación) y se detecta que hay ServiceConnection no registrado y el framework intentará desvincularlo para usted. Vea la implementación de removeContextRegistrations () en android.app.LoadedApk :

 public void removeContextRegistrations(Context context, String who, String what) { final boolean reportRegistrationLeaks = StrictMode.vmRegistrationLeaksEnabled(); ... ... //Slog.i(TAG, "Receiver registrations: " + mReceivers); HashMap<ServiceConnection, LoadedApk.ServiceDispatcher> smap = mServices.remove(context); if (smap != null) { Iterator<LoadedApk.ServiceDispatcher> it = smap.values().iterator(); while (it.hasNext()) { LoadedApk.ServiceDispatcher sd = it.next(); ServiceConnectionLeaked leak = new ServiceConnectionLeaked( what + " " + who + " has leaked ServiceConnection " + sd.getServiceConnection() + " that was originally bound here"); leak.setStackTrace(sd.getLocation().getStackTrace()); Slog.e(ActivityThread.TAG, leak.getMessage(), leak); if (reportRegistrationLeaks) { StrictMode.onServiceConnectionLeaked(leak); } try { ActivityManagerNative.getDefault().unbindService( sd.getIServiceConnection()); } catch (RemoteException e) { // system crashed, nothing we can do } sd.doForget(); } } mUnboundServices.remove(context); //Slog.i(TAG, "Service registrations: " + mServices); } 
  • Servicio de Android matado
  • Mantener viva Servicio de Intención después de que la aplicación es asesinada
  • Servicio de reconocimiento continuo de voz de Android
  • Cómo mostrar el mini controlador en la parte inferior o controles de medios persistentes como spotify o Google música en la aplicación completa
  • OnTaskRemoved () no se llama en dispositivos HUAWEI y XIOMI
  • ¿Debería extender la clase Binder o usar un Messenger?
  • Android: ¿Cómo determinar si IntentService se está ejecutando?
  • Error de Android escribiendo datos de ubicación en la base de datos SQLite de la clase LocationListener
  • ¿Cómo actualizar SeekBar de MediaPlayer en funcionamiento?
  • Desactivar ocultar una presentación (pantalla secundaria)
  • Enviar datos al servidor desde el dispositivo Android cuando la aplicación llega al fondo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.