Arnaldo
Arnaldo

Reputation: 683

(Android Media Player) Why can't use prepareAsync() instead of prepre() with AsyncTask

I am really a newbie in this (and also with the English ). Lately , I spend reading (or at least try) about Android Media Player.

This time, I found this with Google: http://dev-space.googlecode.com/svn/trunk/StreamPlayer/src/com/pozheg/

I tried to play a mp3 file (http://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3) with the original source code and it worked great. But when I use prepareAsync() with my stream, the mMediaPlayer passes to release().

I'm trying to play an audio streaming using prepareAsync() instead of prepare() AsyncTask

The question is: why can not?

I know my question may be very stupid , but I want to learn with you .

In this way:

package com.myaudioservice.app;

import android.app.Service;
import android.content.Intent;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.AsyncTask;
import android.os.Binder;
import android.os.IBinder;

/**
 * Service to serv MediaPlayer in background
 *
 * @author Eugeny Pozharsky
 */
public class PlayerService extends Service {
    private final IBinder mBinder = new LocalBinder();
    private MediaPlayer mediaPlayer;
    private PlayerCallback callback;

    public class LocalBinder extends Binder {
        PlayerService getService() {
            return PlayerService.this;
        }
    }

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

    /**
     * Kill MediaPlayer to release resources
     */
    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mediaPlayer != null) {
            stop();
            mediaPlayer.release();
        }
    }

    /**
     * Starts playing stream.
     * Note that we just start media player and do not obtain real URL of the stream.
     * So, URL that will be redirected by server will not work. To make such URLs works, adding
     * algorithm to obtain the real URL (f.e., create HttpConnection, connect to the server and
     * get real URL from connection).
     *
     * @param url String with URL of a server to connect
     */
    public void start(String url) {
        if (mediaPlayer == null) {
            mediaPlayer = new MediaPlayer();
        }
        if (isPlaying()) {
            mediaPlayer.stop();
            mediaPlayer.reset();
        }
        new Player().execute(url);
    }

    /**
     * Stops playing of the stream.
     */
    public void stop() {
        // stopping MediaPlayer in separate thread because it can take a time
        new Thread(new Runnable() {
            @Override
            public void run() {
                if (mediaPlayer != null) {
                    if (mediaPlayer.isPlaying()) {
                        mediaPlayer.stop();
                    }
                    mediaPlayer.release();
                    mediaPlayer = null;
                }
            }
        }).start();
        if (callback != null) {
            callback.onStopped();
        }
    }

    /**
     * Is stream playing?
     *
     * @return true or false
     */
    public Boolean isPlaying() {
        return mediaPlayer != null && mediaPlayer.isPlaying();
    }

    public void setCallback(PlayerCallback callback) {
        this.callback = callback;
    }

    /**
     * Background task to start MediaPlayer. It is used because starting playing of remote stream may
     * take long time and we must not block UI thread.
     * Also, this approach allows to cancel starting process (not implemented in current version)
     */
    private class Player extends AsyncTask<String, Void, Void> {

        /**
         * This function called in UI thread and we callback to activity to update UI elements
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if (callback != null) {
                callback.onPreStart();
            }
        }

        /**
         * This function called in UI thread and we callback to activity to update UI elements
         */
        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            if (mediaPlayer == null || !mediaPlayer.isPlaying()) {
                // Start MediaPlayer fail.
                if (callback != null) {
                    callback.onStartFailed();
                }
            } else {
                if (callback != null) {
                    callback.onStarted();
                }
            }
        }

        /**
         * This function called from separate thread and we do long-time operation in it
         *
         * @param strings params
         * @return null
         */
        @Override
        protected Void doInBackground(String... strings) {
            mediaPlayer = new MediaPlayer();
            try {
                mediaPlayer.setDataSource(strings[0]);
                mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                mediaPlayer.prepareAsync();
                mediaPlayer.start();
            } catch (Exception e) {
                if (mediaPlayer != null) {
                    mediaPlayer.release();
                }
                mediaPlayer = null;
            }
            return null;
        }
    }
}

Upvotes: 0

Views: 1869

Answers (1)

Kamil W
Kamil W

Reputation: 146

You must wait until stream is prepared before you call start(). When you want to use prepareAsync() you should set OnPrepareListener to media player and call start() form it.

mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.start();
        }
    });
mediaPlayer.prepareAsync();

Upvotes: 1

Related Questions