E/ExoPlayerImplInternal:源错误 com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException:响应代码:403

E/ExoPlayerImplInternal: Source error com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 403

在 Amazon S3 上托管了一个具有授权读取访问权限的视频,我在发送 S3 密钥的同时播放视频时出现上述错误

日志

tech.glide.load.engine.GlideException: Failed to load resource
V/FA: Inactivity, disconnecting from the service
E/ExoPlayerImplInternal: Source error
      com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 403
        at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:300)
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:83)
        at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:962)
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:415)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)


代码

 val defaultHttpDataSourceFactory =
            DefaultHttpDataSourceFactory("Mozilla/5.0 (Linux; U; Android 4.0.3; ko-kr; LG-L160L Build/IML74K) AppleWebkit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30").apply {
                defaultRequestProperties.set("access_key", "")
                defaultRequestProperties.set(
                    "secret_key",   "" )
                defaultRequestProperties.set("bucket_name", "")
                defaultRequestProperties.set("region", "")

            }

        return ProgressiveMediaSource.Factory(defaultHttpDataSourceFactory)
            .createMediaSource(uri)

当检查网络分析器时,我发现 requestheaders 正确。

解决方案是 generatePresignedUrl :

build.gradle 旁边添加:

implementation 'com.amazonaws:aws-android-sdk-s3:2.9.2'


object AmazonS3Helper {

    fun getURI(objectName: String, s3: S3Credentials?): Uri? {
  
        val myCredentials: AWSCredentials =
            BasicAWSCredentials(s3?.accessKey, s3?.secretKey)
        val s3client: AmazonS3 = AmazonS3Client(myCredentials)
        val region = s3?.region ?: "eu-west-2"
        s3client.setRegion(com.amazonaws.regions.Region.getRegion(region))
        val request = GeneratePresignedUrlRequest(s3?.buckeName, objectName)
        val objectURL: URL = s3client.generatePresignedUrl(request)
        return Uri.parse(objectURL.toString())
    }
}


然后像往常一样使用 uri exo-player

注意:S3Credentials 它只是包装器 class 具有 S3 header 值,如(bucket_name,等)。