Search code examples
androidamazon-web-servicesaws-amplify

Downloading multiple files using AWS Amplify for Android


I'm building an Android app which uses AWS Amplify to list and download files from S3.

The sample code shows downloading is asynchronous:

Amplify.Storage.downloadFile()
    "ExampleKey",
    new File(getApplicationContext().getFilesDir() + "/download.txt"),
    result -> Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName()),
    error -> Log.e("MyAmplifyApp",  "Download Failure", error)
);

I wish to download the (possibly many) files in a background thread, and notify the main thread after all files have been downloaded (or an error occurred). Questions:

What is the best way to achieve this functionality?

P.S. I've tried the RxAmplify, which exposes RxJava Observables on which I can call blockingSubscribe(). However, the bindings are very new, and I've encountered some app-crashing uncaught exceptions using it.


Solution

  • With Vanilla Amplify

    downloadFile() will perform its work on a background thread. Just use one of the standard approaches to go back onto the main thread, from the callback:

    Handler handler = new Handler(context.getMainLooper());
    File file = new File(context.getFilesDir() + "/download.txt");
    
    Amplify.Storage.downloadFile(
        "ExampleKey", file,
        result -> {
            handler.post(() -> {
                Log.i("MyAmplifyApp", "Successfully downloaded: " + result.getFile().getName());
            });
        },
        error -> Log.e("MyAmplifyApp",  "Download Failure", error)
    );
    

    With Rx Bindings

    But personally, I would use the Rx Bindings. The official documentation includes snippets for the Rx API. Here's a more tailored example:

    File file = new File(context.getFilesDir() + "/download.txt");
    RxAmplify.Storage.downloadFile("ExampleKey", file)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(result -> {
            Log.i("RxExample", "Download OK.");
        }, failure -> {
            Log.e("RxExample", "Failed.", failure);
        });
    

    Running Many Downloads In Parallel

    Build a collection of Singles by calling RxAmplify.Storage.downloadFile("key", local). Then, use Single.mergeArray(...) to combine them all. Subscribe to that, in the same way as above.

    RxStorageCategoryBehavior storage = RxAmplify.Storage;
    Single
        .mergeArray(
            storage.downloadFile("one", localOne)
                .observeResult(),
            storage.downloadFile("two", localTwo)
                .observeResult()
        )
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(/* args ... */);
    

    Reporting Bugs

    You mention that you encountered an unexpected exception. If so, please file a bug here, and I will fix it.