2012-09-05 19 views
23

Próbuję zrozumieć ograniczone usługi. Poniżej mój przykładowy program, w którym próbuję podążać za http://developer.android.com/guide/components/bound-services.html. Usługa działa tak długo, jak mogę odtwarzać, wstrzymywać i zatrzymywać dźwięk, ale kiedy przełączam się do innej aplikacji, otrzymuję następujący błąd Service not registered.usługi android - błąd: usługa niezarejestrowana

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) 

Ponieważ kodowanie wydaje się ściśle podążać za dokumentacją, nie mam pojęcia, gdzie coś pójdzie nie tak. Uruchomić tę aplikację z minSdk poziomie 8. Błąd dzieje się w MainActivity.onStop na linii

mService.unbindService(mConnection); 

Wszelkie sugestie, aby rozwiązać ten byłby wielki.

Dzięki

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; 
    } 
}; 

} 

i

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

czy wyświetla błąd podczas działania mediaplayer, a następnie zmienia główną aktywność? – waqaslam

+0

w obu przypadkach, działa lub nie działa ... – dorjeduck

+0

możesz zrobić logowanie ** onServiceDisconnected ** i sprawdzić, czy jest on przypadkowo podniesiony ... – waqaslam

Odpowiedz

47

miał podobny problem, ale przyjął odpowiedź nie była rozwiązaniem dla mnie. Na szczęście jeden z komentarzy dał mi odpowiedź:

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.

Dzięki @Waqas znalazłem błąd: Byłem uaktualniające flagę boolean binded tylko wewnątrz onServiceConnected() i onServiceDisconnected(). Teraz dodałem "binded = false" za każdym razem, gdy dzwonię pod numer unbindService(), a problem już minął. To jest to, nie polegaj na onServiceDisconnected

+3

To jest poprawna odpowiedź !! ++++ – ComputerEngineer88

+1

Dzięki! Byłem pod tym samym założeniem, że usługa onServiceDisconnected została wywołana w usłudze unbindService. Umieściłem tam cały mój kod zatrzymania usługi, teraz przeniosłem go do zdarzenia kliknięcia przycisku. – EvilTak

16

Ach, jeden z tych dni

mService.unbindService(mConnection); 

to oczywiście nonsens, nazywając unbind w niewłaściwym kontekście. Powinno być

unbindService(mConnection); 

Dodatkowy błąd w zamieszczonych kodowania jest brakujących

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

    releaseMediaPlayer(); 

    return false; 
} 
+2

Pomógł mi. Zrobiłem to samo głupie. –

+0

Dziękuję, pomógł mi również. Oczywisty błąd, ale nie jest oczywiste, aby debugować IMHO. –

+1

Trochę mi to zajęło, żeby się domyślić, dlaczego to nie zadziałało. Jeśli 'unbindService' jest wywoływana w' Fragment', 'getActivity().' Musi znajdować się z przodu, tak aby było 'getActivity(). UnbindService (mConnection)'. – craned

2

Być może trzeba będzie upewnić się, że mService nie ma wartości null. Poniższy wiersz dał mi „Usługa nie zarejestrowany” error:

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

To było bardzo mylące, ponieważ zarówno mContext i mServiceConn nie były puste.

Ten poprawiony:

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

+0

To nie pomaga (kod IabHelper) – fillobotto

0

Moja MediaPlayer zatrzyma gdy zabiłem aplikację, ale 5 minut warstwa lub mniej byłoby zacząć z powrotem znowu wszystko na własną rękę.

Aby to naprawić, oprócz odpowiedzi @ dorjeducka musiałem również zadzwonić pod numer mediaPlayer.stop(), zanim zadzwonię pod numer mediaPlayer.release().

6

Jako sidenote, ponieważ żadna z innych odpowiedzi nie pomogła, okazało się, że mój błąd był inny niż Context dla wiązania i rozpinania.Moje powiązanie pochodziło z kontekstu aplikacji, ale moje odłączenie pochodziło z kontekstu działania.

Aby naprawić ten błąd, zadbał, aby korzystać z tego samego kontekstu bindService() i unbindService().

Powiązane problemy