I want to cache data while playing it in MediaPlayer. As I read, there is one way to do it - create own local http server and set local url to MediaPlayer's setDataSource(String path).
I am using NanoHTTPD as a local server. There is code of serve function:
@Override public Response serve(String uri, Method method, Map headers, Map parms, Map files) { try { // delete / character URL url = new URL(uri.substring(1)); URLConnection connection = url.openConnection(); connection.connect(); File cacheFolder = new File(Environment.getExternalStorageDirectory(), "TracksFlowCacheNew"); Log.e("RelayServer", "Cache to file " + Utils.md5(url.toExternalForm())); RelayInputStream ris = new RelayInputStream(connection.getInputStream(), new FileOutputStream(new File(cacheFolder, Utils.md5(url.toExternalForm())))); return new Response(Response.Status.OK, NanoHTTPD.MIME_DEFAULT_BINARY, ris); } catch(MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch(FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch(IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; }
RelayInputStream extending InputStream. I am trying to cache data there:
private class RelayInputStream extends InputStream { private InputStream mInputStream = null; private OutputStream mOutputStream = null; public RelayInputStream(InputStream is, OutputStream os) { mInputStream = is; mOutputStream = os; } @Override public int available() throws IOException { Log.e("available", "available = " + mInputStream.available()); mInputStream.mark(mInputStream.available()); return mInputStream.available(); } @Override public int read(byte[] buffer) throws IOException { Log.e("read", "buffer = " + buffer.toString()); mOutputStream.write(buffer); return mInputStream.read(buffer); } @Override public int read(byte[] buffer, int offset, int length) throws IOException { Log.e("read", "buffer = " + buffer.toString() + "; offset = " + offset + "; length = " + length); mOutputStream.write(buffer, offset, length); return mInputStream.read(buffer, offset, length); } @Override public int read() throws IOException { Log.e("read", "no data"); byte[] b = new byte[1]; mInputStream.read(b); mOutputStream.write(b); mInputStream.close(); mOutputStream.close(); return b[0] & 0xff; } }
But RelayInputStream's available returns only few downloaded bytes. So, there is only little part of data cached and returned to the media player. So, what am I doing wrong? How to forward and cache all stream?
mOutputStream.write(buffer);
. You have that statement in two read() functions. But that buffer is empty as read() is a request to fill that buffer. So that statement there is not ok. – Bouffeway to save music stream to storage while playing
. That is something quite different from caching. Please explain better what you want. – Boufferead
methods, except last one, I didmOutputStream.write(buffer)
, whilebuffer
is known to be empty. So maybe you shall swapmInputStream.read(buffer)
andmOutputStream.write(buffer)
and it will work.. But idk. – Selfpreservation