86 votes

Streaming audio à partir d'une URL dans Android avec MediaPlayer ?

J'ai essayé de diffuser des mp3 sur http en utilisant la classe MediaPlayer intégrée d'Android. La documentation me laisse penser que cela devrait être aussi simple que :

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

Cependant, j'obtiens le résultat suivant à plusieurs reprises. J'ai également essayé différentes URL. Ne me dites pas que le streaming ne fonctionne pas sur les 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)

Toute aide est la bienvenue, merci. S

77voto

PiyushMishra Points 2258

Pour la partie xml vous avez besoin d'un bouton avec l'id button1 et deux images dans votre dossier drawable avec le nom button_pause et button_play et n'oubliez pas d'ajouter la permission internet dans votre manifeste.

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

35voto

jwadsack Points 2073

Android MediaPlayer ne prend pas en charge le streaming de MP3 en natif avant la version 2.2. Dans les versions plus anciennes du système d'exploitation, il semble que le streaming 3GP ne soit pas pris en charge. Vous pouvez essayer le code de pocketjourney, bien qu'il soit ancien (il y a une version de nouvelle version ici ) et j'ai eu du mal à le rendre collant - il bégayait à chaque fois qu'il remplissait le tampon.

L'application NPR News pour Android est open source et utilise un serveur proxy local pour gérer le streaming MP3 dans les versions de l'OS antérieures à 2.2. Vous pouvez voir le code correspondant dans les lignes 199-216 (r94 http://code.google.com/p/npr-Android-app/source/browse/Npr/src/org/npr/Android/news/PlaybackService.java?r=7cf2352b5c3c0fbcdc18a5a8c67d836577e7e8e3

Et voici la classe StreamProxy : http://code.google.com/p/npr-Android-app/source/browse/Npr/src/org/npr/Android/news/StreamProxy.java?r=e4984187f45c39a54ea6c88f71197762dbe10e72

L'application NPR continue également à obtenir l'"erreur (-38, 0)" parfois pendant la diffusion. Cela peut être un problème de threading ou un problème de changement de réseau. Vérifiez le suivi des problèmes pour les mises à jour .

10voto

Pabluez Points 1622

Je suppose que vous essayez de lire directement un .pls ou quelque chose de similaire.

Essayez ceci :

1 : le code

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

2 : le fichier .pls

Cette URL est celle de la BBC, à titre d'exemple. Il s'agissait d'un fichier .pls que j'ai téléchargé sous linux avec

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

et ensuite j'ai ouvert avec vim (utilisez votre éditeur préféré ;) et j'ai vu les vraies URLs dans ce fichier. Malheureusement, tous les .pls ne sont pas en texte brut comme ça.

J'ai lu que la version 1.6 ne supportait pas le streaming mp3 sur http, mais je viens de tester le code ci-dessus avec Android 1.6 et 2.2 et je n'ai eu aucun problème.

Bonne chance !

2voto

doep Points 91

J'ai eu la même erreur que vous et il s'est avéré qu'il n'y avait aucun problème avec le code. Le problème était que le serveur web envoyait le mauvais en-tête Content-Type.

Essayez wireshark ou quelque chose de similaire pour voir quel type de contenu le serveur web envoie.

1voto

Fred Grott Points 2004

Pas d'appel mp.start avec un OnPreparedListener pour éviter l'état zéro i le log..

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X