MediaPlayerのプロキシとしてソケットを使用しているため、ソケットに書き込む前にmp3オーディオをダウンロードして復号化できます。これはNPRニュースアプリに表示される例に似ていますが、Androidバージョン2.1-4 atmのすべてに使用しています。
NPR StreamProxyコード- http://code.google.com/p/npr-Android-app/source/browse/Npr/src/org/npr/Android/news/StreamProxy.Java
私の問題は、2.1〜2.3の再生が速いことですが、Android 4.0 ICS MediaPlayerは、onPreparedリスナーを起動する前に、あまりにも多くのデータをバッファリングします。
OnPrepared()の前にSocket OutputStreamに書き込まれるデータ量の例:
2.3.4がインストールされたSGS2の場合-133920バイト以降のonPrepared()
4.0.4を搭載したNexus Sの場合-961930バイト以降のonPrepared()
これはGalaxy Nexusでも発生します。
奇妙なことに、4.0エミュレータは4.0デバイスほどのデータをバッファリングしません。だれでもICSのMediaPlayerで同様の問題が発生しますか?
編集
プロキシがソケットに書き込む方法は次のとおりです。この例では、ファイルから読み込まれたCipherInputStreamからのものですが、HttpResponseから読み込まれたときにも同じことが起こります。
final Socket client = (setup above)
// encrypted file input stream
final CipherInputStream inputStream = getInputStream(file);
// setup the socket output stream
final OutputStream output = client.getOutputStream();
// Writing the header
final String httpHeader = buildHttpHeader(file.length());
final byte[] buffer = httpHeader.getBytes("UTF-8");
output.write(buffer, 0, buffer.length);
int writtenBytes = 0;
int readBytes;
final byte[] buff = new byte[1024 * 12]; // 12 KB
while (mIsRunning && (readBytes = inputStream.read(buff)) != -1) {
output.write(buff, 0, readBytes);
writtenBytes += readBytes;
}
output.flush();
output.close();
オーディオの前にMediaPlayerに書き込まれるHTTPヘッダー。
private String buildHttpHeader(final int contentLength) {
final StringBuilder sb = new StringBuilder();
sb.append("HTTP/1.1 200 OK\r\n");
sb.append("Content-Length: ").append(contentLength).append("\r\n");
sb.append("Accept-Ranges: bytes\r\n" );
sb.append("Content-Type: audio/mpeg\r\n");
sb.append("Connection: close\r\n" );
sb.append("\r\n");
return sb.toString();
}
私は代替の実装を探しましたが、オーディオを暗号化していて、MediaPlayerがデータソースとしてInputStreamsをサポートしていないため、私のような唯一のオプションは、このようなプロキシを使用することです。
繰り返しますが、これはかなりうまく機能していますAndroid 2.1-2.3ですが、ICSではMediaPlayerが再生する前にこのデータを大量にバッファリングしています。
編集2:
さらにテストを行ったところ、これはSGS2でもAndroid 4.0.3にアップグレードされた場合の問題です。したがって、MediaPlayerのバッファリング実装が4.0で大幅に変更されたようです。これはAPIとしてイライラします。動作を変更する方法はありません。
編集3:
Androidのバグが作成されました。コメントを追加して、そこにもスターを付けてください http://code.google.com/p/Android/issues/detail?id=2987
編集4:
私の再生コードはかなり標準的なものです。MediaPlayerのonPrepared()メソッドでstart()を呼び出しています。
mCurrentPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mCurrentPlayer.setDataSource(url);
mCurrentPlayer.prepareAsync();
Prepare()とajacian81の推奨される方法を使用して試したが、役に立たなかった。
最近Googleの従業員が私の質問について返答し、ICS(HDコンテンツの場合)でバッファサイズが意図的に増加したことを確認しました。API開発者にリクエストされました。 MediaPlayerでバッファサイズを設定する機能を追加します。
このAPI変更リクエストは私が来る前に存在していたと思いますが、息を止めるようにアドバイスするつもりはありません。
MediaPlayerを開始()しているコードを確認することはできますか?
STREAM_MUSIC
オーディオストリームタイプを使用していますか?
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
Player.prepareAsync();の間でも実験をしましたか。そしてplayer.prepare();?
昨年覚えていた同様の問題がありました。解決策は、開始、一時停止、そしてonPrepared to start()です。
player.setAudioStreamType(AudioManager.STREAM_MUSIC);
player.setDataSource(src);
player.prepare();
player.start();
player.pause();
player.setOnPreparedListener(new OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
player.start();
}
});
この場合は修正される可能性は低いですが、ホイールを回転させている間、これは一撃の価値があるかもしれません。
私にとっての解決策は、AudioTrackでMediaCodecを使用することでした。
これは解決策になる可能性があります: http://www.piterwilson.com/blog/2014/03/15/mediacodec-mediaextractor-and-audiotrack-to-the-rescue/