android developer
android developer

Reputation: 115980

For AWS download functionality, how to also avoid downloading if the file hasn't changed?

Background

I'm working on a project that uses com.amazonaws:aws-android-sdk-s3 dependency to download files from the server.

fun downloadFile(context: Context, bucketName: String, fileName: String, file: File, transferListener: TransferListener) {
    val transferUtility =
        TransferUtility.builder().s3Client(AmazonS3Client(AnonymousAWSCredentials()))
            .context(context.applicationContext).build()!!
    val observer =
        transferUtility.download(bucketName, fileName, file)
    observer.setTransferListener(transferListener)
}

The problem

The app needs to get the new file for time to time (a JSON file in this case, but can be anything else). Currently it checks with Firebase-RemoteConfig on some trigger, and if it's a new value, it downloads the file. I find it weird and unnecessary.

I want to avoid using RemoteConfig for this purpose. It makes it more annoying to manage updating of the files.

What I've found

If I has Retrofit here, I could have used Etag or something like that for a last-modified-time of the file:

https://medium.com/android-news/reducing-your-networking-footprint-with-okhttp-etags-and-if-modified-since-b598b8dd81a1

I've tried to search about the same thing for AWS, but I couldn't. I found some for uploading, but here it's completely different.

I also couldn't find how to use what's recommended instead of the CTOR of AmazonS3Client, which is deprecated. It says I need to Use AmazonS3Client#AmazonS3Client(AWSCredentials, com.amazonaws.regions.Region) , but when what to put for each...

Later I tried to use Retrofit instead:

interface FileDownloadService {
    @GET
    @Streaming
     fun downloadFile(@Url fileUrl:String): Call<ResponseBody>
}

@WorkerThread
fun test(context: App, url: String) {
    Log.d("AppLog", "test")
    val cacheSizeBytes = 1024L * 1024L * 2L
    val builder = OkHttpClient().newBuilder()
    builder.cache(Cache(context.cacheDir, cacheSizeBytes))
    val client: OkHttpClient = builder.build()
    val retrofitBuilder = Retrofit.Builder()
    retrofitBuilder.baseUrl("https://s3.amazonaws.com").client(client)
    val retrofit = retrofitBuilder.build()
    val service: FileDownloadService = retrofit.create(FileDownloadService::class.java)
    val response = service.downloadFile(url).execute()
    Log.d("AppLog", "isSuccessful?${response.isSuccessful} ${response.code()} ${response.raw().code} ${response.headers()["Last-Modified"]}")
}

This has multiple issues:

  1. On emulator, it keeps getting response code 200 (instead of HttpURLConnection.HTTP_NOT_MODIFIED) and takes a long time (4 seconds). I could just use the header "Last_Modifed" as this seems to be fetched well, though.

  2. On device, I keep getting UnknownHostException: Unable to resolve host "s3.amazonaws.com": No address associated with hostname .

  3. The app already uses Retrofit in other places. I don't know if this could cause more issues as it probably uses different configuration, different threads, ...

The questions

  1. How can I detect when the file has changed, avoiding downloading of the file?

  2. What should I use instead of the CTOR of AmazonS3Client that I see here?

  3. Is is possible to use Retrofit as I've shown? If so, what's wrong with how I did it?

Upvotes: 0

Views: 69

Answers (0)

Related Questions