Hi I want the chat message Align like this when I send message I want them on the right when I receive I want them on left like this in the image
but it looks like this even though I set to two different layouts for in and out but it appears in the same way
In ChatRoomActvity getItemViewType(int position) always return as MESSAGE_IN_VIEW_TYPE;
What am I missing here?
ChatRoomActvity.java
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
private DatabaseReference mFirebaseDatabaseReference;
private FirebaseRecyclerAdapter<FriendlyMessage, MessageViewHolder>
mFirebaseAdapter;
public static final String MESSAGES_CHILD = "messages";
public static final String ANONYMOUS = "anonymous";
private static final String TAG = "ChatRoomAct";
private static final int REQUEST_IMAGE = 2;
private static final String LOADING_IMAGE_URL = "https://www.google.com/images/spin-32.gif";
private FloatingActionButton mSendButton;
private RecyclerView mMessageRecyclerView;
private LinearLayoutManager mLinearLayoutManager;
private ProgressBar mProgressBar;
private EditText mMessageEditText;
private ImageView mAddMessageImageView;
private String mUsername;
private String mPhotoUrl;
private String mUserid;
private String mSenderUid;
//Emoji Function
private ImageView emojiButton;
private EmojiPopup emojiPopup;
private ViewGroup rootView;
private EmojiEditText editText;
private final int MESSAGE_IN_VIEW_TYPE = 1;
private final int MESSAGE_OUT_VIEW_TYPE = 2;
public static class MessageViewHolder extends RecyclerView.ViewHolder {
TextView mTime;
CircleImageView imgProfile;
TextView messageTextView;
ImageView messageImageView;
TextView messengerTextView;
CircleImageView messengerImageView;
TextView mLikesCount;
ImageView imgDropdown, imgLikes;
public MessageViewHolder(View v) {
super(v);
messengerTextView = (TextView) itemView.findViewById(R.id.message_user);
messageTextView = (TextView) itemView.findViewById(R.id.message_text);
mTime = (TextView) itemView.findViewById(R.id.message_time);
messengerImageView = (CircleImageView) itemView.findViewById(R.id.imgDps);
imgLikes = itemView.findViewById(R.id.imgLikes);
mLikesCount = (TextView)itemView.findViewById(R.id.message_Likes);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat_room_actvity);
// Initialize ProgressBar and RecyclerView.
mProgressBar = (ProgressBar) findViewById(R.id.loader);
mMessageRecyclerView = (RecyclerView) findViewById(R.id.list);
mLinearLayoutManager = new LinearLayoutManager(ChatRoomActvity.this);
mLinearLayoutManager.setStackFromEnd(true);
mMessageRecyclerView.setLayoutManager(mLinearLayoutManager);
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
mUserid = mFirebaseUser.getUid();
mUsername = ANONYMOUS;
if (mFirebaseUser == null) {
finish();
return;
} else {
mUsername = mFirebaseUser.getDisplayName();
if (mFirebaseUser.getPhotoUrl() != null) {
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
}
}
displaychatmessages();
}
public void displaychatmessages() {
mFirebaseDatabaseReference = FirebaseDatabase.getInstance().getReference();
SnapshotParser<FriendlyMessage> parser = new SnapshotParser<FriendlyMessage>() {
#NonNull
#Override
public FriendlyMessage parseSnapshot(DataSnapshot snapshot) {
FriendlyMessage friendlyMessage = snapshot.getValue(FriendlyMessage.class);
if (friendlyMessage != null) {
friendlyMessage.setId(snapshot.getKey());
}
return friendlyMessage;
}
};
DatabaseReference messagesRef = mFirebaseDatabaseReference.child(MESSAGES_CHILD);
FirebaseRecyclerOptions<FriendlyMessage> options =
new FirebaseRecyclerOptions.Builder<FriendlyMessage>()
.setQuery(messagesRef, parser)
.build();
mFirebaseAdapter = new FirebaseRecyclerAdapter<FriendlyMessage, MessageViewHolder>(options) {
#Override
public int getItemViewType(int position) {
if(getItem(position).getId().equals(mFirebaseAuth.getCurrentUser().getUid()))
{
return MESSAGE_OUT_VIEW_TYPE;
} else {
return MESSAGE_IN_VIEW_TYPE;
}
}
#Override
protected void onBindViewHolder(MessageViewHolder viewHolder, int position, FriendlyMessage friendlyMessage) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
if (friendlyMessage.getText() != null) {
viewHolder.messageTextView.setText(friendlyMessage.getText());
viewHolder.messageTextView.setVisibility(TextView.VISIBLE);
viewHolder.mTime.setText(DateFormat.format("dd MMM (h:mm a)", friendlyMessage.getMessageTime()));
viewHolder.mLikesCount.setText(String.valueOf(friendlyMessage.getMessageLikesCount()));
if (friendlyMessage.getMessageLikes() != null) {
if (friendlyMessage.getMessageLikes().containsValue(mUserid)) {
viewHolder.imgLikes.setImageResource(R.drawable.red_heart);
} else {
viewHolder.imgLikes.setImageResource(R.drawable.chat_heart);
}
}
}
viewHolder.messengerTextView.setText(friendlyMessage.getName());
if (friendlyMessage.getPhotoUrl() == null) {
viewHolder.messengerImageView.setImageDrawable(ContextCompat.getDrawable(ChatRoomActvity.this,
R.drawable.profile));
} else {
Glide.with(ChatRoomActvity.this)
.load(friendlyMessage.getPhotoUrl())
.into(viewHolder.messengerImageView);
}
}
#NonNull
#Override
public MessageViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = null;
if(i==MESSAGE_IN_VIEW_TYPE){
view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.message_in, viewGroup, false);
}
else if(i==MESSAGE_OUT_VIEW_TYPE){
view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.message_out, viewGroup, false);
}
return new MessageViewHolder(view);
}
};
mFirebaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
#Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
int friendlyMessageCount = mFirebaseAdapter.getItemCount();
int lastVisiblePosition =
mLinearLayoutManager.findLastCompletelyVisibleItemPosition();
// If the recycler view is initially being loaded or the
// user is at the bottom of the list, scroll to the bottom
// of the list to show the newly added message.
if (lastVisiblePosition == -1 ||
(positionStart >= (friendlyMessageCount - 1) &&
lastVisiblePosition == (positionStart - 1))) {
mMessageRecyclerView.scrollToPosition(positionStart);
}
}
});
mMessageRecyclerView.setAdapter(mFirebaseAdapter);
mMessageEditText = (EditText) findViewById(R.id.input);
mMessageEditText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (charSequence.toString().trim().length() > 0) {
mSendButton.setEnabled(true);
} else {
mSendButton.setEnabled(false);
}
}
#Override
public void afterTextChanged(Editable editable) {
}
});
mSendButton = (FloatingActionButton) findViewById(R.id.btnSend);
mSendButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FriendlyMessage friendlyMessage = new
FriendlyMessage(mUserid,mMessageEditText.getText().toString(),null,
mUsername,
mPhotoUrl,
null /* no image */);
mFirebaseDatabaseReference.child(MESSAGES_CHILD)
.push().setValue(friendlyMessage);
mMessageEditText.setText("");
}
});
}
#Override
protected void onStart() {
super.onStart();
}
#Override
protected void onResume() {
super.onResume();
mFirebaseAdapter.startListening();
}
#Override
protected void onPause() {
super.onPause();
mFirebaseAdapter.stopListening();
}
#Override
protected void onStop() {
super.onStop();
}
#Override
public void onBackPressed() {
super.onBackPressed();
}
#Override
protected void onDestroy() {
super.onDestroy();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: requestCode=" + requestCode + ", resultCode=" + resultCode);
if (requestCode == REQUEST_IMAGE) {
if (resultCode == RESULT_OK) {
if (data != null) {
final Uri uri = data.getData();
Log.d(TAG, "Uri: " + uri.toString());
FriendlyMessage tempMessage = new FriendlyMessage(null,null,null,mUsername, mPhotoUrl,
LOADING_IMAGE_URL);
mFirebaseDatabaseReference.child(MESSAGES_CHILD).push()
.setValue(tempMessage, new DatabaseReference.CompletionListener() {
#Override
public void onComplete(DatabaseError databaseError,
DatabaseReference databaseReference) {
if (databaseError == null) {
String key = databaseReference.getKey();
StorageReference storageReference =
FirebaseStorage.getInstance()
.getReference(mFirebaseUser.getUid())
.child(key)
.child(uri.getLastPathSegment());
putImageInStorage(storageReference, uri, key);
} else {
Log.w(TAG, "Unable to write message to database.",
databaseError.toException());
}
}
private void putImageInStorage(StorageReference storageReference, Uri uri, String key) {
storageReference.putFile(uri).addOnCompleteListener(ChatRoomActvity.this,
new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful()) {
task.getResult().getMetadata().getReference().getDownloadUrl()
.addOnCompleteListener(ChatRoomActvity.this,
new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
FriendlyMessage friendlyMessage =
new FriendlyMessage(null,null,null, mUsername, mPhotoUrl,
task.getResult().toString());
mFirebaseDatabaseReference.child(MESSAGES_CHILD).child(key)
.setValue(friendlyMessage);
}
}
});
} else {
Log.w(TAG, "Image upload task was not successful.",
task.getException());
}
}
});
}
});
}
}
}
}
}
FriendlyMessage.java
public class FriendlyMessage {
private String id;
private String text;
private String name;
private String photoUrl;
private String imageUrl;
private long messageTime;
private long messageLikesCount;
private Map<String, Boolean> messageLikes = new HashMap<>();
public FriendlyMessage(){}
public FriendlyMessage(String id,String text,String name, String photoUrl, String imageUrl) {
this.id = id;
this.text = text;
this.name = name;
messageTime = new Date().getTime();
this.photoUrl = photoUrl;
this.imageUrl = imageUrl;
this.messageLikesCount = messageLikesCount;
this.messageLikes= messageLikes;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setText(String text) {
this.text = text;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhotoUrl() {
return photoUrl;
}
public String getText() {
return text;
}
public void setPhotoUrl(String photoUrl) {
this.photoUrl = photoUrl;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public long getMessageTime() {
return messageTime;
}
public void setMessageTime(long messageTime) {
this.messageTime = messageTime;
}
public long getMessageLikesCount() {
return messageLikesCount;
}
public void setMessageLikesCount(long messageLikesCount) {
this.messageLikesCount = messageLikesCount;
}
public Map<String, Boolean> getMessageLikes() {
return messageLikes;
}
public void setMessageLikes(Map<String, Boolean> messageLikes) {
this.messageLikes = messageLikes;
}
}
I can't without the images (for any reason, they are not in the post) but from what I see,
getItem(position).getId().equals(mFirebaseAuth.getCurrentUser().getUid())
and
FriendlyMessage.getId()
I'd say you're not taking the sender into account. ID is conventionally used as a message number, they usually do not point to a uid. Besides, your class already has a field called senderUid, so you should compare against that instead of id.
Optionally, try to log the line before the condition.
#Override
public int getItemViewType(int position) {
FriendlyMessage friendlyMessage = getItem(position);
boolean user = (friendlyMessage.getUserid().equals(mUserid));
if(user)
{
return MESSAGE_OUT_VIEW_TYPE;
} else {
return MESSAGE_IN_VIEW_TYPE;
}
}
I use boolean
Related
I am using FirestoreRecyclerAdapter and faced with the problems.
I read Firestore database documents and retrieve them to the recyclerview but for some reason, does not show anything. I don't know why. Can anyone help me? I would really thankful if anyone could help me.
Thank you in advance!.
This is Adapter;
public MyFriendsAdapter(#NonNull FirestoreRecyclerOptions<ProfileModelClass> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull MyFriendsViewholder holder, int position, #NonNull ProfileModelClass model)
{
holder.myNickname.setText(model.getNickname());
holder.myAge.setText(model.getAge());
holder.myGender.setText(model.getGender());
holder.myDistance.setText(model.getDistance());
holder.myUserDescription.setText(model.getUserDescription());
holder.myMarriage.setText(model.getMarriage());
holder.myAddress.setText(model.getAddress());
// String visit_user_id = getSnapshots().getSnapshot(position).getId();
// Intent chatIntent = new Intent(MainActivity.this, ChatActivity.class);
// chatIntent.putExtra("visit_user_id", visit_user_id);
// startActivity(chatIntent);
Glide.with(holder.myProfileImageView.getContext()).load(model.getProfileImage()).placeholder(R.drawable.profile).into(holder.myProfileImageView);
Glide.with(holder.myPictureOne.getContext()).load(model.getPictureOne()).placeholder(R.drawable.select_image).into(holder.myPictureOne);
Glide.with(holder.myPictureTwo.getContext()).load(model.getPictureTwo()).placeholder(R.drawable.select_image).into(holder.myPictureTwo);
/* holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
String visit_user_id = getRef(position).getKey();
Intent profileIntent = new Intent(FindFriendsActivity.this, ProfileActivity.class);
profileIntent.putExtra("visit_user_id", visit_user_id);
startActivity(profileIntent);
}
}); */
}
#NonNull
#Override
public MyFriendsViewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType)
{
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.all_friends_list_layout,
parent, false);
return new MyFriendsViewholder(view);
}
class MyFriendsViewholder extends RecyclerView.ViewHolder
{
CircleImageView myProfileImageView;
TextView myNickname,myAge, myGender, myDistance, myUserDescription, myMarriage, myAddress,
myFriendsProfile, SendMessageButton;
ImageView myPictureOne, myPictureTwo;
public MyFriendsViewholder(#NonNull View itemView)
{
super(itemView);
myProfileImageView = itemView.findViewById(R.id.all_friends_profile_image_layout);
myNickname = itemView.findViewById(R.id.all_friends_nickname_layout);
myGender = itemView.findViewById(R.id.all_friends_gender_layout);
myAge = itemView.findViewById(R.id.all_friends_age_layout);
myDistance = itemView.findViewById(R.id.all_friends_distance_layout);
myUserDescription = itemView.findViewById(R.id.all_friends_description_layout);
myMarriage = itemView.findViewById(R.id.all_friends_marriage_layout);
myAddress = itemView.findViewById(R.id.all_friends_address_layout);
myPictureOne = itemView.findViewById(R.id.all_friends_post_image_first);
myPictureTwo = itemView.findViewById(R.id.all_friends_post_image_second);
myFriendsProfile = itemView.findViewById(R.id.all_friends_information_layout);
SendMessageButton = itemView.findViewById(R.id.all_friends_call_layout);
myFriendsProfile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
Intent profileIntent = new Intent(v.getContext(), ProfileActivity.class);
profileIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(profileIntent);
}
});
SendMessageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent messageIntent = new Intent(v.getContext(), ChatActivity.class);
messageIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
v.getContext().startActivity(messageIntent);
}
});
This is AllConditionFriendsActivity;
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_all_condition_friends);
mToolbar = (Toolbar) findViewById(R.id.all_condition_age_salary_appbar_layout);
setSupportActionBar(mToolbar);
getSupportActionBar().setTitle("친구찾기");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mAgeSalaryRecyclerList= (RecyclerView) findViewById(R.id.all_condition_age_salary_list);
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
queryFirstAgeSalaryFriends();
}
private void queryFirstAgeSalaryFriends()
{
firstAgeSalaryColRef
.get()
.addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task)
{
if (task.isSuccessful())
{
for (DocumentSnapshot documentSnapshot : task.getResult())
{
if ( documentSnapshot.exists())
{
String age = documentSnapshot.getString("age");
String salary = documentSnapshot.getString("salary");
String gender = documentSnapshot.getString("gender");
if (gender == "남자(//man)" && age == "19살(//age19)" && salary == "대학(원)생(//graduate student)")
{
showManFirstAgeSalaryFriendsList();
}
else if (gender == "여자(//woman)" && age == "19살(//age19)" && salary == "대학(원)생(//graduate student)")
{
showWomanFirstAgeSalaryFriendsList();
}
}
}
}
else
{
}
}
});
}
private void showWomanFirstAgeSalaryFriendsList()
{
Query womanSalaryQuery = db.collection("usersProfiles")
.whereEqualTo("gender", "남자(//man)")
.whereEqualTo("age", "19살(//age19)")
.whereEqualTo("salary", "대학(원)생(//graduate student)");
FirestoreRecyclerOptions<ProfileModelClass> options = new FirestoreRecyclerOptions.Builder<ProfileModelClass>()
.setQuery(womanSalaryQuery, ProfileModelClass.class)
.build();
adapter = new MyFriendsAdapter(options);
mAgeSalaryRecyclerList.setHasFixedSize(true);
mAgeSalaryRecyclerList.setLayoutManager(new LinearLayoutManager(this));
adapter.startListening();
mAgeSalaryRecyclerList.setAdapter(adapter);
}
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
private void showManFirstAgeSalaryFriendsList()
{
Query manSalaryQuery = db.collection("usersProfiles")
.whereEqualTo("gender", "여자(//woman)")
.whereEqualTo("age", "19살(//age19)")
.whereEqualTo("salary", "대학(원)생(//graduate student)");
FirestoreRecyclerOptions<ProfileModelClass> options = new FirestoreRecyclerOptions.Builder<ProfileModelClass>()
.setQuery(manSalaryQuery, ProfileModelClass.class)
.build();
adapter = new MyFriendsAdapter(options);
mAgeSalaryRecyclerList.setHasFixedSize(true);
mAgeSalaryRecyclerList.setLayoutManager(new LinearLayoutManager(this));
adapter.startListening();
mAgeSalaryRecyclerList.setAdapter(adapter);
This is Model class;
private String address, age, marriage, gender, nickname, profileImage, userDescription, pictureOne, pictureTwo, distance;
public ProfileModelClass() {
}
public ProfileModelClass(String address, String age, String marriage, String gender, String nickname, String profileImage, String userDescription, String pictureOne, String pictureTwo, String distance) {
this.address = address;
this.age = age;
this.marriage = marriage;
this.gender = gender;
this.nickname = nickname;
this.profileImage = profileImage;
this.userDescription = userDescription;
this.pictureOne = pictureOne;
this.pictureTwo = pictureTwo;
this.distance = distance;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public String getMarriage() {
return marriage;
}
public void setMarriage(String marriage) {
this.marriage = marriage;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getProfileImage() {
return profileImage;
}
public void setProfileImage(String profileImage) {
this.profileImage = profileImage;
}
public String getUserDescription() {
return userDescription;
}
public void setUserDescription(String userDescription) {
this.userDescription = userDescription;
}
public String getPictureOne() {
return pictureOne;
}
public void setPictureOne(String pictureOne) {
this.pictureOne = pictureOne;
}
public String getPictureTwo() {
return pictureTwo;
}
public void setPictureTwo(String pictureTwo) {
this.pictureTwo = pictureTwo;
}
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
}
Firestore DB;
Your code is querying:
db.collection("usersProfiles")
But in your screenshot, the collection is named GenderAgeSalary. If that is indeed the collection you want to query and show, it should be:
db.collection("GenderAgeSalary")...
I used Firebase Firestore to create a realtime recycler view with pagination, but the problem is that I am trying to order the documents using Timestamp. When I try to add a new document the app crashes. This only happens when adding the first document in a collection, after that it will work fine.
This is the error I'm getting:
java.lang.IllegalArgumentException: Invalid query. You are trying to start or end a query using a document for which the field 'date_posted' is an uncommitted server timestamp. (Since the value of this field is unknown, you cannot start/end a query with it.)
at com.google.firebase.firestore.Query.boundFromDocumentSnapshot(com.google.firebase:firebase-firestore##21.4.3:758)
at com.google.firebase.firestore.Query.startAfter(com.google.firebase:firebase-firestore##21.4.3:648)
at com.project.alihammoud.foodreviewlb.BottomSheetFragmentComment.loadMore(BottomSheetFragmentComment.java:251)
at com.project.alihammoud.foodreviewlb.BottomSheetFragmentComment$2.onScrolled(BottomSheetFragmentComment.java:191)
at androidx.recyclerview.widget.RecyclerView.dispatchOnScrolled(RecyclerView.java:5173)
I have it that when I send a document to the firestore database, it gets its timestamp from the firestore server. I know that there is a delay in assigning the Timestamp so I tried adding a wait before refreshing but that did not work. Any ideas what could work to avoid this issue?
Here is my code:
public class BottomSheetFragmentComment extends BottomSheetDialogFragment {
private Toolbar toolbar;
private String document_id;
private String currentUserID;
private FirebaseAuth auth;
private FirebaseUser currentUser;
private FirebaseFirestore db;
private RecyclerView recyclerView;
private List<CommentInfo> comments_list;
private CommentsAdapter commentsAdapter;
private ImageButton comment_button;
private EditText comment_text;
private DocumentSnapshot lastVisible;
private Boolean isFirstPageFirstLoad = true;
private CommentID commentID;
public BottomSheetFragmentComment(){
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.bottom_sheet_comments,container,false);
document_id = this.getArguments().getString("docID");
auth = FirebaseAuth.getInstance();
currentUser = auth.getCurrentUser();
currentUserID = currentUser.getUid();
db = FirebaseFirestore.getInstance();
comments_list = new ArrayList<>();
commentsAdapter = new CommentsAdapter(comments_list);
Query firstQuery = db.collection("Reviews").document(document_id).collection("Comments")
.orderBy("date_posted", Query.Direction.DESCENDING)
.limit(20);
firstQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshot, #Nullable FirebaseFirestoreException e) {
if (e == null){
if (!documentSnapshot.isEmpty()){
if (isFirstPageFirstLoad){
lastVisible = documentSnapshot.getDocuments().get(documentSnapshot.size()-1);
}
for (DocumentChange documentChange: documentSnapshot.getDocumentChanges()){
if (documentChange.getType() == DocumentChange.Type.ADDED){
String commentID = documentChange.getDocument().getId();
CommentInfo commentAdded = documentChange.getDocument().toObject(CommentInfo.class);
if (isFirstPageFirstLoad){
comments_list.add(commentAdded);
}
else {
comments_list.add(0,commentAdded);
}
commentsAdapter.notifyDataSetChanged();
}
else if (documentChange.getType() == DocumentChange.Type.REMOVED){
comments_list.remove(documentChange.getOldIndex());
commentsAdapter.notifyItemRemoved(documentChange.getOldIndex());
}
else if (documentChange.getType() == DocumentChange.Type.MODIFIED){
CommentInfo commentModified = documentChange.getDocument().toObject(CommentInfo.class);
if (documentChange.getOldIndex() == documentChange.getNewIndex()) {
// Item changed but remained in same position
comments_list.set(documentChange.getOldIndex(),commentModified);
commentsAdapter.notifyItemChanged(documentChange.getOldIndex());
}else {
// Item changed and changed position
comments_list.remove(documentChange.getOldIndex());
comments_list.add(documentChange.getNewIndex(),commentModified);
commentsAdapter.notifyItemMoved(documentChange.getOldIndex(),documentChange.getNewIndex());
}
commentsAdapter.notifyDataSetChanged();
}
}
isFirstPageFirstLoad = false;
}
}
}
});
// db.collection("Reviews").document(document_id).collection("Comments")
if (currentUser != null){
//setUpRecyclerView();
recyclerView = view.findViewById(R.id.recycle_view);
recyclerView.setHasFixedSize(true);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getContext());
mLayoutManager.setReverseLayout(true);
// mLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setAdapter(commentsAdapter);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrollStateChanged(#NonNull RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
}
#Override
public void onScrolled(#NonNull RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
Boolean reachedBottom = !recyclerView.canScrollVertically(-5);
if (reachedBottom){
String desc = lastVisible.getString("comment");
Toast.makeText(getContext(),"Reached: " + desc ,Toast.LENGTH_SHORT).show();
loadMore();
/* final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
}
},5000);*/
}
}
});
}
toolbar = view.findViewById(R.id.toolbar);
toolbar.setTitle("Comments");
toolbar.setTitleTextColor(Color.BLACK);
comment_text = view.findViewById(R.id.comment_text);
comment_button = view.findViewById(R.id.comment_button);
comment_button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
db.collection("Reviews").document(document_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.getResult().exists()){
DocumentReference newComment = db.collection("Reviews").document(document_id).collection("Comments").document();
CommentInfo commentInfo = new CommentInfo();
commentInfo.setUser_id(currentUserID);
commentInfo.setComment(comment_text.getText().toString().trim());
newComment.set(commentInfo);
comment_text.getText().clear();
}
else {
Toast.makeText(getContext(), "This review has been removed, please refresh your feed.", Toast.LENGTH_LONG).show();
}
}
});
}
});
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public void loadMore(){
Query nextQuery = db.collection("Reviews").document(document_id).collection("Comments")
.orderBy("date_posted", Query.Direction.DESCENDING)
.startAfter(lastVisible)
.limit(10);
nextQuery.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshot, #Nullable FirebaseFirestoreException e) {
if (e == null){
if (!documentSnapshot.isEmpty()){
lastVisible = documentSnapshot.getDocuments().get(documentSnapshot.size()-1);
for (DocumentChange documentChange: documentSnapshot.getDocumentChanges()){
if (documentChange.getType() == DocumentChange.Type.ADDED){
String commentID = documentChange.getDocument().getId();
CommentInfo commentAdded = documentChange.getDocument().toObject(CommentInfo.class);
comments_list.add(commentAdded);
commentsAdapter.notifyDataSetChanged();
}
else if (documentChange.getType() == DocumentChange.Type.REMOVED){
comments_list.remove(documentChange.getOldIndex());
commentsAdapter.notifyItemRemoved(documentChange.getOldIndex());
}
else if (documentChange.getType() == DocumentChange.Type.MODIFIED){
// modifying
CommentInfo commentModified = documentChange.getDocument().toObject(CommentInfo.class);
if (documentChange.getOldIndex() == documentChange.getNewIndex()) {
// Item changed but remained in same position
comments_list.set(documentChange.getOldIndex(),commentModified);
commentsAdapter.notifyItemChanged(documentChange.getOldIndex());
}else {
// Item changed and changed position
comments_list.remove(documentChange.getOldIndex());
comments_list.add(documentChange.getNewIndex(),commentModified);
commentsAdapter.notifyItemMoved(documentChange.getOldIndex(),documentChange.getNewIndex());
}
commentsAdapter.notifyDataSetChanged();
}
}
}
}
}
});
}
#NonNull #Override public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override public void onShow(DialogInterface dialogInterface) {
BottomSheetDialog bottomSheetDialog = (BottomSheetDialog) dialogInterface;
setupFullHeight(bottomSheetDialog);
}
});
return dialog;
}
private void setupFullHeight(BottomSheetDialog bottomSheetDialog) {
FrameLayout bottomSheet = (FrameLayout) bottomSheetDialog.findViewById(R.id.design_bottom_sheet);
BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
ViewGroup.LayoutParams layoutParams = bottomSheet.getLayoutParams();
int windowHeight = getWindowHeight();
if (layoutParams != null) {
layoutParams.height = windowHeight;
}
bottomSheet.setLayoutParams(layoutParams);
behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
}
private int getWindowHeight() {
// Calculate window height for fullscreen use
DisplayMetrics displayMetrics = new DisplayMetrics();
((Activity) getContext()).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics.heightPixels;
}
}
public class CommentsAdapter extends RecyclerView.Adapter<CommentsAdapter.ViewHolder> {
private Context context;
private FirebaseFirestore db;
public List<CommentInfo> comments_list;
public CommentsAdapter(List<CommentInfo> comments_list){
this.comments_list = comments_list;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view_comments,parent,false);
context = parent.getContext();
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
db = FirebaseFirestore.getInstance();
//final String commentID = comments_list.get(position)
String comment = comments_list.get(position).getComment();
holder.setComment(comment);
final String commentUserID = comments_list.get(position).getUser_id();
DocumentReference userData = db.collection("Users").document(commentUserID);
userData.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
#Override
public void onComplete(#NonNull Task<DocumentSnapshot> task) {
if (task.isSuccessful()) {
if (task.getResult().exists()) {
String firstname = task.getResult().getString("first_name");
String lastname = task.getResult().getString("last_name");
String userPicture = task.getResult().getString("profile_picture");
holder.setUserData(firstname,lastname,userPicture);
}
}
}
});
}
#Override
public int getItemCount() {
return comments_list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private View mView;
private TextView comment, first_name, last_name;
CircleImageView users_profile_picture;
public ViewHolder(#NonNull final View itemView) {
super(itemView);
mView = itemView;
}
public void setComment(String CommentText){
comment = mView.findViewById(R.id.comment);
comment.setText(CommentText);
}
private void setUserData(String firstName, String lastName, String profilePicture){
first_name = mView.findViewById(R.id.first_name);
last_name = mView.findViewById(R.id.last_name);
users_profile_picture = mView.findViewById(R.id.users_profile_picture);
first_name.setText(firstName);
last_name.setText(lastName);
if (profilePicture != null){
Glide.with(context).load(profilePicture).into(users_profile_picture);
}
}
}
}
#IgnoreExtraProperties
public class CommentInfo {
private String user_id;
private String comment;
private #ServerTimestamp Date date_posted;
public CommentInfo(){
}
public CommentInfo(String user_id, String comment, Date date_posted) {
this.user_id = user_id;
this.comment = comment;
this.date_posted = date_posted;
}
public String getUser_id() {
return user_id;
}
public void setUser_id(String user_id) {
this.user_id = user_id;
}
public String getComment() {
return comment;
}
public void setComment(String comment) {
this.comment = comment;
}
public Date getDate_posted() {
return date_posted;
}
public void setDate_posted(Date date_posted) {
this.date_posted = date_posted;
}
}
The error message is:
Invalid query. You are trying to start or end a query using a document for which the field 'date_posted' is an uncommitted server timestamp. (Since the value of this field is unknown, you cannot start/end a query with it.)
So it looks like it comes from this:
Query nextQuery = db.collection("Reviews").document(document_id).collection("Comments")
.orderBy("date_posted", Query.Direction.DESCENDING)
.startAfter(lastVisible)
.limit(10);
From the error message it seems that the date_posted field may have unknown values, in which case you can't query on it.
This comes from:
private #ServerTimestamp Date date_posted;
From this Github issue with multiple comments from Firestore team members, it seems that:
pagination and server-issued time are essentially incompatible
I have a feed with posts from different users that is built using the FirebaseRecyclerAdapter.
It works fine but when i change a user's profile picture i want the profile picture from all of that user's posts to change as well.
At the moment it just displays the profile picture that was present at the moment the post was created.
Here is the code:
I call chooseImage when i click the upload button:
private void chooseImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
startActivityForResult(intent, PICK_IMAGE_REQUEST);
}
#Override
public 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) {
imageUri = data.getData();
uploadImage();
}
}
private void uploadImage() {
if (imageUri != null) {
StorageReference fileReference = storageReference
.child(FirebaseAuth.getInstance().getCurrentUser().getUid() + "." + getImageExtension(imageUri));
fileReference.putFile(imageUri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Handler handler = new Handler();
Picasso.with(getContext()).load(imageUri).into(imgProfile);
handler.postDelayed(new Runnable() {
#Override
public void run() {
progressBar.setProgress(0);
progressBar.setVisibility(View.GONE);
}
}, 1000);
Toast.makeText(getActivity(), "Image changed successfully", Toast.LENGTH_LONG).show();
databaseReference.child("profilePic").setValue(taskSnapshot.getStorage().getDownloadUrl().toString());
UserProfileChangeRequest profileChangeRequest = new UserProfileChangeRequest.Builder()
.setPhotoUri(imageUri)
.build();
user.updateProfile(profileChangeRequest);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
})
.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(#NonNull UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount());
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress((int) progress);
}
});
} else {
Toast.makeText(this.getContext(), "No image selected", Toast.LENGTH_SHORT).show();
}
}
This is how i add the posts:
btnPostComm.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String story = et.getText().toString();
String title = et2.getText().toString();
String key = refference.push().getKey();
String name = user.getDisplayName();
String uri = user.getPhotoUrl().toString();
CommModel model = new CommModel(
story,
title,
name,
uri
);
refference
.child(key)
.setValue(model);
}
});
This is my Model class:
public class CommModel {
private String story;
private String title;
private String name;
private String uri;
public CommModel(){}
public CommModel(String story, String title, String name, String uri) {
this.story = story;
this.title = title;
this.name = name;
this.uri = uri;
}
public String getStory() {
return story;
}
public void setStory(String story) {
this.story = story;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
This is the ViewHolder:
public class PostsViewHolder extends RecyclerView.ViewHolder {
public TextView txtStory;
public TextView txtTitle;
public TextView txtName;
public CircularImageView proImage;
public QNAViewHolder(#NonNull View itemView) {
super(itemView);
txtStory = itemView.findViewById(R.id.txtStory);
txtTitle = itemView.findViewById(R.id.txtTitle);
txtName = itemView.findViewById(R.id.txtName1);
proImage = itemView.findViewById(R.id.profile3);
}
}
And this is the Adapter in the Fragment that hosts the RecyclerView:
public void showPosts() {
FirebaseRecyclerOptions options = new FirebaseRecyclerOptions.Builder<CommModel>()
.setQuery(ref, CommModel.class)
.build();
adpt = new FirebaseRecyclerAdapter<CommModel, PostsViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull PostsViewHolder holder, int position, #NonNull CommModel model) {
holder.txtStory.setText(model.getStory());
holder.txtTitle.setText(model.getTitle());
holder.txtName.setText(model.getName());
Glide.with(Posts.this).load(model.getUri()).into(holder.proImage);
}
#Override
public int getItemCount() {
return super.getItemCount();
}
#Override
public void onDataChanged() {
recyclerView.removeAllViews();
super.onDataChanged();
}
#NonNull
#Override
public CommModel getItem(int position) {
return super.getItem(getItemCount() - 1 - position);
}
#NonNull
#Override
public PostsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.qna_feed, parent, false);
return new PostsViewHolder(view);
}
};
adpt.startListening();
adpt.notifyDataSetChanged();
recyclerView.setAdapter(adpt);
}
How can i update the pictures on every post of a user when he changes his profile pic?
Thank you very much!
If you want to do that, you have to change the CommModel class. You need to add another property, such as userUid.
private String story;
private String title;
private String name;
private String uri;
private String userUid; //Create new one and getter setter too
After that, at your showPosts method, you can call the user's property and get his profile picture.
holder.txtStory.setText(model.getStory());
holder.txtTitle.setText(model.getTitle());
holder.txtName.setText(model.getName());
final String userUid = model.getUserUid();
//Call Firebase to get user current profile.
FirebaseDatabase.getInstance().getReference().child("User").child(userUid).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exist()){
final String pictureUrl = dataSnapshot.chilld("profilePic").getValue(String.class);
Glide.with(Posts.this).load(pictureUrl).into(holder.proImage);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
I'm not able to see the recycle view, not sure where It has gone wrong. It would be great if you can help me.
Fragment
public class CallDurationFragment extends Fragment {
final FirebaseDatabase database = FirebaseDatabase.getInstance();
ArrayList<CallHistroy> callList = new ArrayList<>();
ArrayList<CallHistroy> callListTemp = new ArrayList<>();
ArrayList<CallHistroy> callObject = new ArrayList<>();
ArrayList<CallHistroy> callListText = new ArrayList<>();
private CallDurationFragment.OnFragmentInteractionListener mListener;
private RecyclerView rvCall;
private RecyclerView.Adapter callAdaptor;
private RecyclerView.LayoutManager eLayoutManager;
private EditText phoneNumber;
private static final int DIALOG_DATE_PICKER = 100;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_callduration_list, container, false);
phoneNumber = (EditText) getActivity().findViewById(editTextSearchKeyPhoneNo);
Context context = getActivity();
rvCall = (RecyclerView) rootView.findViewById(R.id.rvCallDuration);
rvCall.setHasFixedSize(true);
rvCall.setLayoutManager(eLayoutManager);
eLayoutManager = new LinearLayoutManager(getActivity());
phoneNumber.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
callListTemp = getAllCallRecords();
for(int i = 0 ; i < callListTemp.size() ; i++)
if(callListTemp.get(i).getPhoneNumber().contains(s.toString()) )
callListText.add(callListTemp.get(i));
callList = calculateIncomingOutgoing();
callAdaptor = new CallDurationAdapter(getActivity(), callList);
rvCall.setAdapter(callAdaptor);
}
public void beforeTextChanged(CharSequence s, int start,
int count, int after) {
}
public void onTextChanged(CharSequence s, int start,
int before, int count) {
}
});
callList = calculateIncomingOutgoing();
callAdaptor = new CallDurationAdapter(getActivity(), callList);
rvCall.setAdapter(callAdaptor);
return rootView;
}
public ArrayList<CallHistroy> getAllCallRecords(){
DatabaseReference ref = database.getReference();
ref.child("Call").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
callObject.clear();
HashMap<String,Object> call = null;
Iterator<DataSnapshot> items = dataSnapshot.getChildren().iterator();
while(items.hasNext()){
DataSnapshot item = items.next();
Log.e("Listener",item.toString() );
call =(HashMap<String, Object>) item.getValue();
callObject.add(new CallHistroy(call.get("phoneNumber").toString(),call.get("mode").toString(),call.get("duration").toString(), call.get("date").toString(),item.getKey()));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
return callObject;
}
public ArrayList<CallHistroy> calculateIncomingOutgoing(){
if(callListText.size() > 0){
callList = callListText;
}else {
callList = getAllCallRecords();
}
ArrayList<CallHistroy> callHistroyIncomingOutgoing = new ArrayList<>();
if(callList.size() > 0){
if(callList.get(0).getMode().equals("Outgoing")) {
callHistroyIncomingOutgoing.add(new CallHistroy(callList.get(0).getPhoneNumber(), "0", callList.get(0).getDuration()));
}else{
callHistroyIncomingOutgoing.add(new CallHistroy(callList.get(0).getPhoneNumber(), callList.get(0).getDuration(), "0"));
}
}
for( int i = 1 ; i < callList.size() ; i++){
boolean setValue = false;
for (int j = 0; j < callHistroyIncomingOutgoing.size() ;j++){
if( callHistroyIncomingOutgoing.get(j).getPhoneNumber().equals(callList.get(i).getPhoneNumber())){
setValue = true;
int incoming = Integer.parseInt(callHistroyIncomingOutgoing.get(j).getIncomingDuration());
int outgoing = Integer.parseInt( callHistroyIncomingOutgoing.get(j).getOutgoingDuration());
int duration = Integer.parseInt( callList.get(i).getDuration());
if(callList.get(i).getMode().equals("Outgoing")) {
callHistroyIncomingOutgoing.get(j).updateDuration(String.valueOf(incoming), String.valueOf(outgoing + duration));
}else{
callHistroyIncomingOutgoing.get(j).updateDuration(String.valueOf(incoming + duration), String.valueOf(outgoing));
}
}
}
if(!setValue) {
if(callList.get(i).getMode() == "Outgoing") {
callHistroyIncomingOutgoing.add(new CallHistroy(callList.get(i).getPhoneNumber(), "0", callList.get(i).getDuration()));
}else{
callHistroyIncomingOutgoing.add(new CallHistroy(callList.get(i).getPhoneNumber(), callList.get(i).getDuration(), "0"));
}
}
}
return callHistroyIncomingOutgoing;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof CallListFragment.OnFragmentInteractionListener) {
mListener = (CallDurationFragment.OnFragmentInteractionListener) context;
}
}
#Override
public void onDetach() {
super.onDetach();
mListener = null;
}
#Override
public void onPause(){
super.onPause();
}
#Override
public void onDestroyView(){
super.onDestroyView();
}
#Override
public void onDestroy(){
super.onDestroy();
}
public interface OnFragmentInteractionListener {
// TODO: Update argument type and name
void onFragmentInteraction(Uri uri);
}
}
Adaptor
RecyclerView.Adapter<CallDurationAdapter.ViewHolder> {
private List<CallHistroy> mCalls;
private Context mContext;
public CallDurationAdapter(Context context, List<CallHistroy> calls) {
mCalls = calls;
mContext = context;
}
private Context getContext() {
return mContext;
}
#Override
public CallDurationAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater inflater = LayoutInflater.from(context);
// Inflate the custom layout
View callDurationView = inflater.inflate(R.layout.item_call_duration_details, parent, false);
// Return a new holder instance
ViewHolder viewHolder = new ViewHolder(callDurationView);
return viewHolder;
}
#Override
public void onBindViewHolder(CallDurationAdapter.ViewHolder viewHolder, final int position) {
// Get the data model based on position
final CallHistroy ch = mCalls.get(position);
// Set item views based on your views and data model
viewHolder._phoneNoTextView.setText(ch.getPhoneNumber());
viewHolder._incomingTextView.setText(ch.getIncomingDuration());
viewHolder._outgoingTextView.setText(ch.getOutgoingDuration());
final String key = ch.getKey();
}
#Override
public int getItemCount() {
return mCalls.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView _phoneNoTextView;
public TextView _incomingTextView;
public TextView _outgoingTextView;
public ViewHolder(View itemView) {
super(itemView);
_phoneNoTextView = (TextView) itemView.findViewById(R.id.rvs_duration_phone_no);
_incomingTextView = (TextView) itemView.findViewById(R.id.rvs_duration_outing_total_call);
_outgoingTextView = (TextView) itemView.findViewById(R.id.rvs_duration_incoming_total_call);
}
}
}
Activity
public class CallDurationActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_call_duration);
CallDurationFragment newFragment = new CallDurationFragment();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.recordFragmentContainer, newFragment);
transaction.addToBackStack(null);
transaction.commit();
}
public void refreshCallDuration(View v) {
Intent intent = new Intent(this, CallDurationActivity.class);
startActivity(intent);
}
protected void onPause() {
super.onPause();
}
protected void onStop() {
super.onStop();
}
protected void onDestroy() {
super.onDestroy();
}
public void onBackCallDuration(View v) {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
}
Object
public class CallHistroy implements Comparable<CallHistroy> {
String phoneNumber;
String mode;
String duration;
String date;
String key;
String incomingDuration;
String outgoingDuration;
int totalIncoming;
int totalOutgoing;
public CallHistroy(String _phontNumber, String _incomingDuration, String _outgoingDuration ){
setPhoneNumber( _phontNumber );
setIncomingDuration( _incomingDuration );
setOutgoingDuration( _outgoingDuration );
}
public CallHistroy(String _date, int _totalIncoming, int _totalOutgoing ){
setDate(_date);
setTotalIncoming( _totalIncoming );
setTotalOutgoing( _totalOutgoing );
}
public void updateCall(int _totalIncoming, int _totalOutgoing){
setTotalIncoming( _totalIncoming );
setTotalOutgoing( _totalOutgoing );
}
public void updateDuration(String _incomingDuration, String _outgoingDuration){
setOutgoingDuration( _incomingDuration );
setIncomingDuration( _outgoingDuration );
}
public CallHistroy(String _phoneNumber, String _mode, String _duration, String _date ){
setPhoneNumber( _phoneNumber );
setDuration( _duration );
setDate( _date );
setMode( _mode );
}
public CallHistroy(String _phoneNumber, String _mode, String _duration, String _date, String _key ){
setPhoneNumber( _phoneNumber );
setDuration( _duration );
setDate( _date );
setMode( _mode );
setKey( _key );
}
public String getIncomingDuration() {
return incomingDuration;
}
public String getOutgoingDuration() {
return outgoingDuration;
}
public int getTotalIncoming() {
return totalIncoming;
}
public int getTotalOutgoing() {
return totalOutgoing;
}
public void setIncomingDuration(String incomingDuration) {
this.incomingDuration = incomingDuration;
}
public void setOutgoingDuration(String outgoingDuration) {
this.outgoingDuration = outgoingDuration;
}
public void setTotalIncoming(int totalIncoming) {
this.totalIncoming = totalIncoming;
}
public void setTotalOutgoing(int totalOutgoing) {
this.totalOutgoing = totalOutgoing;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getPhoneNumber() {
return phoneNumber;
}
public String getDate() {
return date;
}
public String getMode() {
return mode;
}
public String getDuration() {
return duration;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public void setDate(String date) {
this.date = date;
}
public void setDuration(String duration) {
this.duration = duration;
}
public void setMode(String mode) {
this.mode = mode;
}
#Override
public int compareTo(#NonNull CallHistroy callHistroyObject) {
String[] part = callHistroyObject.date.split("/");
String[] part1 = date.split("/");
int date = Integer.parseInt(part[0]);
int month = Integer.parseInt(part[1]);
String _year = part[2];
int year = Integer.parseInt(_year.substring(0,4));
int date1 = Integer.parseInt(part1[0]);
int month1 = Integer.parseInt(part1[1]);
String _year1 = part1[2];
int year1 = Integer.parseInt(_year1.substring(0,4));
if(year > year1)
return -1;
else if(month > month1)
return -1;
else if(date >date1)
return -1;
else
return 0;
}
}
You're setting your layout manager before it's created
rvCall.setLayoutManager(eLayoutManager);
eLayoutManager = new LinearLayoutManager(getActivity());
should be
eLayoutManager = new LinearLayoutManager(getActivity());
rvCall.setLayoutManager(eLayoutManager);
I followed a Tutorial and was Successfully able to Load the data in Firebase and also retrieve it back in RecyclerView and also Learned How to Delete data but now I'm Stuck that how to update this data in the Firebase and show it in RecyclerView.I have used Picasso for the Images.
This is my Gallery.java file
public class Gallery extends AppCompatActivity {
private static final int PICK_IMAGE_REQUEST= 1;
private Button mButtonChooseImage;
private Button mButtonUpload;
private TextView mTextViewShowGallery;
private EditText mEditTextFileName,mEditTextDesc;
private ImageView mImageView;
private ProgressBar mProgressBar;
private Uri mImageUri;
private StorageReference mStorageRef;
private DatabaseReference mDatabaseRef;
private StorageTask mUploadTask;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gallery);
mButtonChooseImage = (Button)findViewById(R.id.btnChoose);
mButtonUpload = (Button)findViewById(R.id.btnUpload);
mTextViewShowGallery = (TextView)findViewById(R.id.tvShow);
mImageView = (ImageView)findViewById(R.id.imgView);
mProgressBar = (ProgressBar)findViewById(R.id.progress_bar);
mEditTextFileName = (EditText)findViewById(R.id.txtName);
mEditTextDesc = (EditText)findViewById(R.id.txtDesc);
mStorageRef = FirebaseStorage.getInstance().getReference("uploads");
mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
mButtonChooseImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openFileChooser();
}
});
mButtonUpload.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mUploadTask != null && mUploadTask.isInProgress())
{
Toast.makeText(Gallery.this, "Upload In Progress", Toast.LENGTH_SHORT).show();
}
else
{
uploadFile();
}
}
});
mTextViewShowGallery.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openImagesActivity();
}
});
}
private void openFileChooser ()
{
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, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK
&& data != null && data.getData() != null)
{
mImageUri = data.getData();
Picasso.with(this).load(mImageUri).into(mImageView);
}
}
private String getFileExtension(Uri uri)
{
ContentResolver cR = getContentResolver();
MimeTypeMap mime = MimeTypeMap.getSingleton();
return mime.getExtensionFromMimeType(cR.getType(uri));
}
private void uploadFile()
{
if (mImageUri != null)
{
StorageReference fileReference = mStorageRef.child(System.currentTimeMillis()
+ "." + getFileExtension(mImageUri));
mUploadTask = fileReference.putFile(mImageUri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
mProgressBar.setProgress(0);
}
},500);
Toast.makeText(Gallery.this, "Upload Successful", Toast.LENGTH_LONG).show();
UploadImage uploadImage = new UploadImage(mEditTextFileName.getText().toString().trim(),
mEditTextDesc.getText().toString().trim(),taskSnapshot.getDownloadUrl().toString());
String uploadId = mDatabaseRef.push().getKey();
mDatabaseRef.child(uploadId).setValue(uploadImage);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(Gallery.this,e.getMessage(), Toast.LENGTH_SHORT).show();
}
})
.addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
#Override
public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
double progress = (100.0 * taskSnapshot.getBytesTransferred() / taskSnapshot.getTotalByteCount());
mProgressBar.setProgress((int)progress);
}
});
} else {
Toast.makeText(this, "No File Selected", Toast.LENGTH_SHORT).show();
}
}
private void openImagesActivity()
{
Intent intent = new Intent(Gallery.this,ImagesActivity.class);
startActivity(intent);
}
}
This below one is the ImagesActivity which is for the recyclerview, here the delete operation works, as I mentioned and I have used the AlertDialog to open and update the details I tried to Mimic some things from gallery.java but was not able to figure out how they should be Arranged.
public class ImagesActivity extends AppCompatActivity implements ImageAdapter.OnItemClickListener {
private RecyclerView mRecyclerView;
private ImageAdapter mAdapter;
private ProgressBar mProgressCircle;
private static final int PICK_IMAGE_REQUEST= 1;
private StorageTask mUploadTask;
private Uri mImageUri;
private StorageReference mStorageRef;
private FirebaseStorage mStorage;
private DatabaseReference mDatabaseRef;
private ValueEventListener mDBListener;
private List<UploadImage> mUploads;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_images);
mRecyclerView = findViewById(R.id.recycler_view);
mProgressCircle= findViewById(R.id.progress_circle);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
mUploads = new ArrayList<>();
mAdapter = new ImageAdapter(ImagesActivity.this,mUploads);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(ImagesActivity.this);
mStorage = FirebaseStorage.getInstance();
mDatabaseRef = FirebaseDatabase.getInstance().getReference("uploads");
mDBListener = mDatabaseRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
mUploads.clear();
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()){
UploadImage uploadImage = postSnapshot.getValue(UploadImage.class);
uploadImage.setKey(postSnapshot.getKey());
mUploads.add(uploadImage);
}
mAdapter.notifyDataSetChanged();
mProgressCircle.setVisibility(View.INVISIBLE);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(ImagesActivity.this, databaseError.getMessage(), Toast.LENGTH_SHORT).show();
mProgressCircle.setVisibility(View.INVISIBLE);
}
});
}
private String getFileExtension(Uri uri)
{
ContentResolver cR = getContentResolver();
MimeTypeMap mime = MimeTypeMap.getSingleton();
return mime.getExtensionFromMimeType(cR.getType(uri));
}
#Override
public void onItemClick(int position) {
Toast.makeText(this, "Normal Click", Toast.LENGTH_SHORT).show();
}
#Override
public void onUpdateClick(int position) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
LayoutInflater inflater = getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.update_dialog, null);
dialogBuilder.setView(dialogView);
final EditText TextName = (EditText) dialogView.findViewById(R.id.txtName);
final EditText TextDesc = (EditText) dialogView.findViewById(R.id.txtDesc);
final ImageView ImageView = (ImageView) dialogView.findViewById(R.id.imgView);
final Button chooseFile = (Button) dialogView.findViewById(R.id.btnChoose);
final Button UpdateDetails = (Button) dialogView.findViewById(R.id.btnUpdate);
dialogBuilder.setTitle("Update Details");
final AlertDialog b = dialogBuilder.create();
b.show();
chooseFile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
openFileChooser();
}
});
UpdateDetails.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (mUploadTask != null && mUploadTask.isInProgress())
{
Toast.makeText(ImagesActivity.this, "Upload In Progress", Toast.LENGTH_SHORT).show();
}
else
{
if (mImageUri != null)
{
StorageReference fileReference = mStorageRef.child(System.currentTimeMillis()
+ "." + getFileExtension(mImageUri));
mUploadTask = fileReference.putFile(mImageUri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
Toast.makeText(ImagesActivity.this, "Update Successful", Toast.LENGTH_LONG).show();
UploadImage uploadImage = new UploadImage(TextName.getText().toString().trim(),
TextDesc.getText().toString().trim(),taskSnapshot.getDownloadUrl().toString());
String uploadId = mDatabaseRef.push().getKey();
mDatabaseRef.setValue(uploadImage);
mDatabaseRef.child(uploadId).setValue(uploadImage);
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(ImagesActivity.this,e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} else {
Toast.makeText(ImagesActivity.this, "No File Selected", Toast.LENGTH_SHORT).show();
}
}
b.dismiss();
}
});
UploadImage selectedItem = mUploads.get(position);
final String selectedKey = selectedItem.getKey();
// Toast.makeText(this, "Update Clicked", Toast.LENGTH_SHORT).show();
}
private void openFileChooser() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(intent,PICK_IMAGE_REQUEST);
}
#Override
public void onDeleteClick(int position) {
UploadImage selectedItem = mUploads.get(position);
final String selectedKey = selectedItem.getKey();
StorageReference imageRef = mStorage.getReferenceFromUrl(selectedItem.getImageUrl());
imageRef.delete().addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
mDatabaseRef.child(selectedKey).removeValue();
Toast.makeText(ImagesActivity.this, "Item Deleted", Toast.LENGTH_SHORT).show();
}
});
}
#Override
protected void onDestroy() {
super.onDestroy();
mDatabaseRef.removeEventListener(mDBListener);
}
}
This below one is for set and get methods named as UploadImage.java
public class UploadImage {
private String mName;
private String mDesc;
private String mImageUrl;
private String mKey;
public UploadImage()
{
//Empty Constructor Needed
}
public UploadImage(String name, String desc, String imageUrl)
{
if (name.trim().equals(""))
{
name = "No Name";
desc = "No Description";
}
mName = name;
mDesc = desc;
mImageUrl = imageUrl;
}
public String getName() {
return mName;
}
public void setName(String name) {
mName = name;
}
public String getDesc() {
return mDesc;
}
public void setDesc(String desc) {
mDesc=desc;
}
public String getImageUrl() {
return mImageUrl;
}
public void setImageUrl(String imageUrl) {
mImageUrl=imageUrl;
}
#Exclude
public String getKey(){
return mKey;
}
#Exclude
public void setKey(String key){
mKey = key;
}
}
The following one for the Adapter
public class ImageAdapter extends RecyclerView.Adapter<ImageAdapter.ImageViewHolder> {
private Context mContext;
private List<UploadImage> mUploads;
private OnItemClickListener mListener;
public ImageAdapter(Context context, List<UploadImage> uploads){
mContext = context;
mUploads = uploads;
}
#Override
public ImageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(mContext).inflate(R.layout.image_item,parent,false);
return new ImageViewHolder(v);
}
#Override
public void onBindViewHolder(ImageViewHolder holder, int position) {
UploadImage uploadImageCurrent = mUploads.get(position);
holder.textViewName.setText(uploadImageCurrent.getName());
Picasso.with(mContext)
.load(uploadImageCurrent.getImageUrl())
.placeholder(R.drawable.ic_image_black_24dp)
.fit()
.centerCrop()
.into(holder.imageView);
}
#Override
public int getItemCount() {
return mUploads.size();
}
public class ImageViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener{
public TextView textViewName;
public ImageView imageView;
public ImageViewHolder(View itemView) {
super(itemView);
textViewName = itemView.findViewById(R.id.text_view_name);
imageView = itemView.findViewById(R.id.image_view_upload);
itemView.setOnClickListener(this);
itemView.setOnCreateContextMenuListener(this);
}
#Override
public void onClick(View v) {
if (mListener != null)
{
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
//To Handle Normal Item Clicks
mListener.onItemClick(position);
}
}
}
#Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.setHeaderTitle("Select Action");
MenuItem Update = menu.add(Menu.NONE, 1, 1, "Update");
MenuItem Delete = menu.add(Menu.NONE, 2, 2, "Delete");
Update.setOnMenuItemClickListener(this);
Delete.setOnMenuItemClickListener(this);
}
#Override
public boolean onMenuItemClick(MenuItem item) {
if (mListener != null)
{
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION){
//To Check Which Menu Item Was Clicked
switch (item.getItemId())
{
case 1:
mListener.onUpdateClick(position);
return true;
case 2:
mListener.onDeleteClick(position);
return true;
}
}
}
return false;
}
}
public interface OnItemClickListener{
void onItemClick(int position);
void onUpdateClick(int position);
void onDeleteClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener){
mListener = listener;
}
}
Any Solution for this how can I update it.
There is no update method in firebase storage, So for a workaround:
get the name the file you want to delete
delete the file you want to update
upload the new file
rename file with the previous file name