【问题标题】:Android Media Player: Download to File and Stream From FileAndroid 媒体播放器:下载到文件并从文件流式传输
【发布时间】:2012-12-13 16:03:40
【问题描述】:

我正在使用 Android 的 MediaPlayer 播放使用 DownloadManager 同时从 Internet 下载的 MP3 文件。我知道MediaPlayer 可以直接流式传输,但我不想使用它:

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

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

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

【问题讨论】:

  • 你的流媒体怎么样?通过实现一个简单的本地主机服务器,它从下载文件中读取数据并将其提供给已设置为从本地主机流式传输的 MediaPlayer?在这种情况下,你不能让你的服务器返回一个匹配或超过文件全长的 Content-Length 吗?
  • 好吧,我只是将 MediaPlayer 指向当前的文件并将其模式设置为 STREAM_BLAH(无论它实际上被称为什么)。所以我目前没有服务器。
  • 嗨 Hinton,我必须按照您的要求做同样的事情,您能否发布一个答案(详细说明)您是如何做到的,以便我可以实施它。
  • 我现在很忙,但是如果您在阅读本文后仍然想要它,我会在几天内尝试回答。问题:我最后实现的东西很丑。我尝试了 Oren 的方法(这显然是最好的、正确的解决方案),但这对我来说并不太重要,所以我决定默认从 URL 流式传输,让用户告诉我他们是否想下载。在后一种情况下,我会在下载时从 URL 流式传输(是的:浪费带宽),下载完成后,当用户暂停时,我会从流式传输切换到下载的文件。
  • 继续:这非常有效。问题是浪费的带宽。如果您是为不太专心且不了解 android 编程的客户执行此操作,他们将永远不会注意到。它至少作为一个临时解决方案起作用——客户告诉你“我想要这个功能”——那么显然最好快速实施任何事情并在你有时间的时候尝试修复它(=“从不”,如果你是一个愤世嫉俗的人人)。

标签: android audio download streaming media-player


【解决方案1】:

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

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

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

【讨论】:

【解决方案2】:

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

播放器下载和播放音乐。

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

【讨论】:

  • 这段代码会下载文件两次吗?一次通过媒体播放器,第二次通过下载管理器?还是下载管理器能够从媒体播放器中获取文件?
【解决方案3】:

我也有同样的问题。当然,当我同时使用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时,它会创建一个socket请求客户端来下载url,并将流发送到127.0.0.1的服务器。 所以你可以setDataSource('http://127.0.0.1:xxxx/your video's encode url')

  • 使用一次下载、保存和播放。而且它可以使单例服务器多启动一个Activity(生命周期),所以我可以从android.intent.action.SEND或其他LAUNCHER使用它。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-19
    • 2017-10-08
    • 1970-01-01
    相关资源
    最近更新 更多