如何从Firebase存储检索图像并显示它?出现“无内容提供商”错误

时间:2019-05-10 16:10:33

标签: android-imageview firebase-storage android-contentresolver

我的应用程序正在将图像保存在Firebase存储中,但是在检索和查看图像时遇到了问题。图像可以很好地上传到名为“ images”的文件夹中。

每个图像都与一个Box相关联。数据库中的boxes集合如下所示:

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"

我想检索图像并将其显示在DialogFragment中。当前片段布局(dialog_fragment_show_box)看起来像这样(为简洁起见,我已取出layout_width等):

<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>

现在,当DialogFragment加载时,我想传递Box,并显示其名称和关联的图像。 Box.java包含:

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; }

}

Box可以毫无问题地从数据库中检索出来,并传递到DialogFragment中,即:

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

            }
        }

    }
}

运行此命令时,收到以下警告,并且“框图像”为空白:

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)

传递给成功侦听器的uri的形式为:

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

(我更改了一些URL以便在此处发布,但是当我在浏览器中访问它时,它会显示正确的图像,因此我认为可以)。

已填充ContentResolver res;不知道是什么意思,但是在调试器的变量列表中,第一行是:

res = {ContextImpl$ApplicationContentResolver@8456}

有什么想法吗?谢谢!

2 个答案:

答案 0 :(得分:0)

这个answer可以帮助您的处境兄弟!

大概currentTrack有一个File对象。如果是这样,请将Uri.parse(currentTrack.getPath())替换为currentTrack.getUri(),在其中实现getUri()以为Uri.fromFile()返回File的值。

这解决了您的直接问题,即您创建了无效的Uri,因为它没有方案。它还使您可以处理将来可能不需要的Uri个非文件类型(例如content Uri值)。

已复制!

答案 1 :(得分:0)

我实现了以下目标:

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

mStorageRef.child(mBox.getUrl()).getDownloadUrl()
    .addOnSuccessListener(new OnSuccessListener<Uri>() {
         @Override
         public void onSuccess(Uri uri) {                           
             Glide.with(getContext()).load(uri).into(mBoxImage);
         }
    })
    .addOnFailureListener(new OnFailureListener() {
         @Override
         public void onFailure(@NonNull Exception exception) {
             // Handle any errors
         }
   });