wake-up-neo.net

Android - MP3 aus Byte spielen []

Ich habe meine MP3-Datei in Byte [] (von einem Dienst heruntergeladen) und möchte sie auf meinem Gerät ähnlich wie Sie Dateien abspielen können:

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

Aber ich finde keinen Weg, es zu tun. Ich hätte nichts dagegen, Dateien auf dem Telefon zu speichern und sie dann abzuspielen. Wie kann ich die Datei abspielen oder herunterladen und abspielen?

29
kape123

OK, danke an alle, aber ich musste mp3 von Byte [] abspielen, da ich das vom .NET-Webservice bekomme (ich möchte keine dynamisch generierten MP3-Dateien auf dem Server speichern).

Am Ende gibt es eine Reihe von "Gotchas", um einfache MP3s abzuspielen. Hier ist der Code für jeden, der es braucht:

private MediaPlayer mediaPlayer = new MediaPlayer();
private void playMp3(byte[] mp3SoundByteArray) {
    try {
        // create temp file that will hold byte array
        File tempMp3 = File.createTempFile("kurchina", "mp3", getCacheDir());
        tempMp3.deleteOnExit();
        FileOutputStream fos = new FileOutputStream(tempMp3);
        fos.write(mp3SoundByteArray);
        fos.close();

        // resetting mediaplayer instance to evade problems
        mediaPlayer.reset();

        // In case you run into issues with threading consider new instance like:
        // MediaPlayer mediaPlayer = new MediaPlayer();                     

        // Tried passing path directly, but kept getting 
        // "Prepare failed.: status=0x1"
        // so using file descriptor instead
        FileInputStream fis = new FileInputStream(tempMp3);
        mediaPlayer.setDataSource(fis.getFD());

        mediaPlayer.prepare();
        mediaPlayer.start();
    } catch (IOException ex) {
        String s = ex.toString();
        ex.printStackTrace();
    }
}

EDIT: Ich habe diese Antwort vor mehr als 4 Jahren geschrieben - offensichtlich haben sich seitdem viele Dinge geändert. Siehe Justins Kommentar zur Wiederverwendung der MediaPlayer-Instanz. Ich weiß auch nicht, ob .deleteOnExit () jetzt für Sie funktionieren wird - schlagen Sie Verbesserungsvorschläge vor, damit sich temporäre Dateien nicht stauen.

73
kape123

Ich habe eine einfache Lösung gefunden, indem ich meine MP3-Datei als Base64 codierte (ich empfange bereits die von einem Restful-API-Dienst codierten Daten) und dann ein URL-Objekt erstellt. Ich habe es in Android 4.1 getestet.

public void PlayAudio(String base64EncodedString){
        try
        {
            String url = "data:audio/mp3;base64,"+base64EncodedString; 
            MediaPlayer mediaPlayer = new MediaPlayer();
            mediaPlayer.setDataSource(url);
            mediaPlayer.prepare();
            mediaPlayer.start();
        }
        catch(Exception ex){
            System.out.print(ex.getMessage());
        }
    }
9
Max Vargas

Mit Android MarshMellow (Versionscode 23) gibt es eine neue API, die dies ermöglicht.

MediaPlayer.setDataSource (Android.media.MediaDataSource)

Sie können eine benutzerdefinierte Implementierung von MediaDataSource bereitstellen und ein Byte [] umschließen. Eine grundlegende Implementierung wird unten gegeben.

import Android.annotation.TargetApi;
import Android.media.MediaDataSource;
import Android.os.Build;
import Java.io.IOException;


@TargetApi(Build.VERSION_CODES.M)
public class ByteArrayMediaDataSource extends MediaDataSource {

    private final byte[] data;

    public ByteArrayMediaDataSource(byte []data) {
        assert data != null;
        this.data = data;
    }
    @Override
    public int readAt(long position, byte[] buffer, int offset, int size) throws IOException {
        System.arraycopy(data, (int)position, buffer, offset, size);
        return size;
    }

    @Override
    public long getSize() throws IOException {
        return data.length;
    }

    @Override
    public void close() throws IOException {
        // Nothing to do here
    }
}
6
krishnakumarp

Über Bytearrays/bytestreams sind Sie nicht sicher. Wenn Sie jedoch eine URL des Dienstes haben, können Sie versuchen, die Datenquelle durch Aufrufen als Netzwerk-URI festzulegen 

setDataSource(Context context, Uri uri)

Siehe die API-Dokumente .

5
Yoni Samlan

falscher Code:

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

RICHTIGER CODE:

 MediaPlayer mp = new MediaPlayer();
 mp.setDataSource(PATH_TO_FILE);
 mp.setOnpreparedListener(this);
 mp.prepare();

//Implement OnPreparedListener 
OnPrepared() {
    mp.start();
 }

siehe API Demos ..

1
subbarao

Wenn Sie auf API 23 und höher abzielen, erstellen Sie eine solche Klasse

class MyMediaDataSource(val data: ByteArray) : MediaDataSource() {

override fun readAt(position: Long, buffer: ByteArray, offset: Int, size: Int): Int {

    if (position >= data.size) return -1 // -1 indicates EOF 

    val endPosition: Int = (position + size).toInt()
    var size2: Int = size
    if (endPosition > data.size)
        size2 -= endPosition - data.size

    System.arraycopy(data, position.toInt(), buffer, offset, size2)
    return size2
}

override fun getSize(): Long {
    return data.size.toLong()
}

override fun close() {}

}

und so verwenden 

val mediaSource = MyMediaDataSource(byteArray)
MediaPlayer().apply {
    setAudioStreamType(AudioManager.STREAM_MUSIC)
    setDataSource(mediaSource)
    setOnCompletionListener { release() }
    prepareAsync()
    setOnPreparedListener { start() }
}

kredite an die Antwort von krishnakumarp und an diesen Artikel

0
Dan Alboteanu