Android API 23 vs Android API 25 in MediaPlayer 缓冲速度
Android API 23 vs Android API 25 in MediaPlayer buffering speed
我在让 MediaPlayer 在 API23 上正常工作时遇到了一些问题。我已经在相同的 WiFI 网络和/或蜂窝网络上对此进行了测试,结果是相同的。我正在使用 MediaPlayer.prepareAsync()
来准备我的流。我已将调试器附加到 onPreparedListener()
,但它永远不会 运行。请看下面的图表。
Android API 上的网络使用情况 25
Android API 23
上的网络使用情况
Android Studio 中的“监视器”选项卡中有图像。 .mp3 文件长约 10 秒。就像你看到的那样 Android API 23 正在非常缓慢地每 2 到 3 秒加载一小部分歌曲。
而 Android API 25 正在 2 秒内立即加载它。
主要问题是在 Android API 上无限加载歌曲需要很长时间 23. 有没有人有类似的问题并且知道如何解决?我的部分代码将在下面的代码示例中
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);
}
}
经过 HOURS 的研究,我发现了这个问题,这对遇到这个问题的任何人都非常有用。
我的文件 URL 看起来像这样:example.com/company example/files/audio.mp3
Android API 23 及以下的问题在于,这被视为无效的 URL。您的 URL 应如下所示 example.com/company%20example/files/audio.mp3
一个简单的解决方法是像这样在 String
上使用 replaceAll()
:
String url = oldUrl.replaceAll(" ", "%20")
请注意,当您的 URL 无效时,Android 根本不会给出任何错误。因此请确保您的 URL 不包含任何空格。
编辑
在处理了更多无效的 URL 之后,这是要走的路:
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();
我在让 MediaPlayer 在 API23 上正常工作时遇到了一些问题。我已经在相同的 WiFI 网络和/或蜂窝网络上对此进行了测试,结果是相同的。我正在使用 MediaPlayer.prepareAsync()
来准备我的流。我已将调试器附加到 onPreparedListener()
,但它永远不会 运行。请看下面的图表。
Android API 上的网络使用情况 25
Android Studio 中的“监视器”选项卡中有图像。 .mp3 文件长约 10 秒。就像你看到的那样 Android API 23 正在非常缓慢地每 2 到 3 秒加载一小部分歌曲。
而 Android API 25 正在 2 秒内立即加载它。
主要问题是在 Android API 上无限加载歌曲需要很长时间 23. 有没有人有类似的问题并且知道如何解决?我的部分代码将在下面的代码示例中
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);
}
}
经过 HOURS 的研究,我发现了这个问题,这对遇到这个问题的任何人都非常有用。
我的文件 URL 看起来像这样:example.com/company example/files/audio.mp3
Android API 23 及以下的问题在于,这被视为无效的 URL。您的 URL 应如下所示 example.com/company%20example/files/audio.mp3
一个简单的解决方法是像这样在 String
上使用 replaceAll()
:
String url = oldUrl.replaceAll(" ", "%20")
请注意,当您的 URL 无效时,Android 根本不会给出任何错误。因此请确保您的 URL 不包含任何空格。
编辑 在处理了更多无效的 URL 之后,这是要走的路:
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();