Android project issue [closed] - java

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm having some particular problems with my android project.
In particular I have two collections, Users and Courses:
the first one comprehend the list of users (teachers) which have two Strings (email and idCourse)
in the second one there is the list of courses, each one relating to a user (idCourse is the same of the user), inside each course there is a list of lesson which i need to access with a specific user.
I saved in an object admin its data to access to a specific Lessons collection, because in the path there is the admin id.
Courses path to Lessons
Users collection
I tried to, but when i save the id in the addCompleteListener method the data get lost outside, indeed in the addSnapshotListener the value of admin.getCourseId() is null so my recyclerView results empty.
If I try to copy the second method in the first one, as soon as I save the idCourse in Admin, the method works, but if I click on the lesson when i use the app, the app crashes.
I know this may be a specifical issue of mine, but i would like to hear something from you about it.
I'm posting my android project too.
Android Project on Google Drive
Thanks in advance for your help!
CLASS LezioniDocenteActivity:
public class LezioniDocenteActivity extends AppCompatActivity {
private static final String TAG = "FireLog";
private RecyclerView mMainList;
private FirebaseFirestore mFirestore;
private FirebaseAuth firebaseAuth;
private LessonsListAdapter lessonsListAdapter;
private List<Lesson> lessonList;
private String course_id;
//admin per memorizzare le info
private final User admin = new User();
#Override
public void onBackPressed(){
startActivity(new Intent(LezioniDocenteActivity.this, DocenteActivity.class));
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lezioni_docente);
lessonList = new ArrayList<>();
lessonsListAdapter = new LessonsListAdapter(lessonList, getApplicationContext());
mMainList = (RecyclerView)findViewById(R.id.lesson_list);
mMainList.setHasFixedSize(true);
mMainList.setLayoutManager(new LinearLayoutManager(this));
mMainList.setAdapter(lessonsListAdapter);
firebaseAuth = FirebaseAuth.getInstance();
//utente in uso corrente
final FirebaseUser user = firebaseAuth.getCurrentUser();
admin.setEmail(user.getEmail());
mFirestore = FirebaseFirestore.getInstance();
mFirestore.collection("Users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
boolean find = false;
for (DocumentSnapshot doc : task.getResult()) {
String email = doc.getString("email");
if (email.equals(admin.getEmail())) {
//getting admin's courseID
admin.setCourseId(doc.getString("idCorso"));
break;
}
}
}
});
mFirestore.collection("Courses /" + admin.getCourseId() + "/Lessons").addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshots, #Nullable FirebaseFirestoreException e) {
if(e!=null){
Log.d(TAG, "Error :" + e.getMessage());
return;
}
for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
if(doc.getType() == DocumentChange.Type.ADDED){
Lesson lesson = doc.getDocument().toObject(Lesson.class);
lessonList.add(lesson);
lessonsListAdapter.notifyDataSetChanged();
}
}
}
});
}
}
CLASS LessonListAdapter:
public class LessonsListAdapter extends RecyclerView.Adapter<LessonsListAdapter.ViewHolder> {
public List<Lesson> lessonList;
public Context context;
final User admin = new User();
public LessonsListAdapter(List<Lesson> lessonList, Context context){
this.lessonList = lessonList;
this.context = this.context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_lessons, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, int position) {
final FirebaseFirestore firebaseFirestore = FirebaseFirestore.getInstance();
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final FirebaseUser user = firebaseAuth.getCurrentUser();
admin.setEmail(user.getEmail());
holder.dayText.setText(lessonList.get(position).getLessonDate());
holder.argText.setText(lessonList.get(position).getArgument());
final String lessID = lessonList.get(position).lessonID;
final int i = position;
firebaseFirestore.collection("Users").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
boolean find = false;
for(DocumentSnapshot doc : task.getResult()){
String email = doc.getString("email");
if(email.equals(admin.getEmail())) {
find = true;
//getting admin's courseID
admin.setCourseId(doc.getString("courseId"));
break;
}
}
if (find){
holder.delete.setVisibility(View.VISIBLE);
holder.delete.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(context, "OnClick funziona", Toast.LENGTH_SHORT).show();
}
});
} else holder.delete.setVisibility(View.GONE);
}
});
}
#Override
public int getItemCount() {
return lessonList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
View mView;
public TextView dayText;
public TextView argText;
public ImageView delete;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mView = itemView;
dayText = (TextView) mView.findViewById(R.id.day_text);
argText = (TextView) mView.findViewById(R.id.arg_text);
delete = (ImageView) mView.findViewById(R.id.ic_delete);
}
}
}

The following code will work for you. But you have to make changes according to it. I am not using Android Studio. It's notepad code.
mfirebaseFirestore.collection("Users").orderBy("email")
.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
for (QueryDocumentSnapshot querySnapshot : task.getResult()){
if (querySnapshot.get("email").equals(user.getEmail())){
mfirebaseFirestore.collection("Courses/"+ querySnapshot.get("idCorso")+"/Lessons")
.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot documentSnapshots, #Nullable FirebaseFirestoreException e) {
for(DocumentChange doc : documentSnapshots.getDocumentChanges()){
if(doc.getType() == DocumentChange.Type.ADDED){
Lesson lesson = doc.getDocument().toObject(Lesson.class);
lessonList.add(lesson);
}
lessonsListAdapter = new LessonsListAdapter(lessonList, getApplicationContext());
lessonsListAdapter.notifyDataSetChanged();
}
}
});
}
}
}
});
Explanation about code :
From above code as everyone explained Firebase calls are asynchronous (e.g. answer). So the data your trying to retrieve is receiving null as you said.
The above code will check in your database about email then retrieve the details of that user. Which means you will get the course id from it. Then directly call the function to retrieve lessons list by passing the course id.

Related

Realtime Display Value Change form Firebase

I am new to android studio and currently watching tutorials. As of now I have a Shopping cart activity where I can increment, decrement and delete items in cart. The thing is whenever I delete, add or deduct an item, the cart values does not update. I still need to change activities to see the changes. Also the item that I deleted still appears at the bottom of recyclerview items after the dialog appearance unless I change the activity and go back. Please help me how to apply real time update. Below are my class files for the cart activity and adapter class.
CartActivity.java
#Override
protected void onStop() {
if (EventBus.getDefault().hasSubscriberForEvent(MyUpdateCartEvent.class))
EventBus.getDefault().removeStickyEvent(MyUpdateCartEvent.class);
EventBus.getDefault().unregister(this);
super.onStop();
}
#Subscribe(threadMode = ThreadMode.MAIN_ORDERED, sticky = true)
public void onUpdateCart(MyUpdateCartEvent event) {
loadCartFromFirebase();
}
private void loadCartFromFirebase() {
fAuth = FirebaseAuth.getInstance();
if(fAuth.getCurrentUser() != null){
userId = fAuth.getCurrentUser().getUid();
} else {
userId = "UNIQUE_USER_ID";
}
List<CartModel> cartModels = new ArrayList<>();
FirebaseDatabase.getInstance()
.getReference("cart")
.child(userId)
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if (snapshot.exists()) {
for (DataSnapshot cartSnapshot : snapshot.getChildren()) {
CartModel cartModel = cartSnapshot.getValue(CartModel.class);
cartModel.setKey(cartSnapshot.getKey());
cartModels.add(cartModel);
}
cartLoadListener.onCartLoadSuccess(cartModels);
} else {
cartLoadListener.onCartLoadFailed("Cart Empty");
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
cartLoadListener.onCartLoadFailed(error.getMessage());
}
});
}
private void init() {
ButterKnife.bind(this);
cartLoadListener = this;
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recycler_cart.setLayoutManager(layoutManager);
purchScrnBtn.setOnClickListener(v -> startActivity(new Intent(this, PurchaseActivity.class)));
}
#Override
public void onCartLoadSuccess(List<CartModel> cartModelList) {
double sum = 0;
for (CartModel cartModel : cartModelList) {
sum += cartModel.getTotalPrice();
}
textTotal.setText(new StringBuilder("$").append(sum));
MyCartAdapter adapter = new MyCartAdapter(this, cartModelList);
recycler_cart.setAdapter(adapter);
}
MyCartAdapter.java
package com.example.cart.adapter;
public class CartActivity extends AppCompatActivity implements CartLoadListener {
public MyCartViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new MyCartViewHolder(LayoutInflater.from(context)
.inflate(R.layout.layout_cart_item, parent, false));
}
#Override
public void onBindViewHolder(#NonNull MyCartViewHolder holder, int position) {
holder.minus.setOnClickListener(v -> {
minusCartItem(holder,cartModelList.get(position));
});
holder.delete.setOnClickListener(v -> {
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle("Delete item")
.setMessage("Do you really want to delete item")
.setNegativeButton("CANCEL", (dialogInterface, i) -> dialogInterface.dismiss())
.setPositiveButton("OK", (dialogInterface2, i) -> {
//Temp remove
notifyItemRemoved(position);
deleteFromFirebase(cartModelList.get(position));
dialogInterface2.dismiss();
}).create();
dialog.show();
});
}
private void deleteFromFirebase(CartModel cartModel) {
FirebaseDatabase.getInstance()
.getReference("cart")
.child(userId)
.child(cartModel.getKey())
.removeValue()
.addOnSuccessListener(aVoid -> EventBus.getDefault().postSticky(new MyUpdateCartEvent()));
}
#SuppressLint("SuspiciousIndentation")
private void minusCartItem(MyCartViewHolder holder, CartModel cartModel) {
if(cartModel.getQuantity() > 1)
cartModel.setQuantity(cartModel.getQuantity()-1);
cartModel.setTotalPrice(cartModel.getQuantity()*Float.parseFloat(cartModel.getPrice()));
//update quantity
holder.txtQuantity.setText(new StringBuilder().append(cartModel.getQuantity()));
updateFirebase(cartModel);
}
public class MyCartViewHolder extends RecyclerView.ViewHolder{
Unbinder unbinder;
public MyCartViewHolder(#NonNull View itemView) {
super(itemView);
unbinder = ButterKnife.bind(this, itemView);
}
}
}
The thing is whenever I delete, add or deduct an item, the cart values does not update.
That's because you load data from Firebase with addListenerForSingleValueEvent, which only loads the data when you call it. If you want to continue to monitor the data for changes, use addValueEventListener instead.

Messages are showing randomly in my chat app not in sequence in firebase android

I have built a chat app in firebase android everything is working fine the only problem is that when users are chatting with each other the messages are not showing in order or sequence they are just showing randomly. Image should be shown in proper sequence but it is not working please check it guide me why this is happning? thank you in adnvace
image here
I have no idea why is this happening
this is Adapter
public class MessageAdapter extends RecyclerView.Adapter {
Context context;
ArrayList<Message> messageArrayList;
int ITEM_SENT = 1;
int ITEM_RECEIVE = 2;
String senderRoom;
String receiverRoom;
public MessageAdapter()
{
}
public MessageAdapter(Context context, ArrayList<Message> messageArrayList, String senderRoom, String receiverRoom) {
this.context = context;
this.messageArrayList = messageArrayList;
this.senderRoom = senderRoom;
this.receiverRoom = receiverRoom;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType==ITEM_SENT)
{
View view = LayoutInflater.from(context).inflate(R.layout.senderchatlayout, parent, false);
return new SenderViewHolder(view);
}else
{
View view = LayoutInflater.from(context).inflate(R.layout.receiverchatlayout, parent, false);
return new RecieverViewHolder(view);
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
Message message = messageArrayList.get(position);
if (holder.getClass() == SenderViewHolder.class)
{
SenderViewHolder viewHolder = (SenderViewHolder) holder;
viewHolder.textViewMessage.setText(message.getMessage());
viewHolder.timeofmessage.setText(message.getCurrenttime());
}else
{
RecieverViewHolder viewHolder = (RecieverViewHolder) holder;
viewHolder.textViewMessage.setText(message.getMessage());
viewHolder.timeofmessage.setText(message.getCurrenttime());
}
}
#Override
public int getItemViewType(int position) {
Message message = messageArrayList.get(position);
if (FirebaseAuth.getInstance().getCurrentUser().getUid().equals(message.getSenderId()))
{
return ITEM_SENT;
}else
{
return ITEM_RECEIVE;
}
}
#Override
public int getItemCount() {
return messageArrayList.size();
}
public class SenderViewHolder extends RecyclerView.ViewHolder
{
TextView textViewMessage;
TextView timeofmessage;
public SenderViewHolder(#NonNull View itemView) {
super(itemView);
textViewMessage = itemView.findViewById(R.id.senderMessage);
timeofmessage = itemView.findViewById(R.id.senderTime);
}
}
public class RecieverViewHolder extends RecyclerView.ViewHolder
{
TextView textViewMessage;
TextView timeofmessage;
public RecieverViewHolder(#NonNull View itemView) {
super(itemView);
textViewMessage = itemView.findViewById(R.id.receiverMessage);
timeofmessage = itemView.findViewById(R.id.receiverTime);
}
}
}
CODE TO GET MESSAGES IN ChatActivity
public class SpecificChatActivity extends AppCompatActivity {
ActivitySpecificChatBinding binding;
private FirebaseAuth auth;
FirebaseFirestore firebaseFirestore;
private String enteredMessage;
String mreceiveruid, msenderuid;
String senderroom, receiverroom;
String currenttime;
Calendar calendar;
String conversionId;
ArrayList<Message> messageArrayList;
MessageAdapter adapter;
SimpleDateFormat simpleDateFormat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivitySpecificChatBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
auth = FirebaseAuth.getInstance();
firebaseFirestore = FirebaseFirestore.getInstance();
calendar = Calendar.getInstance();
simpleDateFormat = new SimpleDateFormat("hh:mm a");
setSupportActionBar(binding.specificToolbar);
messageArrayList = new ArrayList<>();
String id = UUID.randomUUID().toString();
Intent intent = getIntent();
String name = intent.getStringExtra("name");
String image = intent.getStringExtra("profileImage");
msenderuid = auth.getUid();
mreceiveruid = intent.getStringExtra("receiverUid");
senderroom = msenderuid+mreceiveruid;
receiverroom = mreceiveruid+msenderuid;
binding.specificUserName.setText(name);
if (!image.isEmpty())
{
Glide.with(getApplicationContext())
.load(image)
.placeholder(R.drawable.userchaticon)
.into(binding.specificUserImage);
}
binding.sendBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
enteredMessage = binding.messageBox.getText().toString();
if (enteredMessage.isEmpty())
{
Toast.makeText(SpecificChatActivity.this, "Entered some message", Toast.LENGTH_SHORT).show();
}else
{
Date date = new Date();
currenttime = simpleDateFormat.format(calendar.getTime());
Message message = new Message(enteredMessage, auth.getUid(), mreceiveruid, date.getTime(), currenttime, name, image);
firebaseFirestore.collection("Chats")
.document(senderroom)
.collection("Messages")
.document()
.set(message).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
firebaseFirestore.collection("Chats")
.document(receiverroom)
.collection("Messages")
.document()
.set(message).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
}
});
}
});
binding.messageBox.setText(null);
}
}
});
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setStackFromEnd(true);
binding.specificUserRecycler.setLayoutManager(linearLayoutManager);
adapter = new MessageAdapter(SpecificChatActivity.this, messageArrayList, senderroom, receiverroom);
binding.specificUserRecycler.setAdapter(adapter);
CollectionReference collectionReference = firebaseFirestore.collection("Chats").document(senderroom)
.collection("Messages");
collectionReference.addSnapshotListener(new EventListener<QuerySnapshot>() {
#Override
public void onEvent(#Nullable QuerySnapshot value, #Nullable FirebaseFirestoreException error) {
messageArrayList.clear();
for (DocumentSnapshot snapshots : value.getDocuments())
{
Message message = snapshots.toObject(Message.class);
messageArrayList.add(message);
}
adapter.notifyDataSetChanged();
}
});
}
}
documents in Firebase Firestore are not stored in the order of there creation time, they are ordered by there id name. which in your case is a random ID generated by Firebase itself.
You have two options, the first one is to generate the documents IDs by yourself, by tracking the last ID number in that collection and incrementing it (1, 2, 3...etc), the second option (which I would recommend) is to combine your date and time fields into one fields by simply adding the timestamp values and call it something like dateTime for example, and then using the orderby('dateTime') method that Firebase provide while querying from the collection, for more info on how to use it check out the documentation here
Edit: As pointed out by #AlexMamo in the comments, apparently sequential IDs are bad practice in Firestore, so your only option is to add a timestamp value and use the orderby() method to arrange you messages.
On getting collection reference it is possible to apply orderBy method and then add a snapshot listener. Probably, Firebase stores the entities in different order rather than you expect and order by creation date should be declared explicitly.
firebaseFirestore.collection("Chats").document(senderroom)
.collection("Messages")
.orderBy("${dateField}")
.addSnapshotListener(...)

How to hide current user from FirebaseRecyclerAdapter of all users? [duplicate]

This question already has answers here:
Firebase: Query to exclude data based on a condition
(2 answers)
Closed 3 years ago.
Currently, it pulls in all users details and populates their image, name, and bio. I want it to hide the current user from the list of users and I don't know how to implement the code for it.
I have tried if/while statements to compare dataSnapshot to the current user but I don't know how to populate the users depending on this condition.
public class SearchFragment extends Fragment {
private RecyclerView usersList;
private DatabaseReference databaseReference;
private DatabaseReference userDatabase;
private DatabaseReference checkName;
private FirebaseAuth firebaseAuth;
private String currentUserID;
private View view;
public SearchFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
view = inflater.inflate(R.layout.fragment_search, container, false);
usersList = view.findViewById(R.id.search_users);
firebaseAuth = FirebaseAuth.getInstance();
currentUserID = firebaseAuth.getCurrentUser().getUid();
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
userDatabase = FirebaseDatabase.getInstance().getReference();
checkName = userDatabase.child("Users").child(currentUserID).child("name");
usersList.setHasFixedSize(true);
usersList.setLayoutManager(new LinearLayoutManager(getContext()));
return view;
}
#Override
public void onStart() {
super.onStart();
final FirebaseRecyclerOptions<Users> options = new FirebaseRecyclerOptions.Builder<Users>()
.setQuery(databaseReference, Users.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<Users, SearchFragment.UsersViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull SearchFragment.UsersViewHolder holder, int position, #NonNull final Users users) {
holder.setName(users.getName());
holder.setCity(users.getCity());
holder.setImage(users.getImage());
final String user_ID = getRef(position).getKey();
final String user_Name = users.getName();
final String user_Img = users.getImage();
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
CharSequence pickOption[] = new CharSequence[]{"View Profile", "Send Message"};
final AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Select an Option");
builder.setItems(pickOption, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
if (i == 0){
Intent otherProfileIntent = new Intent(getActivity(), OthersProfileActivity.class);
otherProfileIntent.putExtra("user_ID", user_ID);
otherProfileIntent.putExtra("user_Name", user_Name);
otherProfileIntent.putExtra("user_Img", user_Img);
startActivity(otherProfileIntent);
}
if (i == 1) {
Intent messageIntent = new Intent(getActivity(), MessageActivity.class);
messageIntent.putExtra("user_ID", user_ID);
messageIntent.putExtra("user_Name", user_Name);
messageIntent.putExtra("user_Img", user_Img);
startActivity(messageIntent);
}
}
});
builder.show();
}
});
}
#NonNull
#Override
public SearchFragment.UsersViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.users_layout, parent, false);
return new SearchFragment.UsersViewHolder(view);
}
};
usersList.setAdapter(adapter);
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
}
public static class UsersViewHolder extends RecyclerView.ViewHolder {
View mView;
public UsersViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void setName(String name) {
TextView userNameView = mView.findViewById(R.id.single_userName);
userNameView.setText(name);
}
public void setCity(String name) {
TextView userNameView = mView.findViewById(R.id.single_userStatus);
userNameView.setText(name);
}
public void setImage(String image) {
CircleImageView userImage = mView.findViewById(R.id.single_userImg);
if(!image.equals("default")) {
Picasso.get().load(image).into(userImage);
}
}
}
}
I am expecting the current user to be hidden from the list of all users in the RecyclerView. Thanks in advance!
You might consider modifying your databaseReference like the following.
databaseReference = FirebaseDatabase.getInstance().getReference().child("Users");
checkName = userDatabase.child("Users").child(currentUserID).child("name");
// This is your updated database reference
databaseReference = FirebaseDatabase.getInstance().getReference()
.child("Users").child(currentUserID);
Now while setting the options for your FirebaseRecyclerAdapter you might consider setting the query like the following.
final FirebaseRecyclerOptions<Users> options = new FirebaseRecyclerOptions.Builder<Users>()
.setQuery(databaseReference.equalTo(null), Users.class)
.build();
I have not tested this. However, please let me know if that works.

Unable to filter query with multiple clauses using Firebase Realtime Database

I'm using Firebase Realtime Database with Firebase UI, however i'm not being able to search with multiple clauses.
What i need is to take the Users that do not have an specific id. As i'm already filtering them by City i need to filter these ones with specific id.
I've been trying to solve it in many ways, however none of them has come to success.
This is my Database
I cant take and render the card with the user with that username.
public class SearchFragment extends android.support.v4.app.Fragment {
private EditText mSearchField;
private ImageButton mSearchBtn;
private RecyclerView mResultList;
private DatabaseReference mUserDatabase;
public static SearchFragment newInstance() { return new SearchFragment(); }
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_search, container, false);
mSearchField = view.findViewById(R.id.search_field);
mSearchBtn = view.findViewById(R.id.search_btn);
mResultList = view.findViewById(R.id.result_list);
mResultList.setHasFixedSize(true);
mResultList.setLayoutManager(new LinearLayoutManager(mResultList.getContext()));
mSearchBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String searchText = mSearchField.getText().toString();
firebaseUserSearch(searchText);
mSearchField.setText("");
}
});
mUserDatabase = FirebaseDatabase.getInstance().getReference("usuarios");
return view;
}
public void firebaseUserSearch(String searchText) {
Toast.makeText(getContext(), "Buscando usuários", Toast.LENGTH_LONG).show();
String searchTextLower = searchText.toLowerCase();
final Query firebaseSearchQuery = mUserDatabase.orderByChild("city").startAt(searchTextLower).endAt(searchTextLower + "\uf8ff");
firebaseSearchQuery.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
GenericTypeIndicator<Map<String, String>> genericTypeIndicator = new GenericTypeIndicator<Map<String, String>>() {};
Map<String, String> map = dataSnapshot.getValue(genericTypeIndicator );
String username = map.get("username").toString();
Log.d("oi", username);
Log.d("olar", UserDetails.username);
if(username != UserDetails.username) {
final FirebaseRecyclerOptions<User> options =
new FirebaseRecyclerOptions.Builder<User>()
.setQuery(firebaseSearchQuery, User.class)
.build();
bindAndBuildFirebaseUi(options);
}
}
public void bindAndBuildFirebaseUi(FirebaseRecyclerOptions options) {
final FirebaseRecyclerAdapter<User, UsersViewHolder> firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<User, UsersViewHolder>(options) {
#Override
public UsersViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new UsersViewHolder(v);
}
#Override
protected void onBindViewHolder(final UsersViewHolder holder, int position, final User model) {
holder.bind(model);
Log.d("SearchFragment", "Binded the model");
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserDetails.chatWithId = model.getUsername();
UserDetails.chatWith = model.getName();
startActivity(new Intent(getContext(), Chat.class));
}
});
}
};
firebaseRecyclerAdapter.startListening();
mResultList.setAdapter(firebaseRecyclerAdapter);
}
}
As you can see i even tried to filter them throught the database again, howeever, Firebase ui is taking the filter from options which is the first query filtering the users by city.
Does anyone have any idea how to take avoid rendering the users with an specific id???
And i also know that Firebase does not allow to use more than one orderBy.
The Firebase RTDB doesn't support multiple where clauses unfortunately. However, if you denormalize your data properly, you can use one query to link to another ref in the database and effectively filter data in that way. Take a look at the docs: https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md#using-firebaseui-with-indexed-data.
As a side note, you really shouldn't be using the RTDB to store actual data as it won't scale. It's designed for low latency real-time updates for multiplayer stuff or a ticketing app etc. Instead, I'd recommend looking into Firestore, especially if this is a new app.
Here's the hack I mentioned in my comment below:
public class MyAdapter extends FirebaseRecyclerAdapter {
private static final int TYPE_NORMAL = 0;
private static final int TYPE_HIDDEN = 1;
private final View mEmpty = new View(getContext());
public MyAdapter(#NonNull FirestoreRecyclerOptions options) {
super(options);
mEmpty.setVisibility(View.GONE);
}
#Override
public int getItemViewType(int position) {
if (getItem(position).username.equals(UserDetails.username)) {
return TYPE_HIDDEN;
} else {
return TYPE_NORMAL;
}
}
#Override
public UsersViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == TYPE_HIDDEN) {
return new UsersViewHolder(mEmpty);
}
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_layout, parent, false);
return new UsersViewHolder(v);
}
#Override
protected void onBindViewHolder(final UsersViewHolder holder, int position, final User model) {
if (getItemViewType(position) == TYPE_HIDDEN) return;
holder.bind(model);
Log.d("SearchFragment", "Binded the model");
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
UserDetails.chatWithId = model.getUsername();
UserDetails.chatWith = model.getName();
startActivity(new Intent(getContext(), Chat.class));
}
});
}
}

Android - Firebase - Send Users to Chat Room

Aim
Allowing the Users to access their selected Group Chat. Once the user clicks on the Group Chat name, they will be entered into that Group Chat.
Database Tree
As shown in the Database Tree, the Currently Signed In user will be shown a list of Group Chat names that have been created.
I have an Admin Account to create these Group Chats for the users.
The Android, Asia, and Europe group chats that are seen within the Database ARE NOT fixed variables. They are names. A newly Group Chat name could be "Earth".
Therefore there is no way of calling it by a variable other than calling it by the Node itself.
Screenshot of Application
List of Group Chats 2. Entering a Group Chat
Flow of Activities
GroupFragment ---> Chat Activity
GroupFragment <--- Chat Activity
Flow of Application
User--->LoginActivity--->UserActivity--->GroupFrag--->GroupChatActivity
At the (GroupFrag--->GroupChatActivity) The user must select a Group Chat name within the GroupFrag to enter the GroupChatActivity
The user must select a Group Chat name within the GroupFrag to enter the GroupChatActivity
Description
The users will be able to select a Group Chat name (from GroupFragment) and the app will bring the user into the Group Chat itself (into Chat Activity). The User will be able to go back to the GroupFragment and select another desired Group.
(Group Chat names are NOT FIXED -- They're not a node that can be called from)
Problem
I am unable to select the Group Chat names after it was prompt within the Fragment, which will then bring me to the Group Chat.
Group Fragment
#Override
public void onStart() {
super.onStart();
class GroupAdapter extends RecyclerView.Adapter<GroupAdapter.MyHolder> {
ArrayList<String> list;
public GroupAdapter(ArrayList<String> list) {
this.list = list;
}
#Override
public GroupAdapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_groups, parent, false);
return new MyHolder(view);
}
#Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.setText(list.get(position));
}
#Override
public int getItemCount() {
return list.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
public MyHolder(View itemView) {
super(itemView);
nameTextView = itemView.findViewById(R.id.groupChatNameTxt);
}
public void setText(String groupName) {
nameTextView.setText(groupName);
}
}
}
jGroupsDatabase.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
ArrayList<String> groupChatNames = new ArrayList<>();
for (DataSnapshot child : dataSnapshot.getChildren()) {
groupChatNames.add(child.getKey());
}
GroupAdapter adapter = new GroupAdapter(groupChatNames);
jGroupChatList.setAdapter(adapter);
//I'm not sure where to write a code for userID
//final String usersID = getRef(position).getKey();
// When the user clicks on one of the group chat names, he/she will be sent to the Chat Activity
jGroupChatList.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intentUserProfile = new Intent(getActivity(), ChatActivity.class);
intentUserProfile.putExtra("groupChatName",groupName);
intentUserProfile.putExtra("neighbourhood", neighbourhood);
intentUserProfile.putExtra("usersName", usersName);
intentUserProfile.putExtra("usersID", usersID);
startActivity(intentUserProfile);
}
});
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Chat Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
jGroupChatName = getIntent().getExtras().get("groupChatName").toString();
jUserID = getIntent().getExtras().get("usersID").toString();
jUserName = getIntent().getExtras().get("usersName").toString();
jUserNeighbourhood = getIntent().getExtras().get("neighbourhood").toString();
jChatRoot = FirebaseDatabase.getInstance().getReference().child(jGroupChatName);
jChatToolbar = (Toolbar) findViewById(R.id.allUSersToolBar);
setSupportActionBar(jChatToolbar);
getSupportActionBar().setTitle(jGroupChatName); // Show the name of the selected group name
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
Additional Comments
Online Tutorial
I have watched an Android Firebase Group Chat tutorial on youtube. The link is https://www.youtube.com/watch?v=wVCz1a3ogqk. But it does not provide some the features/ functions whic I am trying to implement.
Linked Question
Android - Firebase - Prompting Group Chat Names
Future Implementations
For future implementations, I would like to send and retrieve the messages and prompt it into the group chat for the users to view like a real group chat. But of course, I will leave that for another Question.
You can update your adapter and viewholder implementation as follows:
public class Adapter extends RecyclerView.Adapter<Adapter.MyHolder> {
Context context;
ArrayList<String> list;
public Adapter(Context context, ArrayList<String> list) {
this.context = context;
this.list = list;
}
#Override
public Adapter.MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_groups, parent, false);
MyHolder holder = new MyHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.setText(list.get(position));
}
#Override
public int getItemCount() {
return list.size();
}
class MyHolder extends RecyclerView.ViewHolder {
TextView nameTextView;
View.OnClickListener onClickListener = new View.OnClickListener() {
#Override
public void onClick(View view) {
String groupName = list.get(getAdapterPosition());
Intent intentUserProfile = new Intent(context, MainActivity.class);
intentUserProfile.putExtra("groupChatName", groupName);
// If fixed, you should pass these values to adapter's constructor
// intentUserProfile.putExtra("neighbourhood", neighbourhood);
// intentUserProfile.putExtra("usersName", usersName);
// intentUserProfile.putExtra("usersID", usersID);
context.startActivity(intentUserProfile);
}
};
public MyHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(onClickListener);
nameTextView = (TextView) itemView.findViewById(R.id.groupChatNameTxt);
}
public void setText(String groupName) {
nameTextView.setText(groupName);
}
}
}
You also have to update this line in your GroupFragment:
GroupAdapter adapter = new GroupAdapter(getActivity(), groupChatNames);
This is another solution that you can implement inside your fragment so that you can put extras in intent (actually modified from your former question):
#Override
public void onStart() {
super.onStart();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference groupChatsRef = rootRef.child("Group Chats");
FirebaseRecyclerAdapter<String, GroupChatViewHolder> chatAdapter = new FirebaseRecyclerAdapter<String, GroupChatViewHolder>(
String.class,
R.layout.layout_groups,
GroupChatViewHolder.class,
groupChatsRef) {
protected void populateViewHolder(GroupChatViewHolder viewHolder, String model, int position) {
final String groupChatName = this.getRef(position).getKey();
viewHolder.setName(groupChatName);
viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intentUserProfile = new Intent(getActivity(), ChatActivity.class);
intentUserProfile.putExtra("groupChatName", groupChatName);
intentUserProfile.putExtra("neighbourhood", neighbourhood);
intentUserProfile.putExtra("usersName", usersName);
intentUserProfile.putExtra("usersID", usersID);
startActivity(intentUserProfile);
}
});
}
};
jGroupChatList.setAdapter(chatAdapter);
}
Note that it handles your string-string group chat entries in your DB as key-value pairs.
public class group_name_list_adapter extends RecyclerView.Adapter<group_name_list_adapter.ViewHolder> {
private List< group_name_list> listItems;
private Context context;
OnItemClickListener onItemClickListener;
public group_name_list_adapter(List<group_name_list> listItems, Context context) {
this.listItems = listItems;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.group_name_list, parent, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
group_name_list listItem = listItems.get(position);
holder.txtTitle.setText(listItem.getTxtTitle());
holder.txtTitle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onItemClickListener.onGroupNameClick(position);
}
});
}
#Override
public int getItemCount() {
return listItems.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public TextView txtTitle;
public ViewHolder(View itemView) {
super(itemView);
txtTitle = (TextView) itemView.findViewById(R.id.txtTitle);
}
}
public void setOnItemClickListener(OnItemClickListener onItemClickListener){
this.onItemClickListener = onItemClickListener;
}
public interface OnItemClickListener{
void onGroupNameClick(int position);
}
}
public class group_name_list {
private String txtTitle;
public group_name_list(String txtTitle) {
this.txtTitle = txtTitle;
}
public String getTxtTitle() {
return txtTitle;
}
}
public class ChatActivity implements group_name_list_adapter.OnItemClickListener
private RecyclerView recyclerGroupName;
private group_name_list_adapter groupNameAdapter;
private List<group_name_list> group_name_List;
private List<String> groupNameKeyList; //This is optional – this is used if you wanted the group chats to have the same name instead of overwriting the groupchat when creating.
Inside your Firebase call:
group_name_List.removeAll(group_name_List t);
groupNameKeyList.removeAll(groupNameKeyList);
//Depending on your firebase reference. This could just be dataSnapshot.getChildren()
for (DataSnapshot child : dataSnapshot.child("Group Chats").getChildren()){
if (!child.getKey().equals(null)){
groupNameKeyList.add(child.getKey().toString()); //Again this is optional
}
group_name_list newGroupList = child.getValue();
);
groupNameList.add(newGroupList);
}
recyclerGroupName.setAdapter(groupNameAdapter);
gLayoutAttribute = new GridLayoutManager(getActivity(), 1);
recyclerGroupName = (RecyclerView) rootView.findViewById(R.id.recyclerGroupName);
recyclerGroupName.setHasFixedSize(true);
recyclerGroupName.setLayoutManager(new LinearLayoutManager(this.getContext()));
recyclerGroupName.setLayoutManager(gLayoutAttribute);
#Override
public void onAttributeClick(int position) {
Intent intentUserProfile = new Intent(getActivity(), ChatActivity.class);
intentUserProfile.putExtra("groupChatName",groupName);
intentUserProfile.putExtra("neighbourhood", neighbourhood);
intentUserProfile.putExtra("usersName", usersName);
intentUserProfile.putExtra("usersID", usersID);
intent.putExtra("name", groupList.get(position).toString());
//intent.putExtra("name", groupListKeyList.get(position).toString()); this is your optional key
startActivity(intentUserProfile);
}
Try according to this
Suppose you've created 5 user's in FirebaseDatabasewith different UID's
In this step you have to get all user's from Firebase and display it in RecyclerView
In Recyclerview's adapter class in onBindViewHolder' you have to do like add and remove` users from list which you generated at the time creating group.
In this step you've to search firebaseDatabase user's Uid which is currently logged in and if your UID is matched found in any Group then you need to get the Group-name .
Happy to help you

Categories

Resources