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 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).