Firebase Real Time Database confusion - android

I am trying to create a real time database with firebase, and my information isn't being stored how it should be. The JSON data is formatted as follows:
How do I get rid of the multiple instances of djProfile? And what does that random string of letters and numbers mean in that hierarchical tree?
Here is my android classes that Im using to try and retrieve this information and store it in my firebase recyclerview:
DjProfile class:
public class DjProfile
{
String djName, uniqueID;
public DjProfile(){}
public DjProfile(String djName, String uniqueID)
{
this.djName = djName;
this.uniqueID = uniqueID;
}
public String getDjName() { return djName; }
public String getUniqueID() {return uniqueID; }
}
RecyclerView information:
RecyclerView recyclerView = findViewById(R.id.dj_result_recycler);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("djProfile");
FirebaseRecyclerOptions<DjProfile> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<DjProfile>()
.setQuery(query, DjProfile.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<DjProfile, ResultsViewHolder>(firebaseRecyclerOptions)
{
#NonNull
#Override
public ResultsViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.searchitem_list, viewGroup, false);
return new ResultsViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull ResultsViewHolder holder, int position, #NonNull DjProfile model) {
holder.setDjProfile(model);
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
#Override
protected void onStart()
{
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
protected void onStop()
{
super.onStop();
if(firebaseRecyclerAdapter != null)
{
firebaseRecyclerAdapter.stopListening();
}
}
public static class ResultsViewHolder extends RecyclerView.ViewHolder
{
private TextView djNameView;
public ResultsViewHolder(View itemView)
{
super(itemView);
djNameView = itemView.findViewById(R.id.result_dj);
}
void setDjProfile(DjProfile profile)
{
String djName = profile.getDjName();
djNameView.setText(djName);
}
}
How can I retrieve just the name inside that djProfile? What am I missing?
Any feedback is greatly appreciated!

what does that random string of letters and numbers mean in that hierarchical tree?
The key starting with -Lar is created each time you call push() on a reference. It's Firebase's equivalent of an array index. To learn more about them, see The 2^120 Ways to Ensure Unique Identifiers and Best Practices: Arrays in Firebase.

Related

Can't retrieve data from cloud firestore firebase

I send data from the activity to the cloud firestore and I retrieve it in the second activity in recycler view.
but the data doesn't appear in the second activity.
I used FirestoreRecyclerAdapter and FirestoreOptions.
This is the activity in which I retrieve the data.
public class MyServicesActivity extends AppCompatActivity {
private FirestoreRecyclerAdapter adapter;
private RecyclerView recyclerView;
private FirebaseFirestore db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_services);
db = FirebaseFirestore.getInstance();
Query query = db.collection("Services Requested");
recyclerView = findViewById(R.id.rv_my_services);
FirestoreRecyclerOptions<ServiceModel> response = new FirestoreRecyclerOptions
.Builder<ServiceModel>()
.setQuery(query, ServiceModel.class)
.build();
adapter = new FirestoreRecyclerAdapter<ServiceModel, ServiceHolder>(response) {
#NonNull
#Override
public ServiceHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.service_design, parent, false);
return new ServiceHolder(v);
}
#SuppressLint("SetTextI18n")
#Override
protected void onBindViewHolder(#NonNull ServiceHolder holder, int position, #NonNull ServiceModel model) {
holder.serviceImage.setImageResource(model.getServiceImage());
Log.d("DATA", "data isn't null" + position);
holder.serviceName.setText(model.getServiceName());
holder.servicePrice.setText(model.getPrice() + "" + " L.E");
}
};
recyclerView.setAdapter(adapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
public class ServiceHolder extends RecyclerView.ViewHolder {
private ImageView serviceImage;
private TextView serviceName, servicePrice;
public ServiceHolder(#NonNull View itemView) {
super(itemView);
serviceImage = itemView.findViewById(R.id.polish_img);
serviceName = itemView.findViewById(R.id.polish_txt);
servicePrice = itemView.findViewById(R.id.price_txt);
}
}
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
adapter.startListening();
}
}
This is the class model for retrieve data from cloud firestore
public class ServiceModel {
private String serviceName;
private int price;
private int serviceImage;
public ServiceModel(){}
public ServiceModel(String serviceName, int price, int serviceImage) {
this.serviceName = serviceName;
this.price = price;
this.serviceImage = serviceImage;
}
public void setServiceName(String serviceName) {
this.serviceName = serviceName;
}
public void setPrice(int price) {
this.price = price;
}
public void setServiceImage(int serviceImage) {
this.serviceImage = serviceImage;
}
public String getServiceName() {
return serviceName;
}
public int getPrice() {
return price;
}
public int getServiceImage() {
return serviceImage;
}
}
I see in your screenshot, that the name of the properties in the database are stored using whitespace between the words, and each word is starting with a capital letter, while in your class, there is no whitespace and the first word starts with a lower-case and the second with a capital letter. When you are using a public getter called getServiceName(), Firebase is looking in the database after a property called serviceName, which actually does not exist.
To solve this, you either change the properties in your database to match the one in the class, remove the actual data, and add a fresh one, or you can use an annotation called PropertyName in front of the getter, to match the actual naming.

How to display multiple users' image using Firebase storage on RecyclerView

Good day everyone, I am having a bit of a struggle trying to grasp the idea on how to retrieve data from my Firebase storage to display it to my RecyclerView. The way my application is being set up, each user is able to set their own user profile picture. So the way I store the picture to cater for every user is by naming the files according to their UID. See below:
Here is my Firestore
Now I am stumped as to how I am going to display it on my RecyclerView. Currently, my RecyclerView can display the user's FullName, Email and Score like shown below:
Here's are the code that I am currently working with right now:
UserModel
public class UserModel {
private String FullName;
private String Email;
private long Score;
public UserModel() {
}
public UserModel(String fullName, String email, long score) {
this.FullName = fullName;
this.Email = email;
this.Score = score;
}
public String getFullName() {
return FullName;
}
public void setFullName(String fullName) {
FullName = fullName;
}
public String getEmail() {
return Email;
}
public void setEmail(String email) {
Email = email;
}
public long getScore() {
return Score;
}
public void setScore(long score) {
Score = score;
}
UserAdapter
public class UserAdapter extends FirestoreRecyclerAdapter<UserModel,
UserAdapter.UserViewHolder> {
public UserAdapter(#NonNull FirestoreRecyclerOptions<UserModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull UserAdapter.UserViewHolder holder, int position, #NonNull UserModel model) {
holder.username.setText(model.getFullName());
holder.email.setText(model.getEmail());
holder.score.setText(model.getScore()+"");
}
#NonNull
#Override
public UserAdapter.UserViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_leaderboard_single, parent, false);
return new UserViewHolder(view);
}
public class UserViewHolder extends RecyclerView.ViewHolder {
CircleImageView userImage;
TextView username;
TextView email;
TextView score;
public UserViewHolder(#NonNull View itemView) {
super(itemView);
userImage = itemView.findViewById(R.id.list_image);
username = itemView.findViewById(R.id.list_username);
email = itemView.findViewById(R.id.list_email);
score = itemView.findViewById(R.id.list_score);
}
}
The Main Activity
public class Leaderboard extends Fragment{
private RecyclerView leaderboard_recycler;
private FirestoreRecyclerAdapter adapter;
private StorageReference storageReference;
FirebaseFirestore fStore;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_leaderboard, container, false);
leaderboard_recycler = view.findViewById(R.id.leaderboard_list);
setUpRecyclerView();
return view;
}
#Override
public void onStop() {
super.onStop();
if(adapter != null)
adapter.stopListening();
}
#Override
public void onStart() {
super.onStart();
if(adapter != null)
adapter.startListening();
}
private void setUpRecyclerView() {
fStore = FirebaseFirestore.getInstance();
//Query
Query query = fStore.collection("users")
.orderBy("Score", Query.Direction.DESCENDING);
//RecyclerOptions
FirestoreRecyclerOptions<UserModel> options = new FirestoreRecyclerOptions.Builder<UserModel>()
.setQuery(query, UserModel.class)
.build();
adapter = new UserAdapter(options);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
leaderboard_recycler.setLayoutManager(linearLayoutManager);
leaderboard_recycler.setAdapter(adapter);
leaderboard_recycler.invalidate();
}
}
I would be eternally grateful if someone can point me to the right direction on how to handle this situation. Thank you.
Your user model class should contain a property called "profilePictureUrl", which is a String type variable for storing the image url.
You should make a screen (Activity or Fragment) for user to upload their pictures to the Firebase Storage, and Firebase Storage will return that file url, just save/update it to your user object.
For displaying the images, use the modern image loading library Glide.
Firebase Storage tutorial: https://youtu.be/r4HgdJKM5ko
Glide tutorial: https://youtu.be/eiP-vnSM0OM
My Chat app demo: https://youtu.be/iTXCn3NVqDM

How to display Firestore timestamp(Date and Time) in a RecyclerView

I'm building a Bank app and want to show history for transactions on the account, When I save the time to Firestore its format as a timestamp, but when I try to display it in my RecyclerView its just seconds and nanoseconds.
How can I show the date and time?
My recyclerView method:
private void setUpRecyclerView() {
String userId = FirebaseAuth.getInstance().getCurrentUser().getUid();
CollectionReference accountTransRef = db.collection(userId).document("accounts")
.collection("accounts").document(accountID).collection("transactions");
Query query = accountTransRef.orderBy("tTimestamp",Query.Direction.DESCENDING);
FirestoreRecyclerOptions<AccountTransactionModel> options = new FirestoreRecyclerOptions.Builder<AccountTransactionModel>()
.setQuery(query, AccountTransactionModel.class)
.build();
adapter = new AccountTransferAdapter(options);
RecyclerView recyclerView = findViewById(R.id.rwTransactionList);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
My Model for Transactions
public class AccountTransactionModel {
private String tType,tAccountToId, tDocumentId;
private Timestamp tTimestamp;
private double tAmount;
public AccountTransactionModel() {
}
public AccountTransactionModel(String tType, String tAccountToId, String tDocumentId, Timestamp tTimestamp, double tAmount) {
this.tType = tType;
this.tAccountToId = tAccountToId;
this.tDocumentId = tDocumentId;
this.tTimestamp = tTimestamp;
this.tAmount = tAmount;
}
public String gettType() {
return tType;
}
public String gettAccountToId() {
return tAccountToId;
}
#Exclude
public String gettDocumentId() {
return tDocumentId;
}
public void settDocumentId(String tDocumentId) {
this.tDocumentId = tDocumentId;
}
public Timestamp gettTimestamp() {
return tTimestamp;
}
public double gettAmount() {
return tAmount;
}
}
My adapter
public class AccountTransferAdapter extends FirestoreRecyclerAdapter<AccountTransactionModel, AccountTransferAdapter.TransferHolder > {
public AccountTransferAdapter(#NonNull FirestoreRecyclerOptions<AccountTransactionModel> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull TransferHolder holder, int position, #NonNull AccountTransactionModel model) {
holder.tvTransListAmount.setText(Double.toString(model.gettAmount()));
holder.tvTransListType.setText(model.gettType());
holder.tvTransListTime.setText(model.gettTimestamp().toString());
}
#NonNull
#Override
public TransferHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.transactions_list,viewGroup,false);
return new TransferHolder(v);
}
class TransferHolder extends RecyclerView.ViewHolder{
TextView tvTransListAmount;
TextView tvTransListTime;
TextView tvTransListType;
public TransferHolder(#NonNull View itemView) {
super(itemView);
tvTransListAmount = itemView.findViewById(R.id.trans_list_amount);
tvTransListTime = itemView.findViewById(R.id.trans_list_time);
tvTransListType = itemView.findViewById(R.id.trans_list_type);
//tvAccName = itemView.findViewById(R.id.tvAccountName);
//tvAccBalance = itemView.findViewById(R.id.tvAccountBalance);
}
}
}
What is displayed in my View,App and Firestore:
Timestamp(seconds=1558437203,nanoseconds=72000000)
If Timestamp is firebase package, then you can go with Timestamp#toDate() function
model.gettTimestamp().toDate().toString() which should give you whole date
Change this:
holder.tvTransListTime.setText(model.gettTimestamp().toString());
into this:
holder.tvTransListTime.setText(model.gettTimestamp().toDate());
From the docs:
public Date toDate ()
Returns a new Date corresponding to this timestamp.

Unable to get child of Current User Id for RecyclerView

I want to set RecyclerView with Child of Current User Id by using getCurrentUser().getUid().The data structure you can see in image below,
In image above, SQyOq80egYehjqx4sgiyeNcW8P02 is current userId and I want to get all child of those id and show in RecyclerView. In above image, the child is wed5qPTCdcQVzVlRcBrMo1NX43v1 and their value is Sep 29, 2018. My question is how to get those childern values separately and show in RecyclerView. As an example, I wrote code for Date (the value of current userId), which gives fatal error. I know error in Model class which I am unable to understand.
Note: this line gives error. Log.d("sdfsdfdgfdfsdfd", blogPost.getDate());
Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
RecyclerView recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
String uid = FirebaseAuth.getInstance().getCurrentUser().getUid();
DatabaseReference rootRef = FirebaseDatabase.getInstance().getReference();
Query query = rootRef.child("Friends").child(uid);
FirebaseRecyclerOptions<BlogPost> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<BlogPost>()
.setQuery(query, BlogPost.class)
.build();
firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<BlogPost, BlogPostHolder>(firebaseRecyclerOptions) {
#Override
protected void onBindViewHolder(#NonNull BlogPostHolder blogPostHolder, int position, #NonNull BlogPost blogPost) {
Log.d("sdfsdfdgfdfsdfd", blogPost.getDate());
blogPostHolder.setBlogPost(blogPost);
}
#Override
public BlogPostHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new BlogPostHolder(view);
}
};
recyclerView.setAdapter(firebaseRecyclerAdapter);
}
#Override
protected void onStart() {
super.onStart();
firebaseRecyclerAdapter.startListening();
}
#Override
protected void onStop() {
super.onStop();
if (firebaseRecyclerAdapter!= null) {
firebaseRecyclerAdapter.stopListening();
}
}
private class BlogPostHolder extends RecyclerView.ViewHolder {
private TextView userDateTextView;
BlogPostHolder(View itemView) {
super(itemView);
userDateTextView = itemView.findViewById(R.id.user_date);
}
void setBlogPost(BlogPost blogPost) {
String date = blogPost.getDate();
userDateTextView.setText(date);
}
}
}
Model:
public class BlogPost {
public String date;
public BlogPost() {}
public BlogPost(String date) {
this.date = date;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
}
change child key in firebase to be date
The wed5qPTCdcQVzVlRcBrMo1NX43v1 in your JSON seems to be dynamic, meaning that each user has a different key. The Firebase client has no way to parse that information into your BlogPost class, which only has static properties.
This means you'll have to provide your own SnapshotParser class to convert the DataSnapshot into the BlogPost object. Based on the FirebaseUI documentation that should look something like this:
FirebaseRecyclerOptions<BlogPost> firebaseRecyclerOptions = new FirebaseRecyclerOptions.Builder<BlogPost>()
.setQuery(query, , new SnapshotParser<Chat>() {
#NonNull
#Override
public BlogPost parseSnapshot(#NonNull DataSnapshot snapshot) {
// first let Firebase read any static properties
BlogPost post = snapshot.getValue(BlogPost.class);
// then do the parsing of the dynamic properties ourselves
for (DataSnapshot friendSnapshot: snapshot.getChildren()) {
String friendUID = friendSnapshot.getKey();
String friendDate = friendSnapshot.getValue(String.class);
post.setDate(friendDate);
}
return post;
}
}).build();
The above code is invoked by FirebaseUI for each new snapshot it gets from the database. It first calls snapshot.getValue(BlogPost.class) to convert the static parts of the JSON into a post, and then parses the friends itself. For now it sets any value it finds to the date property of the post. You may need to modify that to fit your exact use-case.

Android: reading a value from a child with FirebaseUI

I am using FirebaseUI to get some values from my real-time database to Firebase RecyclerView. So.. my data looks like that:
users:
userid:
info:
Name:Muhammad
I don't know how to get the value of Name which means what exactly should I do in the Users class? Here is my code (I think that the problem is in class user, I just don't know how to access child info)
public class User {
private String name;
private String email;
private String state;
private String image;
private String thumbnail;
public User(String name, String state, String image) {
this.name = name;
this.state = state;
this.image = image;
}
public User() {
}
public String getName() {
return name;
}
public String getState() {
return state;
}
public String getImage() {
return image;
}
}
my Main Activity
myDB refer to and on start method (updated after SUPERCILEX comment )
mDb = FirebaseDatabase.getInstance().getReference().child(App_Constants.USERS_COLUMN);
#Override
protected void onStart() {
super.onStart();
Query query = mDb;
FirebaseRecyclerOptions<User> options = new FirebaseRecyclerOptions.Builder<User>()
.setQuery(query, new SnapshotParser<User>() {
#NonNull
#Override
public User parseSnapshot(#NonNull DataSnapshot snapshot) {
String Name = snapshot.child(App_Constants.INFO_COLUMN).child(App_Constants.NAME_COLUMN).getValue().toString();
String State = snapshot.child(App_Constants.INFO_COLUMN).child(App_Constants.STATE_COLUMN).getValue().toString();
String Image = snapshot.child(App_Constants.INFO_COLUMN).child(App_Constants.IMAGE_COLUMN).getValue().toString();
User user = new User(Name,State,Image);
return user;
}
}).build();
FirebaseRecyclerAdapter<User,Users_ViewHolder> adapter = new FirebaseRecyclerAdapter<User, Users_ViewHolder>(options) {
#NonNull
#Override
public Users_ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.single_user,parent,false);
return new Users_ViewHolder(view);
}
#Override
protected void onBindViewHolder(#NonNull Users_ViewHolder holder, int position, #NonNull User model) {
holder.Set_Name(model.getName());
holder.Set_Image(model.getImage());
holder.Set_State(model.getState());
}
};
mUsers.setAdapter(adapter);
}
my ViewHolder
public class Users_ViewHolder extends RecyclerView.ViewHolder{
View mView;
public Users_ViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
public void Set_Name(String Name)
{
TextView mName = mView.findViewById(R.id.tv_single_user_name);
mName.setText(Name);
}
public void Set_Image(String url)
{
CircleImageView mImage = mView.findViewById(R.id.iv_single_user);
Picasso.get().load(url).placeholder(R.drawable.profile).into(mImage);
}
public void Set_State(String State)
{
TextView mState = mView.findViewById(R.id.tv_single_user_state);
mState.setText(State);
}
}
thanks
I believe it'll come in as a Map<String, Object> on the field info. However, you can always use a custom SnapshotParser to build your model to your liking: https://github.com/firebase/FirebaseUI-Android/blob/master/database/README.md#using-the-firebaserecycleradapter.
Some Advices :would you mind changing the set methods names?
from Set_State to setState,I too had similar problems please respect Java naming conventions
Also add the set methods in your custom model
Second:
FirebaseRecyclerOptions<User> options =
new FirebaseRecyclerOptions.Builder<User>()
.setQuery(query, User.class)
.build();
Start Listening:
#Override
protected void onStart() {
super.onStart();
adapter.startListening();
}
stopListening() call removes the event listener and all data in the adapter
#Override
protected void onStop() {
super.onStop();
adapter.stopListening();
}
Here you have a very good explained example

Categories

Resources