2012-04-04 78 views
3

我有byte []数组,其中包含mp3文件。有没有办法如何播放mp3文件而不创建临时文件?Android - 从字节[]数组播放mp3

感谢

编辑:

我试图临时文件的方法:

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

而且我仍然得到NullPointerException异常。我正在写文件的字节数组(称为字节),我保持其引用并使用它。但仍然获得NPE。你知道错误在哪里吗?

+0

该文件可以是.wav吗? (实际上,在PCM) – NitroG42 2012-04-04 14:44:11

+0

不,只是MP3文件 – Waypoint 2012-04-04 14:45:11

+0

编辑和添加的问题 – Waypoint 2012-04-04 15:15:20

回答

2

我假设你正在使用MediaPlayer,直到最新的API是没有办法来设置byte[]格式的数据只是作为一个String(路径),FileDescriptorUri所以恐怕你将不得不写临时File

+3

哦,那很差... – Waypoint 2012-04-04 14:44:52

+0

你会告诉我如何将MP3格式转换为字节数组。 – Joyson 2012-10-10 21:06:35

1

Android提供非常低级别的API(AudioTrack)将原始PCM数据直接写入声音硬件。

+0

不幸的是,它不能用于mp3。 – NitroG42 2012-04-04 14:55:34

+1

如果您使用mp3解码器将mp3字节数组解码为原始数据并将其提供给AudioTrack,它将会生效。 – bhups 2012-04-04 15:04:15

+0

用于解码它,常见的解决方案是使用临时文件... – NitroG42 2012-04-04 15:34:34

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

我知道这是老了,但我搜索的答案,并没有发现任何这确实允许从一个字节数组没有临时文件的播放,而且确实有一个非常简单的方法,创建自定义MediaDataSource。

我在这里发布Xamarin Android的代码,但它很容易移植到Java,问题是你可以看到它的方法。

请注意,这些方法是在Android 6.0 SDK上添加的,如果您定位的是较低版本的Android,则必须使用正确的兼容性支持库。

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

这看起来很大,但它会出现Xamarin当前没有露出MediaDataSource类或API的setDataSource接受一个MediaDataSource。 – Glenn 2016-05-20 17:16:26

+0

呃......这些代码是从我的项目中提取,我用它...只是增加一个“使用Android.Media;”和“使用Java.IO”它应该工作。 – Gusman 2016-05-24 07:26:22

+0

啊,我看到它是在Android 6.0/API 23中添加的。猜猜我们需要一个适用于早期Android版本的兼容性库。 – Glenn 2016-05-25 16:57:56