Byte [](サービスからダウンロード)にmp3ファイルがあり、ファイルを再生する方法と同じようにデバイスで再生したいと思います。
MediaPlayer mp = new MediaPlayer();
mp.setDataSource(PATH_TO_FILE);
mp.prepare();
mp.start();
しかし、私はそれを行う方法を見つけることができないようです。ファイルを電話に保存してから再生してもかまいません。ファイルを再生、またはダウンロードして再生するにはどうすればよいですか?
皆さん、ありがとうございます。ただし、byte []からmp3を再生する必要がありました。これは.NET Webサービスから取得するためです(動的に生成された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年以上前にこの答えを書いてきました-それから明らかに多くのことが変わっています。 MediaPlayerインスタンスを再利用する方法に関するJustinのコメントを参照してください。また、.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
}
}
Bytearrays/bytestreamsについてはわかりませんが、サービスからのURLがある場合は、次を呼び出してネットワークURIにデータソースを設定してみてください。
setDataSource(Context context, Uri uri)
APIドキュメント を参照してください。
不正なコード:
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デモを参照してください。
API 23以降をターゲットとする場合、次のようなクラスを作成します
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の回答と この記事