Android MediaPlayer 准备时间太长

发布于 2024-10-03 04:26:21 字数 759 浏览 11 评论 0原文

嘿, 我正在使用 MediaPlayer 播放常规 ShoutCast 流。该代码非常简单,只需使用prepareAsync() 和一个处理程序即可开始播放。虽然它可以与 DI.FM 或 ETN.FM (http://u10.di.fm:80/di_progressive) 等某些流完美配合,但与其他流 (http://mp3.wpsu.org:8000/) 则无法完美配合。不要超过准备状态。也没有调用其他侦听器。

//Uri streamUri = Uri.parse("http://u10.di.fm:80/di_progressive"); /* works */
Uri streamUri = Uri.parse("http://mp3.wpsu.org:8000/"); /* stuck on prepare state */
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(this.getBaseContext(), streamUri);
mediaPlayer.prepareAsync();

如有任何反馈,我们将不胜感激!

Hey,
I'm using MediaPlayer to play a regular ShoutCast stream. The code is straightforward with prepareAsync() and a handler to start the playback. While it works flawlessly with some streams like DI.FM or ETN.FM (http://u10.di.fm:80/di_progressive), with others (http://mp3.wpsu.org:8000/) it won't go past the prepare state. No other listeners are called either.

//Uri streamUri = Uri.parse("http://u10.di.fm:80/di_progressive"); /* works */
Uri streamUri = Uri.parse("http://mp3.wpsu.org:8000/"); /* stuck on prepare state */
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
    public void onPrepared(MediaPlayer mp) {
        mp.start();
    }
});
mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mediaPlayer.setDataSource(this.getBaseContext(), streamUri);
mediaPlayer.prepareAsync();

Any feedback is appreciated!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

任性一次 2024-10-10 04:26:21

我认为服务器端存在一些兼容性问题。
这很奇怪,因为在我的情况下模拟器可以正常处理它 - 只是在我的 Froyo Galaxy S 上不行,即使它是相同的 API 版本。

这可能是编解码器问题,http 流问题,我不知道。
但所有出现故障的服务器往往都是旧服务器,底部带有“版权所有 1998 - 2004”... 并不完全是您想象的最近或最新的。

一种潜在的解决方法(我尚未尝试过)是使用 StreamProxy,这也将使您的代码与 2.1 和可能更早的版本兼容。以额外的工作、额外的代码和毫无疑问的额外错误为代价...

如果您没有意识到,还有另一个 2.2 的播放器错误报告也可能相关:
基本流音频在 2.1 中有效,但在 2.1 中无效在2.2中

I think that there are some compatibility problems with the server end.
This is rather strange since the emulator handles it ok in my case - just not on my Froyo Galaxy S, even though it is the same API version.

It could be a codec issue, http streaming issue, I do not know.
But all the servers that fail tend to be old ones, with "Copyright 1998 - 2004" at the bottom... Not exactly recent or up to date you would think.

One potential workaround (which I have not tried yet) would be to use the StreamProxy, which would also make your code compatible with 2.1 and possibly earlier versions too. At the cost of extra work, extra code, and without doubt extra bugs...

In case you are not aware of it, there is another player bug report for 2.2 which may be relevant too:
Basic streaming audio works in 2.1 but not in 2.2

↙温凉少女 2024-10-10 04:26:21

当 MP 在准备状态(流)太长时“挂起”时,我遇到一个问题,并且我试图使用重置()来停止它。这会导致 MP 挂起,从而导致我的整个应用程序冻结。看来没有办法阻止MP处于准备状态。我正在考虑使用包含在线程中的prepare()而不是prepareAsync()。然后我就可以杀死该线程。至于现在,我按照以下方式做到了:

private void actionCancel(){
            try {
                mp.setDataSource(new String());
            } catch (Exception e) {
                e.printStackTrace();
                android.util.Log.d(TAG,"actionCancel(): mp.setDataSource() exception");
                mp.reset();
            }
}

并且它可以工作 4me。
另外,我有一个以下计数器:

    @Override
    public void onBufferingUpdate(final MediaPlayer mp, final int percent) {

        if (!mp.isPlaying()){
//          android.util.Log.d(TAG,"onBufferingUpdate(): onBufferingUpdateCount = "+onBufferingUpdateCount);
            if (onBufferingUpdateCount>MAX_BUFFERING_UPDATES_AT_PREPARING_STATE)
                restartMP();
            onBufferingUpdateCount++;
            return;
        }
      }

我发现这个监听器总是在准备状态下触发。因此,如果它触发超过 10 次并且 MP 仍未播放,我只需重新启动它:

private void restartMP(){
        if (mp!=null)
            if (mpState==MediaPlayerState.Preparing)
                actionCancel();
            else
                mp.reset();
    else
        mp = new MediaPlayer();
        mpState = MediaPlayerState.Idle;
        onBufferingUpdateCount=0;
        //isRequestCancelled=false;
        requestTrackInfoStartedAt=0;
        requestPlay();
}

注意 MediaPlayerState 是我的自定义枚举,具有“准备”值。另外 mpState 是一个类属性/字段,它保存当前 MediaPlayerState 状态。在启动prepareAsync()之前,我将mpState设置为MediaPlayerState.Preparing,在完成后将其设置为MediaPlayerState.Started或其他相应的值。

I'm facing an issue when MP "hangs" at preparing state too long (stream) and i'm trying to stop it using reset(). This causes MP to hang and thus my whole app freezes. Seems like there is no way to stop MP at preparing state. Im thinking on use prepare() wrapped in thread instead of prepareAsync(). Then i'll be able to kill that thread. As for now i did it in following way:

private void actionCancel(){
            try {
                mp.setDataSource(new String());
            } catch (Exception e) {
                e.printStackTrace();
                android.util.Log.d(TAG,"actionCancel(): mp.setDataSource() exception");
                mp.reset();
            }
}

and it works 4me.
Additionally i have a following counter:

    @Override
    public void onBufferingUpdate(final MediaPlayer mp, final int percent) {

        if (!mp.isPlaying()){
//          android.util.Log.d(TAG,"onBufferingUpdate(): onBufferingUpdateCount = "+onBufferingUpdateCount);
            if (onBufferingUpdateCount>MAX_BUFFERING_UPDATES_AT_PREPARING_STATE)
                restartMP();
            onBufferingUpdateCount++;
            return;
        }
      }

i'd discover this listener always triggers at preparing state. So if it triggers more than 10 times and MP is still not playing i'm just restarting it:

private void restartMP(){
        if (mp!=null)
            if (mpState==MediaPlayerState.Preparing)
                actionCancel();
            else
                mp.reset();
    else
        mp = new MediaPlayer();
        mpState = MediaPlayerState.Idle;
        onBufferingUpdateCount=0;
        //isRequestCancelled=false;
        requestTrackInfoStartedAt=0;
        requestPlay();
}

note MediaPlayerState is my custom enum which has "Preparing" value. Also mpState is a class property/field which holds current MediaPlayerState state. Before starting prepareAsync() im setting mpState to MediaPlayerState.Preparing after it completes im setting it to MediaPlayerState.Started or other corresponding value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文