2

I am new to this, I am trying to load images from Firestore into a Grid layout recyclerview, the Toast in Firestore onSuccess method shows "Success" message, but the images aren't showing, I am not sure where I did wrong. I used the Image Url saved in Firestore from Firebase Storage.

Could someone please help? Thank you in advance.

Firestore structure: enter image description here

The PhotoActivity:

public class PhotoActivity extends AppCompatActivity {

    private static final int PICK_IMAGE_REQUEST = 1;
    private LinearLayout confirmLayout;
    private ImageView pickedImageView;
    private EditText titleEditText, photoDescriptionEditText;
    private ProgressBar progressBar;

    private String title, photoDescription;
    private Date datePhoto;
    private Uri pickedImageUrl;

    private FirebaseFirestore db;
    private FirebaseAuth mAuth;
    private String userId;
    private CollectionReference collectionReference;
    private StorageReference storageReference;
    private FloatingActionButton fab;
    private RecyclerView recyclerView;

    private List<Photo> photoList;
    private PhotoAdapter photoAdapter;
    private ProgressBar circularProgressbar;

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

        confirmLayout = (LinearLayout) findViewById(R.id.confirmPhotoUploadLayout);
        pickedImageView = (ImageView) findViewById(R.id.pickedImage);
        titleEditText = (EditText) findViewById(R.id.photoTitle);
        photoDescriptionEditText = (EditText) findViewById(R.id.photoDescription);
        progressBar = (ProgressBar) findViewById(R.id.progressbarPhoto);
        recyclerView = (RecyclerView) findViewById(R.id.recyclerViewPhoto);
        circularProgressbar = (ProgressBar) findViewById(R.id.progress_circularPhoto);

        db = FirebaseFirestore.getInstance();
        mAuth = FirebaseAuth.getInstance();

        userId = mAuth.getCurrentUser().getUid();

        storageReference = FirebaseStorage.getInstance().getReference(userId);
        collectionReference = FirebaseFirestore.getInstance().collection("main").document(userId).collection("photo");

        fab = (FloatingActionButton) findViewById(R.id.fabPhoto);
        circularProgressbar.setVisibility(View.VISIBLE);

        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));

        photoList = new ArrayList<>();
        photoAdapter = new PhotoAdapter(this, photoList);
        recyclerView.setAdapter(photoAdapter);

        showPhotoGrid();

    }

    private void showPhotoGrid() {
        collectionReference
                .orderBy("datePhoto", Query.Direction.DESCENDING)
                .get()
                .addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
            @Override
            public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
                assert queryDocumentSnapshots != null;

                if (!queryDocumentSnapshots.isEmpty()){
                    //if contains photos
                    circularProgressbar.setVisibility(View.GONE);
                    Toast.makeText(PhotoActivity.this, "Success", Toast.LENGTH_SHORT).show();
                    List<DocumentSnapshot> list = queryDocumentSnapshots.getDocuments();
                    for (DocumentSnapshot documentSnapshot : list){
                        Photo photo = documentSnapshot.toObject(Photo.class);
                        assert photo != null;
                        photo.setID(documentSnapshot.getId());
                        photoList.add(photo);
                    }
                    photoAdapter.notifyDataSetChanged();

                } else {
                    //show no photos
                    circularProgressbar.setVisibility(View.GONE);
                    Toast.makeText(PhotoActivity.this, "No photos added yet", Toast.LENGTH_SHORT).show();
                }
            }
        }).addOnFailureListener(new OnFailureListener() {
            @Override
            public void onFailure(@NonNull Exception e) {
                circularProgressbar.setVisibility(View.GONE);
                Toast.makeText(PhotoActivity.this, "Error in showing images: " + e.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }

    public void addPhoto(View view) {
        showImageChooser();
    }

    private void showImageChooser() {
        Intent intent = new Intent();
        intent.setType("image/*");
        intent.setAction(Intent.ACTION_GET_CONTENT);
        startActivityForResult(intent, PICK_IMAGE_REQUEST);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            pickedImageUrl = data.getData();

            Picasso.with(this).load(pickedImageUrl).into(pickedImageView);
            confirmLayout.setVisibility(View.VISIBLE);
            fab.setVisibility(View.GONE);
            photoAdapter.notifyDataSetChanged();
        }
    }

    public void hideConfirmLayout(View view) {
        pickedImageView.setImageDrawable(null);
        confirmLayout.setVisibility(View.GONE);
        fab.setVisibility(View.VISIBLE);
    }

    public void uploadPhoto(View view) {
        title = titleEditText.getText().toString().trim();
        photoDescription = photoDescriptionEditText.getText().toString().trim();

        if (title.isEmpty()) {
            titleEditText.setError("Please give a title");
        } else if (photoDescription.isEmpty()) {
            photoDescription = "No description for this photo";
        }

        if (pickedImageUrl != null) {
            if (title.isEmpty()) {
                titleEditText.setError("Required");
            } else {
                StorageReference imageReference = storageReference.child(title + "." + getFileExtension(pickedImageUrl));
                imageReference.putFile(pickedImageUrl).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                        Handler handler = new Handler();
                        handler.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                progressBar.setProgress(0);
                            }
                        }, 1000);

                        String thatImageUrl = taskSnapshot.getStorage().getDownloadUrl().toString();

                        Photo photo = new Photo(userId, title, photoDescription, thatImageUrl, datePhoto);

                        collectionReference.add(photo).addOnSuccessListener(new OnSuccessListener<DocumentReference>() {
                            @Override
                            public void onSuccess(DocumentReference documentReference) {
                                Toast.makeText(PhotoActivity.this, "Saved to gallery", Toast.LENGTH_SHORT).show();
                                confirmLayout.setVisibility(View.GONE);
                                pickedImageView.setImageDrawable(null);
                                titleEditText.setText(null);
                                photoDescriptionEditText.setText(null);
                                fab.setVisibility(View.VISIBLE);
                            }
                        }).addOnFailureListener(new OnFailureListener() {
                            @Override
                            public void onFailure(@NonNull Exception e) {
                                Toast.makeText(PhotoActivity.this, "Firestore error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                            }
                        });

                    }
                }).addOnFailureListener(new OnFailureListener() {
                    @Override
                    public void onFailure(@NonNull Exception e) {
                        Toast.makeText(PhotoActivity.this, "Storage error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                    }
                }).addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
                    @Override
                    public void onProgress(@NonNull UploadTask.TaskSnapshot taskSnapshot) {
                        progressBar.setVisibility(View.VISIBLE);
                        double progress = 100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount();
                        progressBar.setProgress((int) progress);
                    }
                });
            }
        } else {
            Toast.makeText(this, "No photo is selected", Toast.LENGTH_LONG).show();
        }
    }

    private String getFileExtension(Uri uri) {
        //get photo type: jpeg, png
        ContentResolver contentResolver = getContentResolver();
        MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton();
        return mimeTypeMap.getExtensionFromMimeType(contentResolver.getType(uri));
    }
}

The Photo object class

public class Photo implements Serializable {

    private String ID;

    public String getID() {
        return ID;
    }

    public void setID(String ID) {
        this.ID = ID;
    }

    private String photoTitle;
    private String photoDescription;
    private String photoUrl;

    @ServerTimestamp
    private Date datePhoto;

    public Date getDatePhoto() {
        return datePhoto;
    }

    public void setDatePhoto(Date datePhoto) {
        this.datePhoto = datePhoto;
    }

    public Photo() {
    }

    public Photo(String ID, String photoTitle, String photoDescription, String photoUrl, Date datePhoto) {
        this.ID = ID;
        this.photoTitle = photoTitle;
        this.photoDescription = photoDescription;
        this.photoUrl = photoUrl;
        this.datePhoto = datePhoto;
    }

    public String getPhotoTitle() {
        return photoTitle;
    }

    public void setPhotoTitle(String photoTitle) {
        this.photoTitle = photoTitle;
    }

    public String getPhotoDescription() {
        return photoDescription;
    }

    public void setPhotoDescription(String photoDescription) {
        this.photoDescription = photoDescription;
    }

    public String getPhotoUrl() {
        return photoUrl;
    }

    public void setPhotoUrl(String photoUrl) {
        this.photoUrl = photoUrl;
    }
}

the PhotoAdapter:

public class PhotoAdapter extends RecyclerView.Adapter<PhotoAdapter.PhotoViewHolder> {

    private Context context;
    private List<Photo> photoList;

    public PhotoAdapter(Context context, List<Photo> photoList) {
        this.context = context;
        this.photoList = photoList;
    }

    @NonNull
    @Override
    public PhotoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new PhotoViewHolder(LayoutInflater.from(context).inflate(R.layout.single_photo_layout, parent, false));
    }

    @Override
    public void onBindViewHolder(@NonNull PhotoViewHolder holder, int position) {
        Photo photo = photoList.get(position);

        if (photo.getPhotoUrl() != null && !photo.getPhotoUrl().isEmpty()){
            Picasso.with(context).load(photo.getPhotoUrl()).into(holder.showImage);
        }
    }

    @Override
    public int getItemCount() {
        return photoList.size();
    }

    public class PhotoViewHolder extends RecyclerView.ViewHolder {

        ImageView showImage;

        public PhotoViewHolder(View inflate) {
            super(inflate);

            showImage = inflate.findViewById(R.id.singlePhotoImageView);

        }
    }
}

xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/gradient0"
    tools:context=".PhotoActivity">

    <TextView
        android:id="@+id/titlePhoto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:fontFamily="@font/quicksand_bold"
        android:gravity="center"
        android:padding="@dimen/_20sdp"
        android:text="PHOTO GALLERY"
        android:textColor="@color/white"
        android:textSize="@dimen/_14sdp"
        android:layout_alignParentTop="true"/>

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerViewPhoto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/titlePhoto"/>

    <LinearLayout
        android:id="@+id/confirmPhotoUploadLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:background="@drawable/white_rounded"
        android:gravity="center"
        android:orientation="vertical"
        android:paddingTop="@dimen/_20sdp"
        android:paddingBottom="@dimen/_10sdp"
        android:visibility="gone">

        <EditText
            android:id="@+id/photoTitle"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="@dimen/_16sdp"
            android:layout_marginTop="@dimen/_16sdp"
            android:background="@null"
            android:hint="Photo title" />

        <EditText
            android:id="@+id/photoDescription"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginStart="@dimen/_16sdp"
            android:layout_marginEnd="@dimen/_16sdp"
            android:layout_marginBottom="@dimen/_16sdp"
            android:background="@null"
            android:hint="Write something about this photo..." />

        <ProgressBar
            android:id="@+id/progressbarPhoto"
            style="@style/Widget.AppCompat.ProgressBar.Horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:visibility="invisible"
            tools:visibility="visible" />

        <ImageView
            android:id="@+id/pickedImage"
            android:layout_width="match_parent"
            android:layout_height="@dimen/_300sdp"
            android:layout_marginBottom="@dimen/_14sdp"
            android:scaleType="centerCrop" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="@dimen/_10sdp"
            android:gravity="center">

            <Button
                android:layout_width="120dp"
                android:layout_height="wrap_content"
                android:background="@drawable/red_rounded_bg"
                android:onClick="hideConfirmLayout"
                android:text="cancel"
                android:textColor="@color/white" />

            <Button
                android:layout_width="150dp"
                android:layout_height="wrap_content"
                android:layout_marginStart="@dimen/_10sdp"
                android:background="@drawable/rounded_button"
                android:onClick="uploadPhoto"
                android:text="save to gallery"
                android:textColor="@color/white" />

        </LinearLayout>

    </LinearLayout>

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fabPhoto"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_margin="@dimen/_20sdp"
        android:clickable="true"
        android:focusable="true"
        android:onClick="addPhoto"
        android:src="@drawable/ic_add" />

    <ProgressBar
        android:id="@+id/progress_circularPhoto"
        android:layout_width="@dimen/_100sdp"
        android:layout_height="@dimen/_100sdp"
        android:layout_centerInParent="true"
        android:visibility="gone"
        tools:visibility="visible"/>

</RelativeLayout>

single photo Layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/singlePhotoImageView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>
Lionlollipop
  • 113
  • 3
  • 12

2 Answers2

1

I found a solution based on this post--> How to use getdownloadurl in recent versions?

taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                            @Override
                            public void onSuccess(Uri uri) {
                                    //get the uri and carry out action here
                                    //uri = correct filepath
}

now the images are showing in the recyclerview, yay ! Thanks for the help!

Lionlollipop
  • 113
  • 3
  • 12
0

It seems like your urls are wrong.

taskSnapshot.getDownloadUrl returns Task, not the Uri or Url string. You need to add OnSuccessListener callback to get download Uri

Try to save urls by this way:

taskSnapshot.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
                    @Override
                    public void onSuccess(Uri uri) {
                        Uri downloadUrl = uri;
                        String url = downloadUrl.toString()
                        // save this url to Firestore
                    }

Check this in Official documentation

Marat Zangiev
  • 1,172
  • 7
  • 12