6

I have byte[] array, which contains mp3 file. Is there any way how to play mp3 file without creating temporary file?

Thanks

Edited:

I have tried temporary file approach:

                File tempMp3 = File.createTempFile("test", ".mp3", getCacheDir());

                //tempMp3.deleteOnExit();
                FileOutputStream fos = new FileOutputStream(tempMp3);
                fos.write(bytes);
                fos.close();

                mediaPlayer = MediaPlayer.create(getApplicationContext(),Uri.fromFile(tempMp3));
                mediaPlayer.start();

And I am still getting the NullPointerException. I am writing byte array (called bytes) to file, I am keeping its referrence and using it. But still getting NPE. Do you know where is the mistake?

Waypoint
  • 17,283
  • 39
  • 116
  • 170

5 Answers5

2

I am assuming you are using MediaPlayer and until the latest API there is no way to set the data in byte[] format just as a String(path), FileDescriptor, or Uri so I am afraid that you will have to write a temporary File.

Ovidiu Latcu
  • 71,607
  • 15
  • 76
  • 84
2
private void playByteArray(byte[] mp3SoundByteArray) {
    try {
        File Mytemp = File.createTempFile("TCL", "mp3", getCacheDir());
        Mytemp.deleteOnExit();
        FileOutputStream fos = new FileOutputStream(Mytemp);
        fos.write(mp3SoundByteArray);
        fos.close();

        MediaPlayer mediaPlayer = new MediaPlayer();

        FileInputStream MyFile = new FileInputStream(Mytemp);
        mediaPlayer.setDataSource(Mytemp.getFD());

        mediaPlayer.prepare();
        mediaPlayer.start();
    } catch (IOException ex) {
        String s = ex.toString();
        ex.printStackTrace();
    }
}
jogo
  • 12,469
  • 11
  • 37
  • 42
1

Android provide a very low level API (AudioTrack) to write raw PCM data directly to sound hardware.

bhups
  • 14,345
  • 8
  • 49
  • 57
  • 2
    It will if you decode the mp3 byte array to raw data using a mp3 decoder and feed it to AudioTrack. – bhups Apr 04 '12 at 15:04
0

With tmpFile, follow that post : Android - Playing mp3 from byte[]

If it still npe, check if your file (tempMp3) is not null, and if Uri.fromFile return an uri and not null.

Community
  • 1
  • 1
NitroG42
  • 5,336
  • 2
  • 28
  • 32
0

I know this is old, but I searched for an answer and didn't found any which really allows to play from a byte array without temp files, and indeed there is a very easy way, creating a custom MediaDataSource.

I'm posting here the code for Xamarin Android, but it's very easily ported to Java, the question is you can see the method to do it.

Note that these methods were added on the android 6.0 SDK, if you target lower versions of Android you must use the correct compatibility support library.

public class AudioPlayer
{
    MediaPlayer currentPlayer;

    public void Play(byte[] AudioFile, bool Loop)
    {
        Stop();

        currentPlayer = new MediaPlayer();
        currentPlayer.Prepared += (sender, e) =>
        {
            currentPlayer.Start();
        };
        currentPlayer.Looping = Loop;
        currentPlayer.SetDataSource(new StreamMediaDataSource(new System.IO.MemoryStream(AudioFile)));
        currentPlayer.Prepare();
    }

    public void Stop()
    {
        if (currentPlayer == null)
            return;

        currentPlayer.Stop();
        currentPlayer.Dispose();
        currentPlayer = null;
    }
}

public class StreamMediaDataSource : MediaDataSource
{
    System.IO.Stream data;

    public StreamMediaDataSource(System.IO.Stream Data)
    {
        data = Data;
    }

    public override long Size
    {
        get
        {
            return data.Length;
        }
    }

    public override int ReadAt(long position, byte[] buffer, int offset, int size)
    {
        data.Seek(position, System.IO.SeekOrigin.Begin);                
        return data.Read(buffer, offset, size);
    }

    public override void Close()
    {
        if (data != null)
        {
            data.Dispose();
            data = null;
        }
    }

    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);

        if (data != null)
        {
            data.Dispose();
            data = null;
        }
    }
}
Gusman
  • 14,905
  • 2
  • 34
  • 50
  • This looks great but it would appear that Xamarin is not currently exposing the MediaDataSource class or the SetDataSource api that takes a MediaDataSource. – Glenn May 20 '16 at 17:16
  • Er... that code is extracted from my project and I'm using it...Just add an "using Android.Media;" and "using Java.IO;" and it should work. – Gusman May 24 '16 at 07:26
  • Ahh, I see it was added in Android 6.0/API 23. Guess we'd need a compatibility library for earlier Android releases. – Glenn May 25 '16 at 16:57
  • Yes, you're right, I'm updating the post to denote it. – Gusman May 26 '16 at 12:18
  • Do you know which compatibility support library to use? – Illedan Nov 12 '16 at 15:20