audio – Android Media Player: Download to File and Stream From File-ThrowExceptions

Exception or error:

I’m using Android’s MediaPlayer to play MP3 files that are simultaneously downloaded from the internet using the DownloadManager. I’m aware of the MediaPlayer‘s capability to stream directly, but I don’t want to use that:

The obvious advantage you get by downloading and simultaneously streaming from file is that this way, the file gets stored and is available locally afterwards.

  • This works in principle – the MediaPlayer starts to play the file even if it not fully downloaded. (BTW my problem is NOT that I can’t get MediaPlayer to play.)
  • The problem is that when the MediaPlayer gets to the position where the download status just was when it started playing, it stops and calls onCompletion. (Clarification: Let’s assume the file is 12% downloaded when I start playing. When the player gets to the position at 12%, it stops.)
  • Quick side note: OnBufferingUpdateListener.onBufferingUpdate(...) is not called when something is appended to the MP3 file via the DownloadManager.

So the question is: How can I simultaneously download an audio file to the file system and play it? (Android 4+ suffices, if that makes a difference.)

How to solve:

I assume you’re pointing MediaPlayer to the file. In that case I don’t think it supports streaming, and it probably checks the size of the file and such in advance, so it won’t update itself as more of the file comes in.

You have to point it to a content source that will work with streaming, e.g. HTTP.
I’ve just checked how “ES File Explorer” does it (Using LogCat) – when you click on a video file in a remote file share, it opens an local HTTP server, and sends to the MediaPlayer an HTTP Uri to its local server, that also includes the remote path.

When it gets the request through HTTP, the local server starts reading the file from the remote location, and providing it locally to MediaPlayer through HTTP.
You can probably do the same, and in addition to providing it via HTTP also save it to disk.

###

It helped me, I hope to help someone else.

Player download & play music.

mMediaPlayer.setDataSource(DOWNLOAD_URL);

   File root = Environment.getExternalStorageDirectory();
   File dir = new File(root + "/Folder");
   if (!dir.exists()) {
        dir.mkdirs();

DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
            Uri downloadUri = Uri.parse(DOWNLOAD_URL);
            DownloadManager.Request request = new DownloadManager.Request(downloadUri);
            request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
            request.setAllowedOverRoaming(false);
            request.setTitle(TITLE);
            request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
            request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC, TITLE);
            request.allowScanningByMediaScanner();

After downloading file:

mMediaPlayer.setDataSource(Environment.getExternalStorageDirectory() + "/Folder/" + TITLE + ".mp3");

###

I have the same problem. Of course, When I use setDataSource(video_uri) and aCustomDownload(video_uri) at the same time, it can save and play, but it wasted bandwidth.

I tried to make a fake blocking FileDescriptor(FileInputStream, LocalSocket) to setDataSource, and other ways, but all of them were failed.

So I found this solution, VideoCache.

  • It via a http proxy server, same as @Oren ‘s answer.
    It builds a socket local http server , Then listening for a valid url like http://127.0.0.1:xxxx/url_encode('your video url').

  • When it gets a valid url, it creates a socket request client to download the url, and send the stream to server of 127.0.0.1.
    SO you can setDataSource('http://127.0.0.1:xxxx/your video's encode url')

  • Use once download, save and play. And it can made a singleton server with one more Activity(lifecycle) lauching, so I can use it from android.intent.action.SEND or other LAUNCHER.

It’s a prefect solution.

Notice: you must turn off the cache limit. otherwise VideoCache will clear all data when cache size was 512MB(default).

Leave a Reply

Your email address will not be published. Required fields are marked *