2

While a user moves around my app I collect key events in a list. When the user quits the app I want to:

  1. write that list to a file; and
  2. upload that file to the cloud for analysis on the backend

I put everything in a function and unit-tested, and it works fine so long as the app is still active. But:

  1. calling the function from the MainActivity onStop() doesn't upload the file to the cloud (it is written to the device successfully)
  2. ditto onPause()
  3. I tried to send a completableDeferred to the function and .await for it, but that didn't help either (I used a coroutine scope initiated by MainActivity).

I've heard before the edict "Though shalt not mess with the lifecycle events", so I guess this is a confirmation...

How do you suggest I accomplish this (upload the file to the cloud when the user quits the app)? It doesn't need to be immediate, it just needs to happen eventually.

Thank you!

2
  • 2
    We cannot help you with your existing code, as your question does not include it, and you have not provided your definition of "quits the app". My guess is that your definition is "the app moves to the background". It is risky to wait on doing things with data, like persistence, until this event, as your process can be terminated within milliseconds of going into the background. Off the cuff, I would be saving the data to disk as I go (with suitable buffering), with uploads scheduled via WorkManager (probably periodically). Commented Jan 6 at 20:07
  • Just clarifying that there's no code because it's all template stuff (very young app), and I didn't elaborate on "quit" because there are several ways to do that... WorkManager did it, see Oleksandr's code below. Commented Jan 10 at 2:17

1 Answer 1

1

Maybe try to use WorkManager. It can work in background

class FileUploadWorker(context: Context, params: WorkerParameters) : Worker(context, params) {

    override fun doWork(): Result {
        val filePath = inputData.getString("filePath") ?: return Result.failure()

        return try {
            val file = File(filePath)
            if (file.exists()) {
                uploadToCloud(file)
                Result.success()
            } else {
                Result.failure()
            }
        } catch (e: Exception) {
            e.printStackTrace()
            Result.retry()
        }
    }

    private fun uploadToCloud(file: File) {
        // ...
    }
}

And start it from Activity onStop

override fun onStop() {
    super.onStop()

    val filePath = saveEventsToFile()

    val data = Data.Builder()
        .putString("filePath", filePath)
        .build()

    val uploadWorkRequest = OneTimeWorkRequestBuilder<FileUploadWorker>()
        .setInputData(data)
        .build()

    WorkManager.getInstance(applicationContext).enqueue(uploadWorkRequest)
}

private fun saveEventsToFile(): String {
    val filePath = "${filesDir.path}/events.json"
    return filePath
}
Sign up to request clarification or add additional context in comments.

1 Comment

Perfect solution @Oleksandr, works like a charm (I've never heard of WorkManager before). Anyone else consulting this: calling this code from onStop works from Overview and Back, but not the Home button. From onPause it works 100% of the times.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.