user4383363
user4383363

Reputation:

How to retrieve the download URL of an image from Firebase Storage?

I am watching an old tutorial about Firebase Storage. The getDownloadUrl() method from UploadTask.TaskSnapshot is no longer existent, and the documentation fails to be clear to me.

What I've implemented so far is the upload process and I can confirm it works, but getting the URL is a pain and I can't make the way they explain how to do it because:

1) Creating a Task<Uri> urlTask = uploadTask.add[...]() will result in the following error on the IDE:

enter image description here

I don't understand because it is specified in the docs.

2) Using reference.getDownloadUrl() will display a different URL compared to what is shown on the console when seeing the details of the uploaded image. The download URL the console shows is

https://firebasestorage.googleapis.com/v0/b/chatroom-e44e6.appspot.com/o/chat_photos%2F73185640?alt=media&token=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

while logging will show

com.google.android.gms.tasks.xxx@xxxxxxx

My full code at the moment:

if (requestCode == RC_PHOTO_PICKER) {
    if (data != null) {
        Toast.makeText(MainActivity.this, "Uploading...", Toast.LENGTH_SHORT).show();

        Uri file = data.getData();
        final StorageReference reference = mPhotoStorageReference.child(file.getLastPathSegment());
        UploadTask upload = reference.putFile(file);

        upload.addOnFailureListener(this, new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                Toast.makeText(MainActivity.this, "Image could not be uploaded: " + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        }).addOnCompleteListener(this, new OnCompleteListener<UploadTask.TaskSnapshot>() {
            @Override
            public void onComplete(@NonNull Task<UploadTask.TaskSnapshot> task) {
                ChatroomMessage message = new ChatroomMessage(null, mUsername, reference.getDownloadUrl().toString()); // <- com.google.android.gms.tasks.xxx@xxxxxxx
                mMessagesDatabaseReference.push().setValue(message);
                Toast.makeText(MainActivity.this, "Image uploaded!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

My app already has Firebase UI implemented to handle login operations, and the rules are

service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Upvotes: 1

Views: 2253

Answers (3)

Anuj
Anuj

Reputation: 51

I put the effort and wasted more time but here is the more generic and working solution

    private void uploadImage() {

    if (filePath != null) {
        final ProgressDialog progressDialog = new ProgressDialog(this);
        progressDialog.setTitle("Uploading...");
        progressDialog.show();
        final StorageReference ref = storageReference.child("images/" +currentFirebaseUser.getUid() + "");

        ref.putFile(filePath)
                .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        progressDialog.dismiss();

                        Task<Uri> urlTask = taskSnapshot.getStorage().getDownloadUrl();
                        while (!urlTask.isSuccessful());
                        Uri downloadUrl = urlTask.getResult();
                        Log.e("uri12",downloadUrl+"This is uri of image download");
                        Toast.makeText(AddItemActivity.this, "Uploaded", Toast.LENGTH_SHORT).show();
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        progressDialog.dismiss();
                        Toast.makeText(AddItemActivity.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 + "%");
                    }
                });
    }
}

Upvotes: 3

user4383363
user4383363

Reputation:

After many attempts, I managed to solve it. This is the implementation:

Uri file = data.getData();
final StorageReference reference = mPhotoStorageReference.child(file.getLastPathSegment());
UploadTask upload = reference.putFile(file);

upload.addOnFailureListener(this, new OnFailureListener() {
    @Override
    public void onFailure(@NonNull Exception e) {
        Toast.makeText(MainActivity.this, "Image could not be uploaded: " + e.getMessage(), Toast.LENGTH_LONG).show();
    }
});

upload.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();
        }

        return reference.getDownloadUrl();
    }
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
    @Override
    public void onComplete(@NonNull Task<Uri> task) {
        if (task.isSuccessful()) {
            Uri downloadUrl = task.getResult();
            ChatroomMessage message = new ChatroomMessage(null, mUsername, downloadUrl.toString());

            mMessagesDatabaseReference.push().setValue(message);

            Toast.makeText(MainActivity.this, "Image uploaded!", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, task.getException().toString(), Toast.LENGTH_SHORT).show();
        }
    }
});

Upvotes: 0

Sandeep Parish
Sandeep Parish

Reputation: 2258

You have Permission denied error it means you don't have permision for access data from firebase. Please check here

enter image description here

if your security rules is defined public then here is no need for permission and if it isn't public or secured then you need to login by auth before you getting data from firebase and if login success then you can continue your work.

check this it will help you to understanding firebase security rules.

Upvotes: 0

Related Questions