Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I retrieve an image from Firebase Storage and show it? Getting "No content provider" error

My app is saving images in Firebase Storage, but I'm having trouble retrieving and viewing them. Images are uploaded fine, into a folder called "images".

Each image is associated with a Box. The boxes collection in the database looks like this:

boxes > key1 > name: Box 1 name
             > uid: xxxxxxxxx          (user id of Box creator)
             > image: "images/box1image.jpg"
      > key2 > name: Box 2 name
             > uid: yyyyyyyyy          
             > image: "images/box2image.jpg"

I want to retrieve the image and show it in a DialogFragment. Currently the fragment layout (dialog_fragment_show_box) looks like this (I've taken out layout_width etc for brevity):

<android.support.constraint.ConstraintLayout >

    <ImageView
        android:id="@+id/iv_box_image" />

    <TextView
        android:id="@+id/tv_box_name"
        app:layout_constraintTop_toBottomOf="@id/iv_box_image" />

</android.support.constraint.ConstraintLayout>

Now, when the DialogFragment loads, I want to pass in the Box, and display its name and associated image. Box.java contains:

public class HybridBox {

    private String  name, uid, key, url;


    // CONSTRUCTOR
    public HybridBox() {}

    // GETTERS
    public String   getName()         { return name; }
    public String   getUrl()          { return url; }
    public String   getUid()          { return this.uid; }
    public String   getKey()          { return key; }

    // SETTERS
    public void setName(String thisName) { this.name = thisName; }
    public void setUrl(String thisUrl)   { this.url = thisUrl; }
    public void setUid(String thisUid)   { this.uid = thisUid; }
    public void setKey(String thisKey)   { this.key = thisKey; }

}

The Box is retrieved from the database with no problems, and passed into the DialogFragment, which is:

public class DialogFragmentShowBox extends DialogFragment {

    private Context         mContext;
    private EditText        mBoxName;
    private ImageView       mBoxImage;
    private HybridBox       mBox;

    public DialogFragmentShowBox() {}

    public static DialogFragmentShowBox newInstance() {
        return new DialogFragmentShowBox();
    }

    @Override
    public View onCreateView(
            @NonNull LayoutInflater inflater, 
            ViewGroup container, Bundle savedInstanceState) {

        return inflater.inflate(
                R.layout.dialog_fragment_show_box, container, false);

    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        mBoxImage        = view.findViewById(R.id.iv_box_image);
        mBoxName         = view.findViewById(R.id.tv_box_name);

        show_details();
        draw_iv();

    }

    // Pass in Box object
    public void setBox(HybridBox box) {

        mBox = box;

        show_details();
        draw_iv();

    }

    // Set up Context
    public void setContext(Context context) { mContext = context; }

    // Show details of the Box (currently just name)
    private void show_details() {

        if(mBox == null) return;

        if(mBoxName != null) {
            mBoxName(mBox.getName());
        }
    }

    // Draw the Box image
    private void draw_iv() {
        if(mBox == null) return;

        if(mBoxImage != null) {

            FirebaseStorage mStorage = FirebaseStorage.getInstance();
            final StorageReference mStorageRef = mStorage.getReference();

            final String drawableUrl = mBox.getUrl();

            if(drawableUrl != null) {
                mStorageRef.child(mBox.getUrl())
                           .getDownloadUrl()
                           .addOnSuccessListener(new OnSuccessListener<Uri>() {
                    @Override
                    public void onSuccess(Uri uri) {
                        // Got the download URL
                        ContentResolver res = mContext.getContentResolver();
                        try {
                            Bitmap bitmap
                                    = MediaStore.Images.Media.getBitmap(
                                    res,
                                    uri);
                            mBoxImage.setImageBitmap(bitmap);
                        }
                        catch (IOException e)
                        {
                            e.printStackTrace();
                        }
                    }
                });

            }
        }

    }
}

When I run this, I get the following warning, and the Box Image is blank:

W/System.err: java.io.FileNotFoundException: No content provider: https://firebasestorage.googleapis.com/v0/b/tickybox-d8888.appspot.com/o/images%2F561e1408-3b17-4eaa-b0ff-d3b00479d1c0.jpg?alt=media&token=9656ea28-2493-447b-aa30-9dbc4c39b3fc
W/System.err:     at android.content.ContentResolver.openTypedAssetFileDescriptor(ContentResolver.java:1396)
W/System.err:     at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:1247)
W/System.err:     at android.content.ContentResolver.openInputStream(ContentResolver.java:967)
        at android.provider.MediaStore$Images$Media.getBitmap(MediaStore.java:888)
        at sharongilmore.tickybox.fragments.dialogFragments.DialogFragmentShowBox$6.onSuccess(DialogFragmentShowBox.java:295)
W/System.err:     at sharongilmore.tickybox.fragments.dialogFragments.DialogFragmentShowBox$6.onSuccess(DialogFragmentShowBox.java:288)
        at com.google.android.gms.tasks.zzn.run(Unknown Source:4)
        at android.os.Handler.handleCallback(Handler.java:790)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:164)
W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:6494)
W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

The uri being passed into the success listener is in the form:

https://firebasestorage.googleapis.com/v0/b/tickybox-d8888.appspot.com/o/images%2F561e1408-3b17-4eaa-b0ff-d3b00479d1c0.jpg?alt=media&token=9656ea28-2493-447b-aa30-9dbc4c39b3fc

(I've changed some of the url to post here, but when I go to it in a browser it shows the correct image so I think it's ok).

The ContentResolver res is populated; not sure what it's meant to be, but in the variable list in the debugger the first line is:

res = {ContextImpl$ApplicationContentResolver@8456}

Any ideas what's going wrong here?

like image 235
Sharon Avatar asked May 10 '19 16:05

Sharon


1 Answers

This answer can help your situation brother!

Presumably, currentTrack has a File object. If so, replace Uri.parse(currentTrack.getPath()) with currentTrack.getUri(), where you implement getUri() to return the value of Uri.fromFile() for the File.

This solves your immediate problem, which is that you have created an invalid Uri, as it has no scheme. It also sets you up to deal with Uri types that are not files (e.g., content Uri values) that you may wind up needing in the future.

Copied!

like image 112
Hafeez Ul Haq Ahsaas Avatar answered Oct 16 '22 15:10

Hafeez Ul Haq Ahsaas