5

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();

どんなフィードバックでも大歓迎です!

4

2 に答える 2

2

MP が準備状態 (ストリーム) で長時間「ハング」し、reset() を使用して停止しようとすると、問題に直面しています。これにより MP がハングし、アプリ全体がフリーズします。準備状態でMPを止める方法はないようです。prepareAsync() の代わりにスレッドにラップされた prepare() の使用を考えています。その後、私はそのスレッドを殺すことができます。今のところ、私は次の方法でそれを行いました:

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 または他の対応する値に設定します。

于 2011-08-09T09:36:29.233 に答える
2

サーバー側との互換性の問題があると思います。私の場合、エミュレーターはそれを問題なく処理するため、これはかなり奇妙です-同じAPIバージョンであっても、私のFroyo Galaxy Sではそうではありません.

コーデックの問題、http ストリーミングの問題である可能性がありますが、わかりません。しかし、失敗するサーバーはすべて古いサーバーである傾向があり、下部に「Copyright 1998 - 2004」が表示されています...正確に最近または最新ではないと思うでしょう。

考えられる回避策の 1 つ (私はまだ試していません) は、StreamProxyを使用することです。これにより、コードが 2.1 およびおそらくそれ以前のバージョンと互換性を持つようになります。余分な作業、余分なコード、そして間違いなく余分なバグを犠牲にして...

ご存じない方のために、関連する可能性のある 2.2 の別のプレーヤー バグ レポートがあります

于 2010-12-11T18:52:43.457 に答える