首页 > 解决方案 > 当原始 URL 需要标头时,从缓存中播放 ExoPlayer 失败

问题描述

我的 MediaItem 是从 Uri 创建的,带有我使用的标头(需要身份验证):

DefaultHttpDataSource.Factory().setUserAgent(Util.getUserAgent(context, context.resources.getString(R.string.app_name))).setDefaultRequestProperties(Collections.singletonMap("Authorization", "Bearer $token"))

然后我使用以下方法将其存储在缓存中:

fun downloadMedia(url: String, mediaItem: MediaItem, metadata: String) {
        //the download request
        val helper = DownloadHelper.forMediaItem(this, mediaItem)
        helper.prepare(object : DownloadHelper.Callback {
            override fun onPrepared(helper: DownloadHelper) {
                val download =
                    helper.getDownloadRequest(url, Util.getUtf8Bytes(metadata))
                //sending the request to the download service
                DownloadService.sendAddDownload(
                    this@MainActivity,
                    MyDownload::class.java,
                    download,
                    true
                )
            }

            override fun onPrepareError(helper: DownloadHelper, e: IOException) {
                e.printStackTrace()
                Toast.makeText(this@MainActivity, e.localizedMessage, Toast.LENGTH_SHORT).show()
            }
        })

    }

然后我通过检查一个项目是否已经缓存来创建播放列表,添加缓存的项目,否则从 url 获取,如下所示:

downed = (activity as MainActivity).getDownloadedItems().contains(mediaItem)
            if (downed) {

                val dataSourceFactory = DefaultDataSourceFactory(
                    requireContext(), Util.getUserAgent(
                        requireContext(), getString(
                            R.string.app_name
                        )
                    )
                )
                val cachedDataSourceFactory = CacheDataSource.Factory()
                    .setCache((requireContext().applicationContext as App).appContainer.downloadCache)
                    .setCacheReadDataSourceFactory(
                        dataSourceFactory
                    )

                val mediaSource =
                    ProgressiveMediaSource.Factory(cachedDataSourceFactory).createMediaSource(
                        mediaItem
                    )
                podcastPlaylistSources.add(mediaSource)
            } else {
                val properties = HashMap<String, String>()
                properties["Authorization"] = "Bearer $token"

                val dataSourceFactory: DataSource.Factory = DefaultHttpDataSource.Factory().setUserAgent(Util.getUserAgent(requireContext(), requireContext().resources.getString(R.string.app_name))).setDefaultRequestProperties(Collections.singletonMap("Authorization", "Bearer $token"))

                val mediaSource: MediaSource = ProgressiveMediaSource.Factory(dataSourceFactory)
                    .createMediaSource(mediaItem)
                podcastPlaylistSources.add(mediaSource)
            }

这是我的问题:当我从中获取 mp3 的 URL 只是一个常规打开的 mp3 流时,没问题,工作正常。但是,当我有一个需要标头进行身份验证的 URL 时,流媒体很好,它存储得很好,但是当我想从缓存中播放时,我得到:

ExoPlaybackException: Source error
Caused by: com.google.android.exoplayer2.source.UnrecognizedInputFormatException: None of the available extractors (FlvExtractor, FlacExtractor, WavExtractor, FragmentedMp4Extractor, Mp4Extractor, AmrExtractor, PsExtractor, OggExtractor, TsExtractor, MatroskaExtractor, AdtsExtractor, Ac3Extractor, Ac4Extractor, Mp3Extractor, JpegExtractor) could read the stream.
        

与常规流中的缓存项与 header-needing-stream 有何不同?我该如何解决我的问题?

编辑: 可能是 DownloadRequest 需要标头吗?

标签: androidcachingaudio-streamingexoplayerexoplayer2.x

解决方案


推荐阅读