[android] MediaPlayer를 사용하여 Android의 URL에서 오디오를 스트리밍합니까?

Android의 내장 MediaPlayer 클래스를 사용하여 http를 통해 mp3를 스트리밍하려고했습니다. 문서는 이것이 다음과 같이 쉬워야한다고 제안합니다.

MediaPlayer mp = new MediaPlayer();
mp.setDataSource(URL_OF_FILE);
mp.prepare();
mp.start();

그러나 나는 다음과 같은 것을 반복적으로 얻고 있습니다. 다른 URL도 시도했습니다. 스트리밍이 mp3에서 작동하지 않는다고 말하지 마십시오.

E/PlayerDriver(   31): Command PLAYER_SET_DATA_SOURCE completed with an error or info PVMFErrNotSupported
W/PlayerDriver(   31): PVMFInfoErrorHandlingComplete
E/MediaPlayer(  198): error (1, -4)
E/MediaPlayer(  198): start called in state 0
E/MediaPlayer(  198): error (-38, 0)
E/MediaPlayer(  198): Error (1,-4)
E/MediaPlayer(  198): Error (-38,0)

많은 도움을 주셔서 감사합니다.



답변

스트리밍 예제가있는 간단한 미디어 플레이어. xml 부분의 경우 id button1이있는 버튼 하나와 이름이 button_pause 및 button_play 인 드로어 블 폴더에 두 개의 이미지가 필요하며 매니페스트에 인터넷 권한을 추가하는 것을 잊지 마십시오.

public class MainActivity extends Activity {
private Button btn;
/**
 * help to toggle between play and pause.
 */
private boolean playPause;
private MediaPlayer mediaPlayer;
/**
 * remain false till media is not completed, inside OnCompletionListener make it true.
 */
private boolean intialStage = true;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    btn = (Button) findViewById(R.id.button1);
    mediaPlayer = new MediaPlayer();
    mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
    btn.setOnClickListener(pausePlay);

}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.activity_main, menu);
    return true;
}

private OnClickListener pausePlay = new OnClickListener() {

    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub
        // TODO Auto-generated method stub

        if (!playPause) {
            btn.setBackgroundResource(R.drawable.button_pause);
            if (intialStage)
                new Player()
                        .execute("http://www.virginmegastore.me/Library/Music/CD_001214/Tracks/Track1.mp3");
            else {
                if (!mediaPlayer.isPlaying())
                    mediaPlayer.start();
            }
            playPause = true;
        } else {
            btn.setBackgroundResource(R.drawable.button_play);
            if (mediaPlayer.isPlaying())
                mediaPlayer.pause();
            playPause = false;
        }
    }
};
/**
 * preparing mediaplayer will take sometime to buffer the content so prepare it inside the background thread and starting it on UI thread.
 * @author piyush
 *
 */

class Player extends AsyncTask<String, Void, Boolean> {
    private ProgressDialog progress;

    @Override
    protected Boolean doInBackground(String... params) {
        // TODO Auto-generated method stub
        Boolean prepared;
        try {

            mediaPlayer.setDataSource(params[0]);

            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {

                @Override
                public void onCompletion(MediaPlayer mp) {
                    // TODO Auto-generated method stub
                    intialStage = true;
                    playPause=false;
                    btn.setBackgroundResource(R.drawable.button_play);
                    mediaPlayer.stop();
                    mediaPlayer.reset();
                }
            });
            mediaPlayer.prepare();
            prepared = true;
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            Log.d("IllegarArgument", e.getMessage());
            prepared = false;
            e.printStackTrace();
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IllegalStateException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            prepared = false;
            e.printStackTrace();
        }
        return prepared;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        if (progress.isShowing()) {
            progress.cancel();
        }
        Log.d("Prepared", "//" + result);
        mediaPlayer.start();

        intialStage = false;
    }

    public Player() {
        progress = new ProgressDialog(MainActivity.this);
    }

    @Override
    protected void onPreExecute() {
        // TODO Auto-generated method stub
        super.onPreExecute();
        this.progress.setMessage("Buffering...");
        this.progress.show();

    }
}

@Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    if (mediaPlayer != null) {
        mediaPlayer.reset();
        mediaPlayer.release();
        mediaPlayer = null;
    }
}


답변

Android MediaPlayer는 2.2까지 기본적으로 MP3 스트리밍을 지원하지 않습니다. 이전 버전의 OS에서는 기본적으로 3GP 만 스트리밍하는 것으로 보입니다. pocketjourney 코드가 오래되었지만 ( 여기에 새 버전이 있습니다 ) 사용해 볼 수 있습니다. 끈적하게 만드는 데 어려움이있었습니다. 버퍼를 다시 채울 때마다 끊김이 발생했습니다.

Android 용 NPR News 앱은 오픈 소스이며 로컬 프록시 서버를 사용하여 2.2 이전 OS 버전에서 MP3 스트리밍을 처리합니다. 199-216 행 (r94)의 관련 코드는 http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/ 에서 확인할 수 있습니다 . PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

그리고 이것은 StreamProxy 클래스입니다 : http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

NPR 앱은 스트리밍하는 동안 가끔 “오류 (-38, 0)”가 ​​발생합니다. 스레딩 문제 또는 네트워크 변경 문제 일 수 있습니다. 이슈 트래커에서 업데이트를 확인하십시오 .


답변

나는 당신이 .pls를 직접 또는 비슷한 것을 재생하려고 시도하고 있다고 생각합니다.

이것을 시도하십시오 :

1 : 코드

mediaPlayer = MediaPlayer.create(this, Uri.parse("http://vprbbc.streamguys.net:80/vprbbc24.mp3"));
mediaPlayer.start();

2 : .pls 파일

이 URL은 예를 들어 BBC에서 가져온 것입니다. Linux에서 다운로드 한 .pls 파일이었습니다.

wget http://foo.bar/file.pls

그런 다음 vim (좋아하는 편집기 사용;)으로 열었고이 파일 내부의 실제 URL을 보았습니다. 불행히도 모든 .pls가 그런 일반 텍스트는 아닙니다.

1.6이 http를 통한 mp3 스트리밍을 지원하지 않는다고 읽었지만 Android 1.6 및 2.2에서 obove 코드를 테스트했으며 문제가 없었습니다.

행운을 빕니다!


답변

사용하다

 mediaplayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
 mediaplayer.prepareAsync();
 mediaplayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
      @Override
      public void onPrepared(MediaPlayer mp) {
          mediaplayer.start();
      }
 });


답변

나는 당신과 같은 오류가 있었고 코드에 아무런 문제가 없다는 것이 밝혀졌습니다. 문제는 웹 서버가 잘못된 Content-Type 헤더를 보내고 있다는 것입니다.

wireshark 또는 이와 유사한 것을 시도하여 웹 서버가 보내는 콘텐츠 유형을 확인하십시오.


답변

내 프로젝트를 찾고 :

  1. https://github.com/master255/ImmortalPlayer http / FTP 지원, 읽기, 전송 및 캐시 데이터 저장을위한 하나의 스레드. 가장 간단한 방법과 가장 빠른 작업. 복잡한 논리-최선의 방법!
  2. https://github.com/master255/VideoViewCache 캐시가있는 간단한 Videoview. 재생 및 데이터 저장을위한 두 개의 스레드. 잘못된 논리이지만 필요한 경우 이것을 사용하십시오.


답변

로그에서 0 상태를 피하기 위해 OnPreparedListener로 mp.start를 호출하지 않습니다.