0

I am having trouble in executing any async task from inside the onCompleted function of onCompletedListener.

I want to execute 2 things

  1. Upload the pic to firebase storage and obtain a downloadable link. (Done)
  2. Update that downloadable link in my user table in firestore. (Not getting executed)

My approach was to obtain the downloadString in the onCompleteListener of the UploadTask. And then pass it as input to another Worker thread to update my user table. The new worker thread is launched from the onCompleteListener of the first task.

Here's a snippet of my code.

uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
            @Override
            public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                if (!task.isSuccessful()) {
                    throw task.getException(); //TODO catch it later
                }
                return finalPicStorageReference.getDownloadUrl();
            }
        }).addOnCompleteListener(new OnCompleteListener<Uri>() {
            @Override
            public void onComplete(@NonNull Task<Uri> task) {
                if (task.isSuccessful()) {
                    Uri downloadUri = task.getResult();
                    Log.d(TAG, "onComplete: Successfully Uploaded");
                    if (downloadUri != null) {
                        String picDownloadString = downloadUri.toString();
                        Constraints.Builder builder = new Constraints.Builder();
                        Data.Builder data = new Data.Builder();
                        if (profileBoolean) {
                            data.putBoolean("profileBoolean", true);
                        } else if (coverBoolean) {
                            data.putBoolean("coverBoolean", true);
                        }
                        data.putString("picDownloadString", picDownloadString);
                        /*OneTimeWorkRequest updatePicEntryAtDB = new OneTimeWorkRequest
                                .Builder(UpdateUserDatabaseWorker.class)
                                .addTag("Updating pic in database")
                                .setInputData(data.build())
                                .build();
                        WorkManager.getInstance(getApplicationContext()).beginUniqueWork("picUpdationInDB", ExistingWorkPolicy.APPEND,
                                updatePicEntryAtDB).enqueue();
                        */results[0] = Result.success();
                    }
                } else {
                    results[0] = Result.failure();
                }
            }
        });

The code uploads the pic perfectly when it is commented like this. But on removing the comment to allow updating of the user table, the code stops working altogether. That is, the pic doesn't get uploaded too.

  • This is my first question on this site. Pray let me know any improvement in my framing of the question. – Devershi Chandra May 25 '20 at 05:12
  • Does [this](https://stackoverflow.com/questions/43576441/querying-data-from-firebase) or [this](https://stackoverflow.com/questions/33723139/wait-firebase-async-retrieve-data-in-android) answer your question? – Chris32 May 25 '20 at 08:03
  • What do you mean through "stops working altogether"? Do you have an error? – Alex Mamo May 25 '20 at 09:15
  • @AlexMamo no it doesn't give any error. It would just not upload my pics on storage folder anymore if I uncomment those commented line. – Devershi Chandra May 26 '20 at 02:55
  • @Chris32 I went through those links and I have reorganized my code goal as talked about in the first link. But unfortunately, I couldn't find the answer to my question. If I have two firebase insertion jobs, and for some reason I want them to be synchronous why can't I just execute the second jobs from the onCompleteListener's onComplete method of first job? – Devershi Chandra May 26 '20 at 03:03
  • I didn't tried this by myself by but looking at this [post](https://medium.com/firebase-developers/why-are-firebase-apis-asynchronous-callbacks-promises-tasks-e037a6654a93) and [this other](https://stackoverflow.com/questions/33203379/setting-singleton-property-value-in-firebase-listener) seems like addOnCompleteListener is not the best approach here because it will run when your app sends the data, not when it is actually uploaded. You want to use await instead. An even better approach here will be using a Cloud Function triggered by the event to update that field on Firestore – Chris32 May 26 '20 at 08:37

1 Answers1

0

Answering with the workaround I implemented

For the starters, I managed to work around using the Tasks.await method. But the drawback here is that you'll have to much strain on your main thread. Second option is to have a WorkManager which will work just fine. You can design two separate work class. The first one will take the Image as input, and upload the pic on firebase storage and generate the downloadable link, and the other one will take this downloadable link as input and then update the users profile database.