How to get download url for firebase storage and update firestore document?

自闭症网瘾萝莉.ら 提交于 2021-02-05 08:27:09

问题


I have been struggling to get download url for an image uploaded to firebase storage from my app. I want to send this url to firestore databse (not realtime database). I am setting itemImageUri to uri.toString() but in onCreate() method itemImageUrl is null and shows null in firestore. I cannot use CollectionRefernece addItemRef in onSuccess method as it gives error for all string variables: Variable is accessed from within inner class needs to be declared final.

public class AddItemActivity extends AppCompatActivity {

    public class AddItemActivity extends AppCompatActivity {
    public static final int PICK_IMAGE_REQUEST = 1;
    public static final String TAG = "Error!";
    public static final String UPLOAD_TAG = "Image uploaded";
    private Uri imageUri = null;
    private TextInputEditText textFieldTitle;
    private TextInputEditText textFieldDesc;
    private AutoCompleteTextView dropdownItemType;
    private TextInputEditText textFieldAddress;
    private TextInputEditText textFieldAvailability;
    private MaterialButton buttonSubmitItem;
    private MaterialButton buttonAddImage;
    private ImageView imageViewItem;
    private String itemImageUrl;
    private Bitmap bitmap;
    private Uri itemImageUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_add_item);

        imageViewItem = findViewById(R.id.imageView_camera);
        textFieldTitle = findViewById(R.id.textField_title);
        textFieldDesc = findViewById(R.id.textField_description);
        dropdownItemType = findViewById(R.id.dropdown_itemType);
        //Select type dropdown
        String[] itemTypes = new String[] {
                "Food",
                "Clothing",
                "Footwear"
        };
        ArrayAdapter<String> itemsDropdownAdpater = new ArrayAdapter<>(AddItemActivity.this, R.layout.dropdown_item_type, itemTypes);
        dropdownItemType.setAdapter(itemsDropdownAdpater);

        textFieldAddress = findViewById(R.id.textField_address);
        textFieldAvailability = findViewById(R.id.textField_availability);
        buttonAddImage = findViewById(R.id.button_addImage);
        buttonSubmitItem = findViewById(R.id.button_submitItem);

        buttonAddImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (ContextCompat.checkSelfPermission(AddItemActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                        Toast.makeText(AddItemActivity.this, "Permission Denied", Toast.LENGTH_LONG).show();
                        ActivityCompat.requestPermissions(AddItemActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
                    } else {
                        choseImage();
                    }
                } else {
                    choseImage();
                }
            }
        });

        buttonSubmitItem.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                submitItem();
            }
        });
    }

    private void choseImage() {
        CropImage.activity()
                .setGuidelines(CropImageView.Guidelines.ON)
                .setAspectRatio(1, 1)
                .start(AddItemActivity.this);
    }

    private void submitItem() {
        String title = textFieldTitle.getText().toString();
        String desc = textFieldDesc.getText().toString();
        String type = dropdownItemType.getText().toString();
        String address = textFieldAddress.getText().toString();
        String availability = textFieldAvailability.getText().toString();
        
        if (title.trim().isEmpty() ||
                desc.trim().isEmpty() ||
                type.trim().isEmpty() ||
                availability.trim().isEmpty()) {
            Toast.makeText(this, "Fields cant be empty", Toast.LENGTH_SHORT).show();
            return;
        }
       
        handleUpload(bitmap);
        CollectionReference addItemRef = FirebaseFirestore.getInstance()
                .collection("ItemList");
        addItemRef.add(new ItemListModel(title, desc, type, address, availability, itemImageUrl));
        Toast.makeText(this, "Item added", Toast.LENGTH_SHORT).show();
        finish();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK) {
                imageUri = result.getUri();
                imageViewItem.setImageURI(imageUri);
                imageViewItem.invalidate();
                BitmapDrawable drawable = (BitmapDrawable) imageViewItem.getDrawable();
                bitmap = drawable.getBitmap();
            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
                Exception error = result.getError();
            }
        }
    }

    private void handleUpload(Bitmap bitmap) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);
        final StorageReference reference = FirebaseStorage.getInstance().getReference()
                .child("itemImages")
                .child(System.currentTimeMillis() + ".jpeg");

        reference.putBytes(baos.toByteArray())
                .addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        getItemImageUrl(reference);
                    }
                })
                .addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Log.e(TAG, "onFailure: ", e.getCause());
                    }
                });
    }

    private void getItemImageUrl(StorageReference reference) {
        reference.getDownloadUrl()
                .addOnSuccessListener(new OnSuccessListener<Uri>() {
                    @Override
                    public void onSuccess(Uri uri) {
                        itemImageUrl = uri.toString();
                    }
                });

    }
}

回答1:


Determining the download URL requires a call to the servers, which means it happens asynchronously. For this reason, any code that needs the download URL needs to be inside the onSuccess of getDownloadURL() or be called from there.

So:

private void getItemImageUrl(StorageReference reference) {
    reference.getDownloadUrl()
            .addOnSuccessListener(new OnSuccessListener<Uri>() {
                @Override
                public void onSuccess(Uri uri) {
                    itemImageUrl = uri.toString();

                    ... here you can write itemImageUrl to the database
                }
            });

}

Also see:

  • How to get the download url from Firebase Storage?



回答2:


First upload the file to the Storage, then call your upload method to the database on the addOnCompleteListener :

final StorageReference fileReference = storageRef.child(System.currentTimeMillis()
                + "." + getFileExtension(uriList.get(i)));
        uploadTask = fileReference.putFile(uriList.get(i));

        uploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
            @Override
            public Task<Uri> then(@NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
                if (!task.isSuccessful() && task.getException() != null) {
                    throw task.getException();
                }

                return fileReference.getDownloadUrl();
            }
        }).addOnCompleteListener(new OnCompleteListener<Uri>() {
            @Override
            public void onComplete(@NonNull Task<Uri> task) {
                if (task.isSuccessful()) {
                    Uri downloadUri = task.getResult();
                    if(downloadUri != null) {
                        itemImageUrl = downloadUri.toString()
                        
                        // create your object
                        // upload your object to the database here
                    }

                }
            }
        });



回答3:


In NodeJS, to get a link for a document stored in Firebase Storage.

const options = {
        version: 'v2', // defaults to 'v2' if missing.
        action: 'read',
        expires: Date.now() + 1000 * 60 * 60, // one hour
    };

let url = storage
    .bucket(bucketname)
    .file(filename)
    .getSignedUrl(options);


来源:https://stackoverflow.com/questions/62699565/how-to-get-download-url-for-firebase-storage-and-update-firestore-document

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!