Search code examples
javaandroidservice

ANDROID: MediaPlayer shows error (1, -19)


I'm working on a Service that plays a song picked from an ArrayList. The problem comes when I use prepare() and prepareAsync()methods, so here's the code:

public class MusicService extends Service implements MediaPlayer.OnPreparedListener{
    private final static int DEF_VALUE = -1;
    private Context mContext;
    private ArrayList<Song> mSongsList;
    private MediaPlayer mPlayer;
    private boolean isPlaying = false;
    private int mPosition;

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

    @Override
    public void onCreate(){
        super.onCreate();
        mContext = getApplicationContext();
        mSongsList = new ArrayList<Song>();
        mPlayer = new MediaPlayer();
        setMusicPlayer();
    }

    public void setMusicPlayer(){
        //Setting player properties
        mPlayer.setWakeMode(mContext, PowerManager.PARTIAL_WAKE_LOCK);
        mPlayer.setAudioSessionId(AudioManager.STREAM_MUSIC);
        mPlayer.setOnPreparedListener(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int mCommand = intent.getIntExtra("CMD", DEF_VALUE);
        int mTrackSelected = intent.getIntExtra("TRACK_CLICKED", DEF_VALUE);

        /** SERVICE COMMANDS
         *  0 = SERVICE PERMISSIONS
         *  1 = PLAY_PAUSE
         *  2 = NEXT TRACK
         *  3 = PREV TRACK
         *  4 = SONG IN LIST
         */

        switch (mCommand){
            case 0:
                GetTracks mGetSongs = new GetTracks();
                mSongsList = mGetSongs.listAllSongs(mContext);
                Log.d("test size arrayList", ""+mSongsList.size());
                break;
            case 1:
                setPlayPause();
                break;
            case 2:
                skipNextTrack();
                break;
            case 3:
                skipPrevTrack();
                break;
            case 4:
                if(mTrackSelected != DEF_VALUE){
                    mPosition = mTrackSelected;
                    setSongToPlay(mPosition);
                }
                break;
            default:
                Log.d("error cmd", "You shouldn't be here!");
                break;
        }

        return START_STICKY;
    }

    private void skipPrevTrack() {
        Log.d("method called:", "skipPrevTrack()");
        if(mPosition == 0){
            setSongToPlay(mPosition = mSongsList.size()-1);
        } else setSongToPlay(--mPosition);
        Log.d("test mPosition service", ""+mPosition);
    }

    private void skipNextTrack() {
        Log.d("method called:", "skipNextTrack()");
        if(mPosition == mSongsList.size()-1){
            setSongToPlay(mPosition = 0);
        } else setSongToPlay(++mPosition);
        Log.d("test mPosition service", ""+mPosition);
    }


    private void setSongToPlay(int pos) {
        Log.d("method called:", "setSongToPlay("+pos+")");
        startSong(mSongsList.get(pos).getSongUri());
    }
    private void startSong(Uri uri){

        try{
            mPlayer.reset();
            mPlayer.setDataSource(mContext, uri);
            mPlayer.prepareAsync();

            /** +++WORKS FINE WITH THIS CODE+++
             mPlayer = MediaPlayer.create(mContext, uri);
             mPlayer.start();
             */

        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private void setPlayPause() {
        Log.d("method called:", "setPlayPause()");
    }

    @Override
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
}

LOG:

 12-19 16:12:18.325 4013-4013/sebbsoft.myApp D/method called:: setSongToPlay(3)
12-19 16:12:18.341 4013-4013/sebbsoft.myApp D/test song playing: Fiori del male ft. Sfera Ebbasta
12-19 16:12:18.363 4013-4013/sebbsoft.myApp D/MediaPlayer: setSubtitleAnchor in MediaPlayer
12-19 16:12:18.428 4013-4028/sebbsoft.myApp E/MediaPlayer: error (1, -19)

How can I solve it?


Solution

  • Finally solved it! After a lot of trial & error!! This is the line that causes it for me:

    mMediaPlayer.setAudioSessionId(AudioManager.STREAM_MUSIC);
    

    The API doc for setAudioSessionId doesn't indicate any alternative or any issue on still using it which made it hard to debug. But I saw setAudioStreamType just below it, which is deprecated and suggests setAudioAttributes instead, w/c is added in API 21.

    So I changed the above code to this:

    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            mMediaPlayer.setAudioAttributes(new AudioAttributes.Builder()
                    .setUsage(AudioAttributes.USAGE_MEDIA)
                    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                    .build());
    } else {
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    }
    

    And now it works!

    By the way, as you can see, I checked only against version N (API 24) and above instead of from LOLLIPOP even though setAudioAttributes was added in API 21, because I only encounter this issue on Nougat devices, setAudioSessionId works up to Marshmallow devices for me so... don't wanna break anything that's already working.

    I do hope someone would stop by and explain why this happens and what the error really means.

    Hope this saves anyone days of headache :)

    EDIT: For anyone Googling around, I also changed the original mMediaPlayer.setAudioSessionId to mMediaPlayer.setAudioStreamType, as pointed out by Eugen Pechanec. See his comment and answer for details. You would also want to change from checking against Build.VERSION_CODES.N to Build.VERSION_CODES.LOLLIPOP with that.