redL1ne
redL1ne

Reputation: 123

MediaPlayer.onPrepared() is not called

I use media player in service and activity with a button(play/stop stream).
I'm trying to do such a one thing:
start serice only once when activity starts, and than use UI part to operate with media player in service (start, stop streaming). I'm using for it Service Binder.
But when i click on button to start media player, it causes errors:

E/MediaPlayer: start called in state 1
E/MediaPlayer: error (-38, 0)

Than i added the flag isPrepared to onPrepared() and on play stream button click check the flag. Flag is always false. It seems that onPrepare() is not called or smth like that. Why? What's wrong?

UPDATED
Activity:

public class MainActivity extends AppCompatActivity {

String url = "http://62.80.190.246:8000/ProstoRadiO128";
Button mPlayPauseButton;
boolean musicPlaying = false;
Intent serviceIntent;
MyService mService;
boolean mBound = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initViews();
    initListeners();
}

@Override
protected void onStart() {
    super.onStart();
    serviceIntent = new Intent(this, MyService.class);
    serviceIntent.putExtra("url", url);
    bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE);
    startService(serviceIntent);
    musicPlaying = true;
    mPlayPauseButton.setBackgroundResource(R.drawable.pause);
    Log.d("", "mConnection: " + mConnection);
}

@Override
protected void onStop() {
    super.onStop();
    if (mBound) {
        unbindService(mConnection);
        mBound = false;
    }
}

private ServiceConnection mConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        MyService.MyServiceBinder binder = (MyService.MyServiceBinder) service;
        mService = binder.getService();
        mBound = true;
        Log.d("", "in onServiceConnected: mBound = " + mBound);
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {
        mBound = false;
    }
};


private void initViews() {
    mPlayPauseButton = (Button) findViewById(R.id.btn_play_pause);
    mPlayPauseButton.setBackgroundResource(R.drawable.play);
}

private void initListeners() {
    mPlayPauseButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            playPauseClick();
        }
    });
}

private void playPauseClick() {
    if (musicPlaying == false) { //mBound &&
        Log.d("", "mBound: " + mBound);
        mService.startStream();
        mPlayPauseButton.setBackgroundResource(R.drawable.pause);
        musicPlaying = true;
    }
    else if (musicPlaying == true) { //!mBound
        mService.stopStream();
        mPlayPauseButton.setBackgroundResource(R.drawable.play);
        musicPlaying = false;
    }
}
}

UPDATED Service:

public class MyService extends Service implements MediaPlayer.OnPreparedListener, MediaPlayer.OnCompletionListener{

String TAG = "PlayerService__Log";
String url;
MediaPlayer mediaPlayer;
private final IBinder mBinder = new MyServiceBinder();
boolean isPrepared;

public class MyServiceBinder extends Binder {
    MyService getService() {
        return MyService.this;
    }
}

@Override
public IBinder onBind(Intent intent) {
    return mBinder;
}

@Override
public void onCreate() {
    Log.v(TAG, "Creating Service");
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setOnPreparedListener(this);
    mediaPlayer.setOnCompletionListener(this);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

    Log.d(TAG, "onStartCommand");

    url = intent.getStringExtra("url");
    Log.d(TAG, "url: " + url);
    if (!mediaPlayer.isPlaying()) {
        try {
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setDataSource(url);
            mediaPlayer.prepareAsync();
        } catch (Exception e) {
            e.printStackTrace();
            Log.d(TAG, e.getClass().getName() + " " + e.getMessage());
        }
    }
    return START_STICKY;
}

@Override
public void onPrepared(MediaPlayer mp) {
    mp.start();
    Log.d(TAG, "media player prepared");
    isPrepared = true;
}

@Override
public void onCompletion(MediaPlayer mp) {
    Log.d(TAG, "onCompletion");
}

@Override
public void onDestroy() {
    super.onDestroy();
    if (mediaPlayer != null) {
        if (mediaPlayer.isPlaying()) {
            mediaPlayer.stop();
        }
        mediaPlayer.release();
        mediaPlayer = null;
    }
}

public void startStream() {
    if (!mediaPlayer.isPlaying() ) { //&& isPrepared == true
        mediaPlayer.start();
        Log.d(TAG, "media player started");
    }
    else {
        Log.d(TAG, "media player is not prepared");
        //isPrepared = false;
    }
}

public void stopStream() {
    if (mediaPlayer.isPlaying()) {
        mediaPlayer.stop();
        Log.d(TAG, "media player stoped");
    }
}
}

Upvotes: 1

Views: 2337

Answers (2)

weston
weston

Reputation: 54791

You forgot to start the service. Call:

startService(serviceIntent);

Please read this as you will need to stop the service too.

and for pausing, rather than stop, call:

mediaPlayer.pause();

Familiarise yourself with the state diagram and invalid states in the docs.

Upvotes: 1

sschrass
sschrass

Reputation: 7166

onPrepared() is called when the player is successfully prepared/initialised. But as the Error is indicating, something goes wrong during this phase and (probably) therfore onPrepared never gets called.

You could try to override onError, to get notified like this:

@Override
public boolean onError(MediaPlayer mediaPlayer, int what, int why) {
    Log.e(TAG, "onError");
    setPlayerState(PlayerState.ERROR);
    if (MediaPlayer.MEDIA_ERROR_UNKNOWN == what) {
        Log.d(TAG, "MEDIA_ERROR_UNKNOWN");
        if (MediaPlayer.MEDIA_ERROR_IO == why) {
            Log.e(TAG, "MEDIA_ERROR_IO");
            if (this.playbackPosition > 0) { //we could play this video in the past, but cannot resume. start all over again.
                Log.e(TAG, "Probably we requested a content range, but server didn't support that. (responded with 200), restarting!");
                this.playbackPosition = 0;
                start(this.playbackPosition);
            } else {
                callbacks.onUnrecoverableError(what, why);
            }
        }
        if (MediaPlayer.MEDIA_ERROR_MALFORMED == why) {
            Log.e(TAG, "MEDIA_ERROR_MALFORMED");
            callbacks.onUnrecoverableError(what, why);
        }
        if (MediaPlayer.MEDIA_ERROR_UNSUPPORTED == why) {
            Log.e(TAG, "MEDIA_ERROR_UNSUPPORTED");
            callbacks.onUnrecoverableError(what, why);
        }
        if (MediaPlayer.MEDIA_ERROR_TIMED_OUT == why) {
            Log.e(TAG, "MEDIA_ERROR_TIMED_OUT");
            callbacks.onUnrecoverableError(what, why);
        }
    } else if (MediaPlayer.MEDIA_ERROR_SERVER_DIED == what) {
        Log.e(TAG, "MEDIA_ERROR_SERVER_DIED");
        callbacks.onUnrecoverableError(what, why);
    }
    return true;
}

Upvotes: 1

Related Questions