2012-09-05 17 views
23

Estoy tratando de entender los servicios limitados. Debajo de mi programa de ejemplo en el que trato de seguir http://developer.android.com/guide/components/bound-services.html. El servicio funciona tanto como puedo reproducir, pausar y detener el audio, pero cuando cambio a otra aplicación recibo el siguiente error de servicio no registrado.android services - error: service not registered

java.lang.RuntimeException: Unable to stop activity {com.example.dd_services_audio_01/com.example.dd_services_audio_01.MainActivity}: java.lang.IllegalArgumentException: Service not registered: [email protected] 
09-05 14:04:32.625: E/AndroidRuntime(5810):  at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:2451) 
09-05 14:04:32.625: E/AndroidRuntime(5810):  at android.app.ActivityThread.handleStopActivity(ActivityThread.java:2496) 

Como la codificación parece seguir de cerca el ejemplo de la documentación, no tengo ni idea de dónde van las cosas mal. Corro esta aplicación con el nivel minSdk 8. El error ocurre en MainActivity.onStop en la línea de

mService.unbindService(mConnection); 

Cualquier sugerencia para resolver esto sería grande.

Gracias

martin

package com.example.dd_services_audio_01; 

import android.app.Activity; 
import android.content.ComponentName; 
import android.content.Context; 
import android.content.Intent; 
import android.content.ServiceConnection; 
import android.os.Bundle; 
import android.os.Environment; 
import android.os.IBinder; 
import android.util.Log; 
import android.view.Menu; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 

import com.example.dd_services_audio_01.AudioPlayerService.AudioPlayerBinder; 

public class MainActivity extends Activity { 

private final String TAG = "MainActivity"; 

AudioPlayerService mService; 
boolean mBound = false; 

Button mPlay, mPause, mStop; 

String audioFile = Environment.getExternalStorageDirectory() 
     + "/justdzongsar/DJKR_AboutToGetIt.mp3"; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    Log.d(TAG,"onCreate"); 
    setContentView(R.layout.activity_main); 

    mPlay = (Button) findViewById(R.id.buttonPlay); 
    mPause = (Button) findViewById(R.id.buttonPause); 
    mStop = (Button) findViewById(R.id.buttonStop); 

    mPlay.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) { 
      mService.play(audioFile); 
     } 
    }); 

    mPause.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) { 
      mService.pause(); 
     } 
    }); 

    mStop.setOnClickListener(new OnClickListener() { 
     public void onClick(View v) { 
      mService.stop(); 
     } 
    }); 

} 

@Override 
public boolean onCreateOptionsMenu(Menu menu) { 
    getMenuInflater().inflate(R.menu.activity_main, menu); 
    return true; 
} 

@Override 
protected void onStart() { 
    super.onStart(); 
    // Bind to LocalService 
    Intent intent = new Intent(this, AudioPlayerService.class); 
    bindService(intent, mConnection, Context.BIND_AUTO_CREATE); 


} 

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

    if (mBound) { 
     mService.unbindService(mConnection); 
     mBound=false; 
    } 
} 

/** Defines callbacks for service binding, passed to bindService() */ 
private ServiceConnection mConnection = new ServiceConnection() { 

    @Override 
    public void onServiceConnected(ComponentName className, IBinder service) { 
     // We've bound to LocalService, cast the IBinder and get 
     // LocalService instance 
     AudioPlayerBinder binder = (AudioPlayerBinder) service; 
     mService = binder.getService(); 
     mBound = true; 
    } 

    @Override 
    public void onServiceDisconnected(ComponentName arg0) { 
     mService = null; 
     mBound = false; 
    } 
}; 

} 

y

package com.example.dd_services_audio_01; 

import java.io.IOException; 

import android.app.Service; 
import android.content.Intent; 
import android.media.MediaPlayer; 
import android.media.MediaPlayer.OnCompletionListener; 
import android.media.MediaPlayer.OnPreparedListener; 
import android.os.Binder; 
import android.os.IBinder; 
import android.util.Log; 

public class AudioPlayerService extends Service implements OnPreparedListener, 
    OnCompletionListener { 

private final String TAG = "AudioPlayerService"; 

private final IBinder mBinder = new AudioPlayerBinder(); 

private MediaPlayer mMediaPlayer; 

private String currentDataSource; 

public class AudioPlayerBinder extends Binder { 
    public AudioPlayerService getService() { 
     Log.v(TAG, "AudioPlayerBinder: getService() called"); 
     return AudioPlayerService.this; 
    } 
} 

@Override 
public IBinder onBind(Intent intent) { 
    // TODO Auto-generated method stub 
    return mBinder; 
} 

@Override 
public boolean onUnbind(Intent intent) { 
    // All clients have unbound with unbindService() 
    return false; 
} 

@Override 
public void onStart(Intent intent, int startId) { 
    Log.i(TAG, 
      "AudioPlayerService: onStart() called, instance=" 
        + this.hashCode()); 
} 

@Override 
public void onDestroy() { 
    Log.i(TAG, "AudioPlayerService: onDestroy() called"); 
    releaseMediaPlayer(); 
} 

// ----- 

public void play(String audioFile) { 
    Log.d(TAG, "audio play called with file " + audioFile); 
    if (mMediaPlayer != null && audioFile.compareTo(currentDataSource) == 0) { 
     if (mMediaPlayer.isPlaying() == true) { 
      return; 
     } 
     mMediaPlayer.start(); 

     return; 
    } 
    releaseMediaPlayer(); 

    try { 

     mMediaPlayer = new MediaPlayer(); 
     mMediaPlayer.setDataSource(audioFile); 


     mMediaPlayer.setOnPreparedListener(this); 
     mMediaPlayer.setOnCompletionListener(this); 
     currentDataSource = audioFile; 

        mMediaPlayer.prepareAsync(); 


    } catch (IOException ioe) { 
     Log.e(TAG, "error trying to play " + audioFile, ioe); 
    } 

} 

public void pause() { 

    Log.d(TAG, "audio pause"); 
    if (mMediaPlayer != null && mMediaPlayer.isPlaying()) { 
     mMediaPlayer.pause(); 
    } 
} 

public void seek(int timeInMillis) { 
    if (mMediaPlayer != null) { 
     mMediaPlayer.seekTo(timeInMillis); 
    } 
} 

public int elapsed() { 
    if (mMediaPlayer == null) { 
     return 0; 
    } 
    return mMediaPlayer.getCurrentPosition(); 
} 

public void stop() { 
    Log.d(TAG, "audio stop"); 
    releaseMediaPlayer(); 
} 

// -- 

private void releaseMediaPlayer() { 
    if (mMediaPlayer == null) { 
     return; 
    } 

    if (mMediaPlayer.isPlaying()) { 
     mMediaPlayer.stop(); 
    } 
    mMediaPlayer.release(); 
    mMediaPlayer = null; 
} 

@Override 
public void onCompletion(MediaPlayer arg0) { 
    // TODO Auto-generated method stub 
    releaseMediaPlayer(); 
} 

@Override 
public void onPrepared(MediaPlayer mp) { 
    if (mp != null) { 
     mp.start(); 
    } 

    // TODO Auto-generated method stub 

} 

} 
+0

¿Se produce un error cuando el reproductor de medios se está ejecutando y luego cambia su actividad principal? – waqaslam

+0

en ambos casos, ejecutándose o no ... – dorjeduck

+0

puede hacer un inicio de sesión en ** onServiceDisconnected ** y ver si se produce accidentalmente ... – waqaslam

Respuesta

47

tenido un problema similar, pero la respuesta no fue aceptada la solución para mí. Por suerte uno de los comentarios me dio la respuesta:

onServiceDisconnected is not supposed to be raised when you unbind your service, so don't rely on it. It is supposed to inform you in case the connection between your Service and ServiceConnection is dropped.

Gracias a @Waqas he encontrado el error: yo estaba actualizando la bandera boolean binded sólo dentro onServiceConnected() y onServiceDisconnected(). Ahora agregué "binded = false" cada vez que llamo al unbindService() y el problema desapareció. Eso es todo, no confíe en enServicioDisconnected

+3

¡Esta es la respuesta correcta! ++++ – ComputerEngineer88

+1

¡Gracias! Estaba bajo la misma suposición de que onServiceDisconnected fue llamado en unbindService. Puse todo mi código de detención de servicio allí, ahora lo he movido al evento de clic de botón. – EvilTak

16

Ah, uno de estos días

mService.unbindService(mConnection); 

obviamente sin sentido, llamando a desatar en el contexto equivocado. Debe ser

unbindService(mConnection); 

error adicional en la codificación publicado es la falta de

@Override 
public boolean onUnbind(Intent intent) { 
    // All clients have unbound with unbindService() 

    releaseMediaPlayer(); 

    return false; 
} 
+2

me ayudó. Hice la misma estupidez. –

+0

Gracias, me ayudó también. Error obvio, pero no es obvio para depurar en mi humilde opinión. –

+1

Me llevó un poco descubrir por qué esto no funcionaba. Si se llama 'unbindService' dentro de un' Fragment', 'getActivity() .' debe estar al frente, de modo que sea' getActivity(). UnbindService (mConnection) '. – craned

2

Es posible que deba asegurarse de que mService no sea nulo. La siguiente línea me dio el "Servicio no registrada" error:

if (mContext != null) mContext.unbindService(mServiceConn);

esto era muy confuso porque tanto mContext y mServiceConn no eran nulas.

que esto esté arreglado que:

if (mContext != null && mService != null) mContext.unbindService(mServiceConn);

+0

Esto no ayuda (código de IabHelper) – fillobotto

0

Mi capa MediaPlayer pararía cuando maté a la aplicación, pero a 5 minutos o menos que comenzaría de nuevo otra vez por su propia cuenta.

Para solucionar esto, además de la respuesta de @ dorjeduck, también tuve que llamar al mediaPlayer.stop() antes de llamar al mediaPlayer.release().

6

Como nota al margen, ya que ninguna de las otras respuestas me ayudó, encontré que mi error estaba usando un Context diferente para vincular y desvincular.Mi enlace era del contexto de la Aplicación, pero mi desvinculación fue del contexto de la Actividad.

Para arreglar el error, me aseguré de usar el mismo contexto para bindService() y unbindService().