MediaPlayer kullanarak Android'de bir URL'den Ses Akışı mı Yapıyorsunuz?


87

Android'in yerleşik MediaPlayer sınıfını kullanarak http üzerinden mp3 yayınlamaya çalışıyorum. Belgeler bana bunun şu kadar kolay olmasını öneriyor:

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

Ancak aşağıdakileri tekrar tekrar alıyorum. Farklı URL'leri de denedim. Lütfen bana akışın mp3'lerde çalışmadığını söyleme.

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)

Herhangi bir yardım çok takdir edilir, teşekkürler S


Birkaç soru: (1) Hangi SDK sürümünü kullanıyorsunuz? (2) Hangi cihazları test ediyorsunuz? Bu, bir Droid üzerinde test edilen SDK 2.0.1'de iyi çalışıyor.
Roman Nurik

Merhaba Roman, zaman ayırdığınız için teşekkürler. Bunu 1.6'ya karşı deniyorum ve bir HTC Hero kullanıyorum. Yorumlarınız ışığında 2.01'de deneyeceğim, ancak bu sadece 2.x ve üzeri cihazlarda çalışsaydı gülünç bir sonuç olurdu.
Pandalover

2.01 öykünücüsünde denedim. Maalesef çalışmıyor. Bunu gerçek bir 1.6 cihaza ve gerçek bir 2.01 cihaza karşı denemek ilgimi çekiyor. 4'ünde Google testindeyim. Belki o zamana kadar beklemem gerekecek. Yine de zorunda kalmamayı tercih ederim.
Pandalover

2.0 ve 2.0.1'in herhangi bir fark yaratacağından şüphelenmiyorum, ancak emülatör ile canlı bir cihaz bir fark yaratabilir. Bunun Hero'da işe yaramadığına şaşırdım. Bakacağım ve daha iyi bir cevap alıp alamayacağıma bakacağım. Oh ayrıca, tıpkı bir akıl sağlığı kontrolü olarak, manifestte INTERNET izni talep ettiğinizden emin olmalısınız.
Roman Nurik

Hey tartışma dışında bir sorum var. Mp.setDataSource (URL_OF_FILE) kullanırsam; Ses akışı için herhangi bir dosya kaydetmemize gerek yoktur. Değil mi? Bu şekilde herhangi bir konumdan ses akışı yapmanın en iyi yolu budur. Herhangi bir fikir?
Bohemian

Yanıtlar:


78

akış örneği ile basit bir Medya Oynatıcı. xml bölümü için, button_pause ve button_play adlı çekilebilir klasörünüzde id button1 ile bir düğme ve iki resim gerekir ve lütfen bildiriminize internet iznini eklemeyi unutmayın.

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;
    }
}

Bununla ilgili küçük bir sorun var, MediaPlayer oynarken telefonumu kilitlersem, kilidini açtığımda uygulamam çöküyor.
CiaranC94

3
OnPause () 'da "mediaPlayer.release ()" satırına yorum yapmayı denedim ve şimdi uygulamam kilit açıldığında kilitlenmiyor.
CiaranC94

@PiyushMishra bu özellikler geliştirici konsolu tarafından kabul ediliyor mu? Uygulamam reddedildiğinden b'coz Vitamio 4.x sürümünü kullandım
Pallavi

35

Android MediaPlayer, 2.2'ye kadar yerel olarak MP3 akışını desteklemiyor. İşletim sisteminin eski sürümlerinde, yalnızca yerel olarak 3GP akışı sağlanıyor gibi görünüyor. Cep yolculuğu kodunu deneyebilirsiniz, ancak eski olmasına rağmen (burada yeni bir sürümü var ) ve onu yapışkan hale getirme konusunda sorun yaşadım - arabelleği her doldurduğunda kekeliyordu .

Android için NPR News uygulaması açık kaynaktır ve 2.2'den önceki işletim sistemi sürümlerinde MP3 akışını işlemek için yerel bir proxy sunucusu kullanır. İlgili kodu 199-216 (r94) satırlarında burada görebilirsiniz: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/ PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Ve bu StreamProxy sınıfıdır: http://code.google.com/p/npr-android-app/source/browse/Npr/src/org/npr/android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

NPR uygulaması da yayın sırasında bazen hala "(-38, 0)" hatası alıyor. Bu bir iş parçacığı sorunu veya bir ağ değişikliği sorunu olabilir. Güncellemeler için sorun izleyiciyi kontrol edin .


Bundan kesinlikle emin misin? Anladığım kadarıyla pandomim tipi ile ilgisi vardı. T'nin 2.1 öncesi doğru MIME türü ile çalışıp çalışmadığını kontrol edebilir misiniz? Şu anda başka bir şey üzerinde çalışıyorum ve bir süre kontrol edemedim.
Pandalover

1
2.2 sürüm notlarına göre ( developer.android.com/sdk/android-2.2-highlights.html ), "yerel dosya oynatmayı ve HTTP aşamalı akışı destekleyen yeni bir medya çerçevesi (Stagefright)" içerir. Tüm testlerimde bir 2.1 cihazını doğrudan bir shoutcast sunucusundan yayınlayamadım. Sorunun, shoutcast sunucularının HTTP / 1.1 yerine bir ICY / 1.1 protokolü döndürmesi ve medya oynatıcısının bu içeriğe nasıl yanıt vereceğini bilmediği için buna takılıp kalması olduğuna inanıyorum.
jwadsack

@jwadsack ya ses dosyalarının bir kez indirilmesi gerekiyorsa ve kullanıcılar bu dosyaları çevrimdışı da oynatabiliyorsa?
Devendra Singh

@DevendraSingh Mevcut medya oynatıcı uygulamasıyla akış halindeyken dosyayı kaydedip kaydedemeyeceğinizi bilmiyorum (bu cevap neredeyse beş yaşında ve 2.2'den beri çok şey değişti). Başka bir şey yoksa, bu örneği izleyerek bir proxy oluşturabilir ve dosyayı proxy'den geçirirken depoya yazabilirsiniz.
jwadsack

11

Doğrudan bir .pls veya benzeri bir şey oynamaya çalıştığınızı tahmin ediyorum.

bunu dene:

1: kod

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

2: .pls dosyası

Bu URL, örnek olarak BBC'den alınmıştır. Linux'ta indirdiğim bir .pls dosyasıydı.

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

ve sonra vim ile açtım (favori düzenleyicinizi kullanın;) ve bu dosyanın içindeki gerçek URL'leri gördüm. Maalesef .pls'lerin tümü böyle düz metin değildir.

1.6'nın http üzerinden mp3 akışını desteklemediğini okudum, ancak yukarıdaki kodu android 1.6 ve 2.2 ile test ettim ve herhangi bir sorun yaşamadım.

iyi şanslar!


7
Müzik akışı yapmak istiyorsanız mediaplayer.prepareAsync kullanmanız gerektiğini ve mediaplayer.prepare kullanmanız gerektiğini unutmayın. Bu nedenle mediaplayer.create () işlevini kullanamazsınız, çünkü .create () işlevlerinden herhangi biri Media Player nesnenizi doğrudan Hazırlandı durumuna götürür ve buradan hazırlanmak için hazırlamanız gereken hazır Async'i çağıramazsınız. developer.android.com/reference/android/media/MediaPlayer.html
marienke

4

Kullanım

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

2

Sizinle aynı hatayı aldım ve kodda yanlış bir şey olmadığı ortaya çıktı. Sorun, web sunucusunun yanlış Content-Type başlığı göndermesiydi.

Web sunucusunun hangi içerik türünü gönderdiğini görmek için wireshark veya benzeri bir şey deneyin.


mp3 dosyaları için Content-Type olmalıdır: audio / mpeg
Sorunumu

1
O dosyayı nasıl yayınladınız?
Nauman Khalid


1

Günlükte sıfır durumunu önlemek için bir OnPreparedListener ile mp.start çağrısı yok.


Hala 05-22 günlük satırını alıyorum 20: 26: 13.625: E / MediaPlayer (23818): Media Player'ımı ready () işlevinde başlatmama rağmen 0 durumunda çağrıyı durdur. Ayrıca Media Player nesnesini sıfırladığım bir onError işlevim de var. Akışımın oynatılmaya başlaması hala 2 dakikayı buluyor. Soruma buradan bakın: stackoverflow.com/questions/16672568/…
marienke
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.