Streaming Audio dari URL di Android menggunakan MediaPlayer?

87

Saya telah mencoba untuk streaming mp3 melalui http menggunakan kelas MediaPlayer bawaan Android. Dokumentasi tersebut menyarankan kepada saya bahwa ini semudah:

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

Namun saya mendapatkan yang berikut berulang kali. Saya telah mencoba URL yang berbeda juga. Tolong jangan beri tahu saya bahwa streaming tidak berfungsi pada 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)

Setiap bantuan sangat dihargai, terima kasih S

Pandalover
sumber
Beberapa pertanyaan: (1) versi SDK mana yang Anda gunakan? (2) Perangkat mana yang Anda uji? Ini berfungsi dengan baik pada SDK 2.0.1, menguji pada Droid.
Roman Nurik
Hai Roman, terima kasih telah meluangkan waktu. Saya mencoba ini melawan 1.6 dan saya menggunakan HTC Hero. Saya akan mencobanya di 2.01 berdasarkan komentar Anda tetapi itu akan menjadi hasil yang konyol jika ini hanya bekerja pada perangkat 2.x dan di atasnya di luar kotak.
Pandalover
Baru saja mencobanya di emulator 2.01. Sayangnya tidak bekerja. Saya tertarik untuk mencoba ini melawan perangkat 1.6 asli dan perangkat 2.01 asli. Saya dalam pengujian Google pada tanggal 4. Mungkin aku harus menunggu sampai saat itu. Saya lebih suka tidak harus melakukannya.
Pandalover
Saya tidak menduga 2.0 vs. 2.0.1 akan membuat perbedaan apa pun, tetapi emulator vs. perangkat live dapat membuat perbedaan. Saya terkejut ini tidak berhasil pada Pahlawan. Saya akan memeriksanya dan melihat apakah saya bisa mendapatkan jawaban yang lebih baik. Selain itu, hanya sebagai pemeriksaan kewarasan, Anda harus memastikan bahwa Anda telah meminta izin INTERNET di manifes.
Roman Nurik
Hei, baru saja keluar dari diskusi, saya punya pertanyaan. Jika saya menggunakan mp.setDataSource (URL_OF_FILE); Kami tidak perlu menyimpan file apa pun untuk streaming audio. Bukan? Jadi itulah cara terbaik untuk mengalirkan audio dari lokasi mana pun. Ada ide?
Bohemian

Jawaban:

78

Pemutar Media sederhana dengan contoh streaming.Untuk bagian xml Anda memerlukan satu tombol dengan tombol id1 dan dua gambar di folder drawable Anda dengan nama button_pause dan button_play dan jangan lupa untuk menambahkan izin internet di manifes Anda.

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;
    }
}
PiyushMishra
sumber
Ada sedikit masalah dengan ini, jika saya mengunci ponsel saya saat MediaPlayer diputar, aplikasi saya macet saat saya membukanya.
CiaranC94
3
Saya baru saja mencoba mengomentari baris "mediaPlayer.release ()" di onPause (), dan sekarang aplikasi saya tidak mogok saat membuka kunci.
CiaranC94
@PiyushMishra fitur ini diterima oleh konsol pengembang? Karena aplikasi saya ditolak karena saya telah menggunakan versi Vitamio 4.x
Pallavi
35

Android MediaPlayer tidak mendukung streaming MP3 secara native hingga 2.2. Dalam versi OS yang lebih lama, tampaknya hanya melakukan streaming 3GP secara native. Anda dapat mencoba kode pocketjourney, meskipun sudah lama (ada versi baru di sini ) dan saya kesulitan membuatnya lengket - kode akan gagap setiap kali mengisi ulang buffer.

Aplikasi NPR News untuk Android adalah open source dan menggunakan server proxy lokal untuk menangani streaming MP3 dalam versi OS sebelum 2.2. Anda dapat melihat kode yang relevan pada baris 199-216 (r94) di sini: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/ PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Dan ini adalah kelas StreamProxy: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

Aplikasi NPR juga terkadang masih mendapatkan "error (-38, 0)" saat streaming. Ini mungkin masalah threading atau masalah perubahan jaringan. Periksa pelacak masalah untuk pembaruan .

jwadsack
sumber
Apakah Anda benar-benar yakin tentang ini? Pemahaman saya adalah bahwa hal itu berkaitan dengan tipe pantomim. Bisakah Anda memeriksa apakah t berfungsi dengan tipe MIME yang benar sebelum 2.1? Saya sedang mengerjakan sesuatu yang lain sekarang dan tidak dapat memeriksanya untuk sementara waktu.
Pandalover
1
Menurut catatan rilis 2.2 ( developer.android.com/sdk/android-2.2-highlights.html ), ini mencakup "Kerangka media baru (Stagefright) yang mendukung pemutaran file lokal dan streaming progresif HTTP". Dalam semua pengujian saya, saya tidak bisa mendapatkan perangkat 2.1 untuk melakukan streaming dari server shoutcast secara langsung. Saya percaya bahwa masalahnya adalah bahwa server shoutcast mengembalikan protokol ICY / 1.1 daripada HTTP / 1.1 dan pemutar media tersandung karena tidak tahu bagaimana menanggapi konten itu.
jwadsack
@jwadsack bagaimana jika file audio harus diunduh sekali dan pengguna juga dapat memutar file secara offline?
Devendra Singh
@DevendraSingh Saya tidak tahu apakah Anda dapat menyimpan file saat sedang streaming dengan penerapan pemutar media saat ini (jawaban ini hampir berusia lima tahun dan banyak yang telah berubah sejak 2.2). Jika tidak ada yang lain, Anda dapat membuat proxy dengan mengikuti contoh ini dan menulis file ke penyimpanan saat Anda meneruskannya melalui proxy.
jwadsack
11

Saya rasa Anda mencoba memainkan .pls secara langsung atau yang serupa.

coba ini:

1: kode

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

2: file .pls

URL ini dari BBC hanya sebagai contoh. Itu adalah file .pls yang saya unduh di linux

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

dan kemudian saya buka dengan vim (gunakan editor favorit Anda;) dan saya telah melihat URL asli di dalam file ini. Sayangnya tidak semua .pls berupa teks biasa seperti itu.

Saya telah membaca bahwa 1.6 tidak akan mendukung streaming mp3 melalui http, tetapi, saya baru saja menguji kode di atas dengan Android 1.6 dan 2.2 dan tidak mengalami masalah apa pun.

semoga berhasil!

Pabluez
sumber
7
Ingatlah bahwa jika Anda ingin streaming musik, Anda harus menggunakan mediaplayer.prepareAsync dan bukan mediaplayer.prepare. Oleh karena itu, Anda tidak dapat menggunakan mediaplayer.create () karena salah satu fungsi .create () membawa objek Media Player Anda langsung ke status Prepared, yang darinya Anda tidak dapat memanggil preparedAsync, yang harus Anda lakukan untuk streaming. developer.android.com/reference/android/media/MediaPlayer.html
marienke
4

Menggunakan

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

Saya mengalami kesalahan yang sama seperti yang Anda alami dan ternyata tidak ada yang salah dengan kodenya. Masalahnya adalah server web mengirimkan header Jenis Konten yang salah.

Coba wireshark atau sesuatu yang serupa untuk melihat jenis konten apa yang dikirim server web.

doep
sumber
untuk file mp3 harus Jenis Konten: audio / mpeg Itu memecahkan masalah saya :)
doep
1
Bagaimana Anda mengalirkan file itu?
Nauman Khalid
2

Melihat proyek saya:

  1. https://github.com/master255/ImmortalPlayer http / dukungan FTP, Satu utas untuk membaca, mengirim dan menyimpan ke data cache. Cara paling sederhana dan pekerjaan tercepat. Logika yang kompleks - cara terbaik!
  2. https://github.com/master255/VideoViewCache Simple Videoview dengan cache. Dua utas untuk memutar dan menyimpan data. Logika yang buruk, tetapi jika Anda membutuhkan maka gunakan ini.
Menguasai
sumber
1

Tidak ada panggilan mp.start dengan OnPreparedListener untuk menghindari keadaan nol di log ..

Fred Grott
sumber
Saya masih mendapatkan baris log 05-22 20: 26: 13.625: E / MediaPlayer (23818): berhenti dipanggil dalam keadaan 0 meskipun saya memulai Pemutar Media saya dalam fungsi prepared (). Saya juga memiliki fungsi onError di mana saya mengatur ulang objek Media Player. Masih perlu waktu hingga 2 menit untuk streaming saya untuk mulai diputar. Lihat pertanyaan saya di sini: stackoverflow.com/questions/16672568/…
marienke