我有一个以byte[]格式的mp3文件(从服务中下载),我希望像播放其他文件一样在我的设备上播放它:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();
但我似乎找不到方法。我不介意把文件保存到手机上,然后再播放它。如何播放该文件,或者下载后再播放它?
我有一个以byte[]格式的mp3文件(从服务中下载),我希望像播放其他文件一样在我的设备上播放它:
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();
但我似乎找不到方法。我不介意把文件保存到手机上,然后再播放它。如何播放该文件,或者下载后再播放它?
好的,感谢大家的回答,但我需要从byte[]中播放mp3文件,因为我是从.NET webservice获取的(不希望在服务器上存储动态生成的mp3文件)。
最终,要播放简单的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()现在是否适用于您 - 请随意建议改进措施,以免临时文件堆积。
我通过将我的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());
}
}
从Android MarshMellow (版本代码23)开始,有一种新的API可以实现这一点。
MediaPlayer.setDataSource(android.media.MediaDataSource)
您可以提供MediaDataSource的自定义实现并包装一个byte[]。下面是一个基本的实现。
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
}
}
如果你对字节数组/字节流不确定,但是如果你有一个来自服务的URL,你可以尝试通过调用将数据源设置为网络URI。
setDataSource(Context context, Uri uri)
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() {}
}
val mediaSource = MyMediaDataSource(byteArray)
MediaPlayer().apply {
setAudioStreamType(AudioManager.STREAM_MUSIC)
setDataSource(mediaSource)
setOnCompletionListener { release() }
prepareAsync()
setOnPreparedListener { start() }
}
感谢krishnakumarp上面的回答以及这篇文章
setAudioAttributes(AudioAttributes.Builder().setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED).setLegacyStreamType(AudioManager.STREAM_MUSIC).setUsage(AudioAttributes.USAGE_GAME).setContentType(AudioAttributes.CONTENT_TYPE_MUSIC).build())
而不是现在已弃用的 setAudioStreamType(...)
。 - user1300214 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 演示...