I’ve got a list of files to upload to Firebase storage from my Kotlin Android app. I’m finding that if I upload them asynchronously, there can be so many uploading at once my Android app sometimes crashes with an Out Of Memory error.
So I’m trying to make the uploads sequential, with just one uploading at a time, and the loop pausing to wait for the upload to complete before continuing.
I see that I can use something like fileRef.putFile(fileUri).await().storage.downloadUrl.await().toString()
to wait for Firebase to return the Url of a successful upload, before continuing with the loop. When the upload returns a Url, my code works fine.
But if there is an error in the upload, that line of code gets stuck there, waiting indefinitely for that Url.
So how do I wait for successful downloads, but also catch errors and cancel the wait if there is an error?
Is await() even the correct approach?
Here is the code (redacted for simplicity) I’m trying to convert into uploading files sequentially rather than simultaneously. It works fine except rarely, when too many simultaneous uploads throw an OOM:
val fileUri = Uri.fromFile(file)
val fileRef =
Firebase.storage.reference.child("$BLAH/$userID/${Uuid}/${fileUri.lastPathSegment}")
fileRef.putFile(fileUri).addOnSuccessListener {
fileRef.downloadUrl.addOnSuccessListener {
Firebase.firestore.collection(BLAH).document(BLAH)
.set(
blinkybill.toCloud(BLAH, it.toString()),
SetOptions.merge()
)
.addOnSuccessListener {
updateStatus(CloudSyncStatus.STARTED)
CoroutineScope(Dispatchers.IO).launch {
blahDao.updateBlah(
blahEntity.copy(
fileUploaded = true
)
)
}
}
.addOnFailureListener { e ->
logger("Error uploading the URL to Firebase. Not the one I care about right now")
updateStatus(CloudSyncStatus.ERROR)
}
}
}.addOnFailureListener {
logger("THIS IS THE UPLOAD ERROR I WANT TO CATCH WHILE WAITING FOR DOWNLOAD")
updateStatus(CloudSyncStatus.ERROR)
}