Search code examples
androidkotlinamazon-s3exoplayerexoplayer2.x

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


There is a video hosted on Amazon S3 with Authorized-Read Access, I got above error when play video while I send S3 keys

Log

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)


Code

 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)

when check network profiler i found request has headers correctly.


Solution

  • Solution was to generatePresignedUrl :

    add next to 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())
        }
    }
    
    
    

    then use uri as normal with exo-player

    NOTE: S3Credentials it is just wrapper class to have S3 header values like(bucket_name, etc).