Actividad ha filtrado ServiceConnection @ 438030a8 que originalmente estaba enlazado aquí

10 minutos de lectura

avatar de usuario
catdotgif

Estoy trabajando en mi primera aplicación para Android. Tengo tres actividades en mi aplicación y el usuario cambia de un lado a otro con bastante frecuencia. También tengo un servicio remoto, que maneja una conexión telnet. Las aplicaciones deben vincularse a este servicio para enviar/recibir mensajes de telnet.

Editar

Gracias BDLS por su respuesta informativa. He reescrito mi código a la luz de su aclaración sobre la diferencia entre usar bindService() como una función independiente o después startService()y ahora solo recibo el mensaje de error de fuga de forma intermitente cuando uso el botón Atrás para alternar entre actividades.

Mi actividad de conexión tiene la siguiente onCreate() y onDestroy():

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /*
     * Initialize the ServiceConnection.  Note that this is the only place startService() is run.
     * It is also the only time bindService is run without dependency on connectStatus.
     */
    conn = new TelnetServiceConnection();
    //start the service which handles telnet
    Intent i = new Intent();
    i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
    startService(i);
    //bind to the service
    bindService(i, conn, 0);

    setContentView(R.layout.connect);
    setupConnectUI();

}//end OnCreate()

@Override
protected void onDestroy() {
    super.onDestroy();

    //unbind the service and null it out
    if (conn != null) {
        unbindService(conn);
        conn = null;
        }

    if(connectStatus == 0) {
        //stop the service
        Intent i = new Intent();
        i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
        stopService(i);
        Log.d("LightfactoryRemote", "Connect onDestroy() attempted to stop service");
        }

    Log.d("LightfactoryRemote", "Connect onDestroy()");
    }//end onDestroy()

Entonces, el servicio se inicia cuando se inicia la actividad y se detiene cuando la actividad se destruye si no se realizó una conexión telnet exitosa (connectStatus == 0). Las otras actividades se unen al servicio solo si se realizó una conexión exitosa (connectStatus == 1, guardado en preferencias compartidas). Aquí está su onResume() y onDestroy():

@Override
protected void onResume() {
    super.onResume();

    //retrieve the shared preferences file, and grab the connectionStatus out of it.
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_WORLD_WRITEABLE);
    connectStatus = settings.getInt("connectStatus", 0);

    Log.d("LightfactoryRemote", "Focus onResume with " + connectStatus);

    //if a telnet connection is active, start the service and bind to it
    if (connectStatus == 1) {
        conn = new TelnetServiceConnection();
        Intent i = new Intent();
        i.setClassName("com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService");
        bindService(i, conn, 0);
        //TODO write restore texview code
        }//end if
    }//end onResume

@Override
protected void onDestroy() {
    super.onDestroy();
    //unbind the service and null it out.
    if (conn != null) {
        Log.d("LightfactoryRemote", "Focus onDestroy() attempted to unbind service");
        unbindService(conn);
        conn = null;
        }
    Log.d("LightfactoryRemote", "Focus onDestroy()");
    }//end onDestroy()

Entonces el enlace ocurre en onResume() para que recoja el estado cambiado de la actividad de conexión, y en el onDestroy() función es independiente, si es necesario.

Finalizar edición

Pero sigo recibiendo el mensaje de error de pérdida de memoria “La actividad ha filtrado ServiceConnection @ 438030a8 que originalmente estaba vinculado aquí” de forma intermitente al cambiar de actividad. ¿Qué estoy haciendo mal?

Gracias de antemano por cualquier consejo o sugerencia!!!

A continuación se muestra el mensaje de error completo (del código revisado):

01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onStop()
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy() attempted to unbind service
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy()
01-02 22:04:26.672: ERROR/ActivityThread(2024): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:927)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:822)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ApplicationContext.bindService(ApplicationContext.java:842)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.content.ContextWrapper.bindService(ContextWrapper.java:319)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.Activity.performResume(Activity.java:3559)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2838)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2866)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.access$2100(ActivityThread.java:116)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.os.Looper.loop(Looper.java:123)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.main(ActivityThread.java:4203)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at java.lang.reflect.Method.invokeNative(Native Method)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at java.lang.reflect.Method.invoke(Method.java:521)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at dalvik.system.NativeStart.main(Native Method)
01-02 22:04:26.692: WARN/ActivityManager(558): Unbind failed: could not find connection for android.os.BinderProxy@43c509a8

edito el 2do

Gracias una vez más bdls por sus sugerencias. Hice lo que me sugeriste y agregué un onUnBind() anular el servicio. onUnBind() en realidad, solo se activa cuando todos los clientes se desconectan del servicio, pero cuando presioné el botón de inicio, se ejecutó y luego apareció el mensaje de error. Esto no tiene sentido para mí, ya que todos los clientes se han desvinculado del servicio, entonces, ¿cómo podría el que fue destruido filtrar una conexión de servicio? Échale un vistazo:

01-03 19:38:30.837: DEBUG/LightfactoryRemote(1118): Focus onPause()1
01-03 19:38:31.577: WARN/IInputConnectionWrapper(1118): showStatusIcon on inactive InputConnection
01-03 19:38:31.587: DEBUG/LightfactoryRemote(1118): Focus onStop()
01-03 19:38:31.600: DEBUG/LightfactoryRemote(1118): Focus onDestroy() attempted to unbind service
01-03 19:38:31.607: DEBUG/LightfactoryRemote(1118): Focus onDestroy()
01-03 19:38:31.677: DEBUG/LightfactoryRemote(1125): TelnetService onUnBind()
01-03 19:38:31.727: ERROR/ActivityThread(1118): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:886)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:781)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ApplicationContext.bindService(ApplicationContext.java:820)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.content.ContextWrapper.bindService(ContextWrapper.java:307)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.Activity.performResume(Activity.java:3530)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2619)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2647)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2287)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.access$1800(ActivityThread.java:112)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.os.Looper.loop(Looper.java:123)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.main(ActivityThread.java:3948)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at java.lang.reflect.Method.invokeNative(Native Method)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at java.lang.reflect.Method.invoke(Method.java:521)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at dalvik.system.NativeStart.main(Native Method)
01-03 19:38:31.777: WARN/ActivityManager(564): Unbind failed: could not find connection for android.os.BinderProxy@4370f8a8

Pensé que podría ser algo como lo que dijiste, donde el enlace al servicio no está completo cuando unbindService() se llama, sin embargo, intenté llamar a un método en el servicio mientras retrocedía en cada actividad para verificar que el enlace estuviera completo, y todo salió bien.

En general, este comportamiento no parece estar relacionado con el tiempo que permanezco en cada actividad. Sin embargo, una vez que la primera actividad pierde su conexión de servicio, todos hacen lo mismo que yo después de eso.

Otra cosa, si enciendo “Destruir actividades inmediatamente” en Dev Tools, evita este error.

¿Algunas ideas?

  • ¿Puedes agregar el código LightfactoryRemote.onCreate()? (com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onCreate(LightfactoryRemote.java:97))

    – tbruyelle

    3 de enero de 2010 a las 0:13

avatar de usuario
bdls

No ha proporcionado nada de su código de LightFactoryRemotepor lo que esto es solo una suposición, pero parece el tipo de problema que vería si estuviera usando el bindService método por sí mismo.

Para garantizar que un servicio se mantenga en ejecución, incluso después de que la actividad que lo inició haya tenido su onDestroy método llamado, primero debe usar startService.

Los documentos de Android para Empieza el servicio estado:

El uso de startService() anula la duración predeterminada del servicio que administra bindService(Intent, ServiceConnection, int): requiere que el servicio siga ejecutándose hasta que se llame a stopService(Intent), independientemente de si hay clientes conectados a él.

mientras que para enlazarServicio:

El servicio se considerará requerido por el sistema solo mientras exista el contexto de llamada. Por ejemplo, si este contexto es una actividad que se detiene, no se requerirá que el servicio continúe ejecutándose hasta que se reanude la actividad.


Entonces, lo que sucedió es que la actividad que vinculó (y, por lo tanto, inició) el servicio, se detuvo y, por lo tanto, el sistema cree que el servicio ya no es necesario y causa ese error (y luego probablemente detiene el servicio).


Ejemplo

En este ejemplo, el servicio debe seguir ejecutándose independientemente de si la actividad de llamadas se está ejecutando.

ComponentName myService = startService(new Intent(this, myClass.class));
bindService(new Intent(this, myClass.class), myServiceConn, BIND_AUTO_CREATE);

La primera línea inicia el servicio y la segunda lo vincula a la actividad.

  • Comienzo el servicio usando START_STICKY y también lo inicia la intención de arranque. Si llamo a StartService, crea otra instancia del servicio y no quiero que se ejecuten 2 servicios al mismo tiempo. ¿Cómo puedo corregir el error en este caso?

    – opc0de

    10 de octubre de 2012 a las 6:44

  • @opc0de, no, no está creando otro servicio cuando llama a startService() dos veces. Los servicios son lógicamente únicos por naturaleza. No importa cuántas veces lo inicie, solo se ejecuta un servicio.

    – mahkie

    14 de marzo de 2013 a las 1:06

  • ¿Cuál es la solución para continuar el servicio en segundo plano para el reproductor de música?

    –Anand Savjani

    25 de noviembre de 2016 a las 10:01

avatar de usuario
Mostafá Rostami

Puedes usar:

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

    if (mServiceConn != null) {
        unbindService(mServiceConn);
    }
}

  • Excelente. Eso es lo que es.

    – Seltsam

    5 abr 2020 a las 20:14

te unes onResume pero desatar en onDestroy. Deberías hacer el desvinculado en onPause en su lugar, de modo que siempre haya pares coincidentes de llamadas enlazar/desenlazar. Sus errores intermitentes serán donde su actividad se detiene pero no se destruye, y luego se reanuda nuevamente.

Solo debe desvincular el servicio en onDestroy(). Entonces, la advertencia irá.

Ver aquí.

Como intenta explicar el documento de actividad, hay tres grupos principales de vinculación/desvinculación que usará: onCreate() y onDestroy(), onStart() y onStop(), y onResume() y onPause().

avatar de usuario
bdls

Mencionas que el usuario cambia entre actividades bastante rápido. ¿Podría ser que estás llamando? unbindService antes de que se haya establecido la conexión de servicio? Esto puede tener el efecto de no desvincularse y luego filtrar el enlace.

No estoy del todo seguro de cómo podrías manejar esto… Tal vez cuando onServiceConnected se llama podrías llamar unbindService si onDestroy ya ha sido llamado. Aunque no estoy seguro de si eso funcionará.


Si aún no lo ha hecho, puede agregar un método onUnbind a su servicio. De esa manera, puede ver exactamente cuándo sus clases se desvinculan de él, y podría ayudar con la depuración.

@Override
public boolean onUnbind(Intent intent) {
    Log.d(this.getClass().getName(), "UNBIND");
    return true;
}

avatar de usuario
Ashwini Shahapurkar

Intente usar unbindService() en OnUserLeaveHint(). Previene el escenario filtrado de ServiceConnection y otras excepciones.
Lo usé en mi código y funciona bien.

avatar de usuario
صلي علي محمد Atef Farouk

este error ocurre cuando va a vincular un servicio acotado. entonces, sol debería ser :-

  1. en la conexión de servicio agregue serviceBound como se muestra a continuación:

    private final ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // your work here.
    
        serviceBound = true;
    
    }
    
    @Override
    public void onServiceDisconnected(ComponentName name) {
    
        serviceBound = false;
    }
    

    };

  2. desvincular el servicio onDestroy

        if (serviceBound) {
            unbindService(serviceConnection);
        }
    

¿Ha sido útil esta solución?