22

我正在使用 AndroidMediaPlayer播放 MP3 文件,这些文件使用DownloadManager. 我知道MediaPlayer's 直接流式传输的能力,但我不想使用它:

通过下载文件并同时从文件流式传输,您获得的明显优势是,通过这种方式,文件被存储并且之后可以在本地使用。

  • 这在原则上是有效的 -MediaPlayer即使文件没有完全下载,它也会开始播放。(顺便说一句,我的问题不是我不能MediaPlayer玩。)
  • 问题是当MediaPlayer到达下载状态刚开始播放时的位置时,它会停止并调用onCompletion. (澄清:假设我开始播放时文件下载了 12%。当播放器到达 12% 的位置时,它会停止。)
  • 快速旁注:OnBufferingUpdateListener.onBufferingUpdate(...)当某些内容通过DownloadManager.

所以问题是:如何同时将音频文件下载到文件系统并播放?(Android 4+ 就足够了,如果有区别的话。)

4

3 回答 3

9

我假设您将 MediaPlayer 指向该文件。在那种情况下,我认为它不支持流式传输,并且它可能会提前检查文件的大小等,因此随着更多文件的进入,它不会自行更新。

您必须将其指向一个可以与流一起使用的内容源,例如 HTTP。我刚刚检查了“ES 文件资源管理器”是如何做到的(使用 LogCat) - 当您单击远程文件共享中的视频文件时,它会打开一个本地 HTTP 服务器,并向 MediaPlayer 发送一个 HTTP Uri 到其本地服务器,这也包括远程路径。

当它通过 HTTP 获得请求时,本地服务器开始从远程位置读取文件,并通过 HTTP 在本地将其提供给 MediaPlayer。您可能也可以这样做,除了通过 HTTP 提供它之外,还可以将它保存到磁盘。

于 2012-12-13T19:04:41.440 回答
5

它帮助了我,我希望能帮助别人。

播放器下载和播放音乐。

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();

下载文件后:

mMediaPlayer.setDataSource(Environment.getExternalStorageDirectory() + "/Folder/" + TITLE + ".mp3");
于 2016-03-16T10:41:41.830 回答
1

我也有同样的问题。当然,当我同时使用setDataSource(video_uri)aCustomDownload(video_uri)时,它可以保存和播放,但它浪费了带宽。

我试图用其他方式制作一个伪造的阻塞FileDescriptor (FileInputStream, LocalSocket) setDataSource,但都失败了。

所以我找到了这个解决方案VideoCache

  • 它通过 http 代理服务器,与 @Oren 的答案相同。它构建一个套接字本地 http 服务器,然后侦听一个有效的 url,如http://127.0.0.1:xxxx/url_encode('your video url').

  • 当它获得一个有效的 url 时,它会创建一个套接字请求客户端来下载该 url,并将流发送到127.0.0.1. 这样你就可以setDataSource('http://127.0.0.1:xxxx/your video's encode url')

  • 使用一次下载,保存和播放。并且它可以创建一个单例服务器,再启动一个 Activity(lifecycle),所以我可以使用它android.intent.action.SEND或其他LAUNCHER.

这是一个完美的解决方案。

注意:您必须关闭缓存限制。否则 VideoCache 将在缓存大小为 512MB(默认)时清除所有数据。

于 2018-05-21T08:06:05.220 回答