Подтвердить что ты не робот

Android - Воспроизведение mp3 с байта []

У меня есть mp3 файл в байте [] (скачан из службы), и я хотел бы воспроизвести его на своем устройстве, аналогично тому, как вы можете воспроизводить файлы:

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

Но я не могу найти способ сделать это. Я бы не прочь сохранить файл на телефоне, а затем воспроизвести его. Как я могу воспроизвести файл или загрузить его?

4b9b3361

Ответ 1

Хорошо, спасибо всем, но мне нужно было играть в mp3 с байта [], как я получаю это от .NET webservice (не хочу хранить динамически созданные mp3 на сервере).

В конце - есть число "gotchas" для воспроизведения простой mp3... вот код для тех, кто в ней нуждается:

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

РЕДАКТИРОВАТЬ: Я написал этот ответ более 4 лет назад - очевидно, с тех пор многое изменилось. См. Комментарий Justin о том, как повторно использовать экземпляр MediaPlayer. Кроме того, я не знаю, будет ли теперь .deleteOnExit() работать для вас - не стесняйтесь предлагать улучшения, чтобы временные файлы не накапливались.

Ответ 2

Не уверен в bytearrays/bytestreams, но если у вас есть URL-адрес из службы, вы можете попробовать установить источник данных в сетевой URI, вызвав

setDataSource(Context context, Uri uri)

См. API-документы.

Ответ 3

Я нашел легкое решение, закодировав свой MP3 файл как Base64 (я уже получил данные, закодированные из службы Restful API), а затем создав объект URL. Я тестировал его в Android 4.1.

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

Ответ 5

неправильный код:

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

ПРАВИЛЬНЫЙ КОД:

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

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

см. API Demos..

Ответ 6

Запуск Android MarshMellow (код версии 23), есть новый API, который сделает это возможным.

MediaPlayer.setDataSource(android.media.MediaDataSource)

Вы можете предоставить пользовательскую реализацию MediaDataSource и обернуть байт []. Ниже приведена базовая реализация.

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