Android API 23 vs Android API 25 in MediaPlayer buffering speed

571 views Asked by At

I am having some problems getting the MediaPlayer to properly work on API 23. I've tested this on the SAME WiFI network and or Cellular network and the results are the same. I am using MediaPlayer.prepareAsync() to prepare my stream. I've attached the debugger to the onPreparedListener() and it gets never ran. Please have a look at the graphs below.

Graph from Android API 25

Network usage on Android API 25

Graph from Android API 23 Network usage on Android API 23

There are the images from the Monitor tab in Android Studio. The .mp3 file is about 10 seconds long. Like you can see Android API 23 is loading the song only very slowly a small portion every 2 to 3 seconds.

While Android API 25 is loading it instantly within 2 seconds.

The main problem is that is taking a long time to infinite to load the song on Android API 23. Does anyone have similar issues and knows how to fix it? A portion of my code will be in a code sample below

public class CustomMediaPlayer implements MediaPlayer.OnPreparedListener {

private Context context;

private MediaPlayer mediaPlayer;
private boolean mediaPlayerReady;
private MaterialDialog loadingDialog;
private MaterialDialog playingDialog;
private TextView textTime;
private SeekBar seekBar;
private Handler handler;
private Runnable updateSongTime;

private String audioFileTitle;
private String audioFileUrl;
private int customPlayerView;


public CustomMediaPlayer(Context context) {
    this.context = context;
    this.mediaPlayerReady = false;
}

public void setSongName(String audioFileTitle) {
    this.audioFileTitle = audioFileTitle;
}

public void setSongUrl(String audioFileUrl) {
    this.audioFileUrl = audioFileUrl;
}

public void setCustomView(int customPlayerView) {
    this.customPlayerView = customPlayerView;
}

public void show() {
    PrepareDialogs();
    MediaPlayerCreate();
    HandlerRunnableCreate();
    MediaPlayerPrepare();
}

private void PrepareDialogs() {
    this.loadingDialog = new MaterialDialog.Builder(this.context)
            .title("Loading...")
            .content("Please wait")
            .progress(true, 0)
            .cancelable(true)
            .build();

    this.loadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
        @Override
        public void onCancel(DialogInterface dialog) {
            mediaPlayer.release();
            handler.removeCallbacks(updateSongTime);
            dialog.dismiss();
        }
    });

    this.playingDialog = new MaterialDialog.Builder(this.context)
            .title(this.audioFileTitle)
            .customView(this.customPlayerView, false)
            .neutralText("Close")
            .onNeutral(new MaterialDialog.SingleButtonCallback() {
                @Override
                public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
                    mediaPlayer.release();
                    handler.removeCallbacks(updateSongTime);
                    dialog.dismiss();
                }
            })
            .cancelable(false)
            .build();

    this.playingDialog.getCustomView().findViewById(R.id.image_play_pause).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ImageView image = (ImageView) v;
            if(mediaPlayer.isPlaying()) {
                image.setImageResource(R.drawable.ic_play);
                mediaPlayer.pause();
            } else {
                image.setImageResource(R.drawable.ic_pause);
                mediaPlayer.start();
            }
            v = image;
        }
    });

    this.textTime = (TextView) this.playingDialog.getCustomView().findViewById(R.id.text_time);
    this.seekBar = (SeekBar) this.playingDialog.getCustomView().findViewById(R.id.seek_bar);

    this.seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            mediaPlayer.pause();
            handler.removeCallbacks(updateSongTime);
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            mediaPlayer.seekTo(seekBar.getProgress());
            mediaPlayer.start();
            handler.postDelayed(updateSongTime, 100);
        }
    });
}

private void MediaPlayerCreate() {
    this.mediaPlayer = new MediaPlayer();
    this.mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    try {
        this.mediaPlayer.setDataSource(this.audioFileUrl);
        this.mediaPlayerReady = true;
    } catch(IOException e) {
        e.printStackTrace();
    }

    this.mediaPlayer.setOnPreparedListener(this);
}

private void HandlerRunnableCreate() {
    this.handler = new Handler();
    this.updateSongTime = new Runnable() {
        public void run() {
            try {
                if (mediaPlayer.isPlaying()) {
                    int startTime = mediaPlayer.getCurrentPosition();
                    seekBar.setProgress(startTime);
                    seekBar.setMax(mediaPlayer.getDuration());
                }
                handler.postDelayed(this, 100);
            } catch (IllegalStateException e) {
                e.printStackTrace();
            }
        }
    };
}

private void MediaPlayerPrepare() {
    if (this.mediaPlayerReady) {
        this.loadingDialog.show();
        this.mediaPlayer.prepareAsync();
    } else {
        Toast.makeText(this.context, "Media Player not ready", Toast.LENGTH_LONG).show();
    }
}

@Override
public void onPrepared(MediaPlayer mp) {
    loadingDialog.dismiss();
    mediaPlayer.start();
    playingDialog.show();
    handler.postDelayed(updateSongTime, 100);
}

}
1

There are 1 answers

0
Roy Berris On BEST ANSWER

After HOURS of research I've found the problem, which is very useful for anyone coming across this question.

My file URL looked like this: example.com/company example/files/audio.mp3 The problem with Android API 23 and below is that this is seen as a invalid URL. Your URL should look like this example.com/company%20example/files/audio.mp3 An easy fix is to use the replaceAll() on an String like this:

String url = oldUrl.replaceAll(" ", "%20")

Note that Android does not give any error at all while your URL is invalid. So make sure your URL does not contain any spaces.

EDIT After working more with invalid URL's this is the way to go:

URL url = new URL(oldURL);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
String encodedUrl = uri.toASCIIString();