1
votes

Basically I have created a class called 'Club'. I save a new club to firebase realtime database successfully with no real problems, until I want to add an imageURL (called clubImage) from Firebase Storage to my club class.

I am able to succesfully upload my image to Firebase Storage using the below code.

    private void uploadImage() {
        //upload selected image to database
        //code from https://code.tutsplus.com/tutorials/image-upload-to-firebase-in-android-application--cms-29934
             if(filePath != null)
        {
            final ProgressDialog progressDialog = new ProgressDialog(this);
            progressDialog.setTitle("Uploading...");
            progressDialog.show();

            final StorageReference ref = storageReference.child("images/"+ UUID.randomUUID().toString());


            ref.putFile(filePath)
                    .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                            progressDialog.dismiss();
                            Toast.makeText(AddClubActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();

                        }
                    })
                    .addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            progressDialog.dismiss();
                            Toast.makeText(AddClubActivity.this, "Failed "+e.getMessage(), Toast.LENGTH_SHORT).show();
                        }
                    })
                    .addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                        @Override
                        public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
                            double progress = (100.0*taskSnapshot.getBytesTransferred()/taskSnapshot
                                    .getTotalByteCount());
                            progressDialog.setMessage("Uploaded "+(int)progress+"%");
                        }
                    });
        }
    }

This all works fine. However, in the same method, I also have this code, which is where I try to get my downloadURL for the uploaded image.

            ref.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri) {
                    Uri downloadUrl = uri;
                    clubImage = downloadUrl.toString();
                }
            });

I know it is inefficient to have two OnSuccessListeners for the same thing, I am just not sure how else to go about both uploading an image and getting the downloadUrl at the same time. Regardless, this doesn't work, and my new club saves without the clubImage field. I get the error: E/StorageException: StorageException has occurred. Object does not exist at location.

Does anyone know how to fix this? Thanks.

2

2 Answers

4
votes

I know it is inefficient to have two OnSuccessListeners for the same thing

You have two tasks that you're trying to complete:

  1. Upload a file
  2. Get the download URL for that file

Since these are two separate tasks, you'll need two OnSuccessListeners. There is nothing inefficient about this, nor are the tasks the same.

The Firebase documentation on getting a download URL after uploading shows precisely how to complete these two tasks in succession:

final StorageReference ref = storageRef.child("images/mountains.jpg");
uploadTask = ref.putFile(file);

Task<Uri> urlTask = 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();
        }

        // Continue with the task to get the download URL
        return ref.getDownloadUrl();
    }
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
    @Override
    public void onComplete(@NonNull Task<Uri> task) {
        if (task.isSuccessful()) {
            Uri downloadUri = task.getResult();
        } else {
            // Handle failures
            // ...
        }
    }
});

You'll note that this code first completes the uploadTask (which uploads the file) and only then starts a new task to get the download URL. Executing the tasks in this sequence prevents the "Object does not exist at location" error message you get.

0
votes

try using this:

private Uri ImageUri;   //and get image from gallery intent to this ImageUri
...............
StorageReference filePath = FirebaseStorage.getInstance().getReference().child("Club Images").child(ImageUri.getLastPathSegment() + ".jpg");

    filePath.putFile(ImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task)
        {
            if(task.isSuccessful())
            {
                downloadUrl = task.getResult().getDownloadUrl().toString();

                updatetoFirebaseDatabase();

            }
            else
            {
                String message = task.getException().getMessage();
            }
        }
    });
........... 

create updatetoFirebaseDatabase(String imageUrl) method:

updatetoFirebaseDatabase(String imageUrl){
    //implement FirebaseDatabase setvalue method with given image URL
}