Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prepareAsync() doesn't work #40

Open
anonym24 opened this issue Apr 29, 2017 · 16 comments
Open

prepareAsync() doesn't work #40

anonym24 opened this issue Apr 29, 2017 · 16 comments

Comments

@anonym24
Copy link

anonym24 commented Apr 29, 2017

I created a hybrid player in my service.
When I do this:

       mMediaPlayer.reset();
       try {
            mMediaPlayer.setDataSource(source);
            mMediaPlayer.prepareAsync();
       } catch (IOException e) {
            Log.i(TAG, "mMediaPlayer setDataSource e: " + e);
       }

        ....

       @Override
       public boolean onError(IBasicMediaPlayer mp, int what, int extra) {
           Log.i(TAG, "MediaPlayer: onError " + " " + what + " " + extra);
           return false;
       }

It just instantly calls onError & onCompletion and tries to play the next song, fails again with the same error and so on

04-29 20:13:56.809 26389-26389/com.android.testpalyer E/OpenSLMediaPlayer: An error occurred in getCurrentPosition()
04-29 20:13:56.815 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError  -38 0
04-29 20:13:56.815 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onCompletion
04-29 20:13:56.890 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError  -38 0
04-29 20:13:56.890 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onCompletion
04-29 20:13:56.977 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError  -38 0
04-29 20:13:56.979 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onCompletion
04-29 20:13:57.059 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError  -38 0
04-29 20:13:57.060 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onCompletion
04-29 20:13:57.157 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError  -38 0
04-29 20:13:57.159 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onCompletion
@anonym24
Copy link
Author

anonym24 commented Apr 29, 2017

And when I run mMediaPlayer.prepareAsync(); in new Thread, then everything is ok, but I don't think this is a normal solution, this should work without creating any new threads (like with default android mediaplayer)

        mMediaPlayer.reset();
        try {
            mMediaPlayer.setDataSource(source);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mMediaPlayer.prepareAsync();
                }
            }).start();
        } catch (IOException e) {
            Log.i(TAG, "mMediaPlayer setDataSource e: " + e);
        }

@SluggedGerm2
Copy link

SluggedGerm2 commented Apr 30, 2017

I also confirm that prepareAsync() not load OnPreparedListener(). It dose only the first time, cold be the .resete()?

@h6ah4i
Copy link
Owner

h6ah4i commented May 6, 2017

@anonym24 @SluggedGerm2 Hi. Sorry for the late response 😞 I tried to reproduce it today, but it cannot be done yet. Could you provide a sample project which can reproduce the issue?


04-29 20:13:56.809 26389-26389/com.android.testpalyer E/OpenSLMediaPlayer: An error occurred in getCurrentPosition()
04-29 20:13:56.815 26389-26389/com.android.testpalyer I/LOGGG: MediaPlayer: onError -38 0

This seems that you are calling getCurrentPosition() method in wrong state. Please refer to the "Valid and invalid states" table on the official MediaPlayer document.

@SluggedGerm2
Copy link

SluggedGerm2 commented May 6, 2017

public OpenSLMediaPlayer player;
    private OpenSLMediaPlayerContext openSLMediaPlayerContext;
    public Song nextSong;
    private Song actual_playing;

    public customPlayer(Context context){
OpenSLMediaPlayerContext.Parameters parameters = new OpenSLMediaPlayerContext.Parameters();
        parameters.streamType = AudioManager.STREAM_MUSIC;
        openSLMediaPlayerContext = new OpenSLMediaPlayerContext(context,parameters);                
        player = new OpenSLMediaPlayer(openSLMediaPlayerContext,Settings.OPTION_USE_FADE);          
        player.setOnPreparedListener(new OnPreparedListener());                                     //I add one single time the prepared listener

        nextSong = null;

        actual_listSong = new ArrayList<>();
    }

class OnPreparedListener implements IBasicMediaPlayer.OnPreparedListener{
        @Override
        public void onPrepared(IBasicMediaPlayer mp) {
            mp.start();
        }
    }
   
private void playSong(final Context context, final Song song){
if (player == null) {   //create the player if it is null
            new customPlayer(context);
        } else {
            player.reset(); //reset the player anyway. If it is playing, or has finished to play, setdatasource wan't crash without the reset of mediaplayer
            //player.setOnPreparedListener(new OnPreparedListener()); //I tried here to reset the player,but didn't work
        }
        Uri contentUri = ContentUris.withAppendedId(android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, song.getID());
        if (contentUri == null) {
            Log.i(LOG_TAG,"Error finding the media Id : " + song.getTitle() + " - " + song.getID());
            return;
        }

        setNextSong();  //update the next song

        try {
            player.setDataSource(context,contentUri);
            player.prepare();
            player.start();
        } catch (IOException e) {
            e.printStackTrace();
            Toast.makeText(context,e.getMessage() + " (" + actual_playing.getTitle() + ")",Toast.LENGTH_LONG).show();
        }
}

Using prepareAsync() the OnPrepared is called the first time but not the following times. For this reason i'm using normal prepare()
I also tried to create an asynctask and simulate the prepareAsync() but didn't work, some error occured

@h6ah4i
Copy link
Owner

h6ah4i commented May 7, 2017

@SluggedGerm2 Thanks, but it cannot be reproduced yet on my setup. Could you try the following repository, it is a simple sample project based on your code.

https://github.com/h6ah4i/openslmediaplayer_issue_40

My setup:

  • Nexus 5X + Stock Android 7.1.2

@SluggedGerm2
Copy link

SluggedGerm2 commented May 7, 2017

Your sample works :/ what is the trick?

@anonym24
Copy link
Author

anonym24 commented May 7, 2017

@h6ah4i
for me my own project seems to be working ok now, not sure what happened
I tried 0.7.3 & 0.7.5 and both worked ok.
I'll let you know if issue happens again and upload example

also I'll check my old backuped projects, and compare with the latest one and mb find out something

@SluggedGerm2
Copy link

SluggedGerm2 commented May 7, 2017

@h6ah4i: I have updated my project from 0.7.3 to 0.7.5 and now the prepareAsync() is called some times, but still not always. I can't see anything common for songs that never arrived to OnPreparedListener.
The same song sometimes works and other time not. I thought that cold be the thread that simultaneasly try to read the the song cover art, but also disabling this thread prepareAsync doesn't work. Disabling this thread there isn't anything more can interfare with song prepare, i think
For example now I'm trying to play always same two songs. Sometimes both works, sometimes only one, and sometimes none works.
But your sample works. I can't understand what's wrong.

@anonym24
Copy link
Author

anonym24 commented May 7, 2017

I guess I quite understood the problem, so mb it really because of calling such methods like .getDuration , .getCurrentPosition in the wrong state (e.g. before source/song was prepared).
And it seems that OpenslMediaPlayer calls onCompletion method when these errors happens - here I guess the difference between OpenslMediaPlayer & Default Android MediaPlayer.
So for Default Android MediaPlayer these errors weren't critical, it didn't call onCompletion and it still calls onPrepared so there was no loop with fast switching to the next song (in onCompletion method I call my nextSong method)

@anonym24
Copy link
Author

anonym24 commented May 7, 2017

yes, now I'm sure. If we for example call mMediaPlayer.getCurrentPosition() while something is being prepared async (with prepareAsync method), OpenslMediaPlayer will call onError and onCompletion and will NOT call onPrepared.
Default Android MediaPlayer doesn't behave like this with prepareAsync

@SluggedGerm2
Copy link

@anonym24 Thanks for this clarification! now I can try to avoid this problem :)

@SluggedGerm2
Copy link

I solved with a simple boolean that is setted to false when setDataSource is setted (so before prepareAsync) and is setted to true when the Onprepared is called. So I ovveride dangerous methods like getCurrentPosition() to make it only working if the boolean is true

@anonym24
Copy link
Author

anonym24 commented May 7, 2017

@SluggedGerm2 yeah I did exactly the same :)

@SluggedGerm2
Copy link

@anonym24 @h6ah4i Thanks a lot for your kind help

@TavishBarua
Copy link

TavishBarua commented Nov 7, 2019

@anonym24 @h6ah4i @SluggedGerm2 Is there anyone to guide me for the same.
Actually I'm also facing the same scenario even after performing the above suggestions
And my audio glitches if I perform prepare()

fun startSong() {
mHandler?.removeCallbacks(sendUpdatesToUI)

    mSong = mSongs[mSongPos]
    mMediaPlayer1?.reset()
    mMediaPlayerPrepared = false
    try {
        mSongDataHelper = SongDataHelper()
        mSongDataHelper?.populateSongData(mContext!!, null, mSongPos)
        mMediaPlayer1?.setDataSource(mContext!!, getUri(mSongs[mSongPos]._id!!))
       mMediaPlayer1?.setOnPreparedListener(onPreparedListener)
        mMediaPlayer1?.setOnErrorListener(onErrorListener)
        mMediaPlayer1?.prepareAsync()

    } catch (ex: Exception) {
        ex.printStackTrace()
    }
}

/* Prepared Listener */

private val onPreparedListener =
        IBasicMediaPlayer.OnPreparedListener {
            mMediaPlayerPrepared = true
            mMediaPlayer1?.setOnCompletionListener(mOnCompletionListener)
            if (mPlayingForFirstTime) {
                mPlayingForFirstTime = false
            }
            startPlaying()

            val intent = Intent(Constants.ACTION_UPDATE_NOW_PLAYING_UI)
            intent.putExtra(Constants.UPDATE_UI, true)
            sendBroadcast(intent)
        }

@metinsevindik
Copy link

@anonym24 @h6ah4i @SluggedGerm2 Is there anyone to guide me for the same.
Actually I'm also facing the same scenario even after performing the above suggestions
And my audio glitches if I perform prepare()

fun startSong() {
mHandler?.removeCallbacks(sendUpdatesToUI)

    mSong = mSongs[mSongPos]
    mMediaPlayer1?.reset()
    mMediaPlayerPrepared = false
    try {
        mSongDataHelper = SongDataHelper()
        mSongDataHelper?.populateSongData(mContext!!, null, mSongPos)
        mMediaPlayer1?.setDataSource(mContext!!, getUri(mSongs[mSongPos]._id!!))
       mMediaPlayer1?.setOnPreparedListener(onPreparedListener)
        mMediaPlayer1?.setOnErrorListener(onErrorListener)
        mMediaPlayer1?.prepareAsync()

    } catch (ex: Exception) {
        ex.printStackTrace()
    }
}

/* Prepared Listener */

private val onPreparedListener =
        IBasicMediaPlayer.OnPreparedListener {
            mMediaPlayerPrepared = true
            mMediaPlayer1?.setOnCompletionListener(mOnCompletionListener)
            if (mPlayingForFirstTime) {
                mPlayingForFirstTime = false
            }
            startPlaying()

            val intent = Intent(Constants.ACTION_UPDATE_NOW_PLAYING_UI)
            intent.putExtra(Constants.UPDATE_UI, true)
            sendBroadcast(intent)
        }

Wonderfull. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants