Search code examples
androidkotlinandroid-workmanager

Uploading large bitmaps using WorkManager


I'm trying to use WorkManager to upload a bitmap to the server. Basically the user takes a picture and presses a button to upload it to the server.

However, the problem comes when I try to serialise the bitmap using the Data.Builder class of Work Manager, which has a limit of 10240 bytes. Therefore, if I do the following:

val data = Data.Builder()
//Add parameter in Data class. just like bundle. You can also add Boolean and Number in parameter.
data.putString(IMAGE_NAME, identifier)
data.putByteArray(BITMAP_ARRAY, imageBytes) 

The following crash will be thrown java.lang.IllegalStateException: Data cannot occupy more than 10240 bytes when serialized

I could always save the photo to a file before starting the work manager, and in work manager read the file. However, I would rathe avoid all file management if possible, because the user could always close the app, etc.

I just wanted to save the file, if the server responded successful.

Is there any other way to achieve this? Is there a google "suggestion" for this kind of things?

Here is my doWork() of WorkManager functionality

    override fun doWork(): Result {
        val identifier = inputData.getString(IMAGE_NAME)!!
        val imageBytes = inputData.getByteArray(BITMAP_ARRAY)!!

        val result = executeRequest(identifier, imageBytes)

        return if (result.isSuccess()) {
            //saving image
            val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
            saveToInternalStorage(context, identifier, bitmap)
            Result.success()
        } else {
            Result.failure()
        }
    }

Solution

  • I would rathe avoid all file management if possible, because the user could always close the app, etc.

    Then you should not use WorkManager. The documentation states this clearly:

    WorkManager is not intended for in-process background work that can safely be terminated if the app process goes away

    With regards to putting a lot of data in a Data, the documentation is clear on this as well:

    There is a maximum size limit of 10KB for Data objects. [...] If you need to pass more data in and out of your Worker, you should put your data elsewhere

    So if you want to use WorkManager for this after all (which sounds like a good idea to me), you have to put the large bitmap in a file, put the URI of that file in the Data object, and then in your doWork() upload the bitmap from that file and then delete the file.

    If you kill your app in in the middle of doWork(), the WorkManager framework will start your app process (without a UI) later (with increasing backoff time) and attempt to do the upload again.