Android MediaPlayer - onBufferingUpdate在调用0之前调用100

时间:2016-02-29 04:29:42

标签: android android-mediaplayer

以下代码是托管MediaPlayer以从URL播放MP3流的Activity的最小示例。按" btn1"触发URL1播放(NPR播客)。按" btn2"触发URL2播放(不同电台的mp3录音)。

public class MainActivity extends AppCompatActivity {

    public static final String TAG = MainActivity.class.getSimpleName();
    static final String URL1 = "http://13503.mc.tritondigital.com/WAITWAIT_PODCAST/media-session/822d578a-af47-4d7e-b3ca-d18af78071bc/anon.npr-podcasts/podcast/344098539/464996449/npr_464996449.mp3";
    static final String URL2 = "http://www.selbie.com/wrekapp/Fri0130.mp3";

    MediaPlayer _player;

    void startPlayerAsync(String url) {

        stopPlayer();  // _player.reset(); _player.release(); _player=null;

        Log.d(TAG, "===================");
        Log.d(TAG, "Starting new player for URL: "+url);

        _player = new MediaPlayer();

        try
        {
            _player.setDataSource(url);
        }
        catch (IOException e) {
            Log.d(TAG, "IOException", e);
            return;
        }

        _player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                Log.d(TAG, "onBufferingUpdate: " + percent);
            }
        });

        _player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                if (mp == _player)
                {
                    Log.d(TAG, "onPrepared");
                    _player.start();
                }
            }
        });

        _player.prepareAsync();
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btn1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPlayerAsync(URL1);
            }
        });

        findViewById(R.id.btn2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startPlayerAsync(URL2);
            }
        });
    }

}

单击btn1时,听到音频之前的logspew摘要如下:

02-28 19:47:43.764 D/MainActivity: ===================
02-28 19:47:43.764 D/MainActivity: Starting new player for URL: http://13503.mc.tritondigital.com/WAITWAIT_PODCAST/media-session/822d578a-af47-4d7e-b3ca-d18af78071bc/anon.npr-podcasts/podcast/344098539/464996449/npr_464996449.mp3
02-28 19:47:44.695 1D/MainActivity: OnBufferingUpdate: 0
02-28 19:47:44.697 D/MediaPlayer: setSubtitleAnchor in MediaPlayer
02-28 19:47:44.699 D/MainActivity: onPrepared
02-28 19:47:44.703 D/MainActivity: onBufferingUpdate: 0
02-28 19:47:45.703 D/MainActivity: onBufferingUpdate: 6
02-28 19:47:46.704 D/MainActivity: onBufferingUpdate: 9
...

当为其他网址按下btn2时,行为略有不同:

02-28 19:47:18.892 D/MainActivity: ===================
02-28 19:47:18.893 D/MainActivity: Starting new player for URL: http://www.selbie.com/wrekapp/Fri0130.mp3
02-28 19:47:20.453 D/MainActivity: onBufferingUpdate: 100     <==== NOTICE THIS
02-28 19:47:20.453 D/MediaPlayer: setSubtitleAnchor in MediaPlayer
02-28 19:47:20.465 D/MainActivity: onPrepared
02-28 19:47:20.676 D/MainActivity: onBufferingUpdate: 0
02-28 19:47:21.680 D/MainActivity: onBufferingUpdate: 2
...

在第一种情况下,onBufferingUpdate(0)之前会发生早期onPrepared事件。然后,当流播放时,onBufferingUpdate个调用的周期性间隔从0递增到100。

但是在第二种情况下,发生了一个虚假的onBufferingUpdate(100)事件。但几秒钟之后,onBufferingUpdate(0)之后的onPrepared更正了。

用户首先点击哪个按钮或启动哪个流并不重要。我甚至将URL2的mp3文件从其原始服务器移动到另一台服务器。有关于第二个URL的mp3流导致MediaPlayer想要以这种方式运行的东西。在我的实际应用中,这会导致&#34;二次进展&#34;我的进度控制线在显示预期缓冲之前显示实线一秒。这是应用程序的视觉瑕疵。

我的解决方法是在onBufferingUpdate被触发之前忽略所有onPrepared个事件。在我做出改变之前,我想了解一下为什么会发生这种情况。并确保可以安全地假设在流启动之前缓冲达到100%是不合法的。这是正确的解决办法吗?

1 个答案:

答案 0 :(得分:0)

没有其他选项,当MediaPlayer处于准备状态并且之前没有使用非零值调用时,我决定忽略对onBufferingUpdate的任何调用,其值为100 :

实际上,代码变为:

    _player.setOnBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {

             // percent can be something awkward like "-2147483648" on a live source. Just clamp it.
            if (percent < 0) {
               percent = 0;
            }
            else if (percent > 100) {
                percent = 100;
            }

            if ((_state == Preparing) && (_secondaryPercent == 0) && (percent == 100)) {
                  Log.d(TAG, "onBufferingUpdate(100) invoked while in preparing state - ignoring");
            }
            else if (_secondaryPercent != percent) {
                _secondaryPercent = percent;
                handleBufferingUpdate(percent);
            }
        }
    });