Hi I am developing a chat application using Firebase database.
below is the structure of my database for user on Firebase
The structure of my model classes for User currently is
public class User {
Credential credentials;
List<Conversation> conversationList;
}
public class Credential implements Parcelable {
private String name="";
private String email="";
private String profilePicLink="";
}
I am not getting what should be the structure of conversations list as per the structure on firebase db .
TIA.
Update the rules for your database to allow reads and writes from all users,
{
"rules": {
".read": "true",
".write": "true"
}
}
Reference:
https://firebase.google.com/docs/database/android/read-and-write
https://firebase.google.com/docs/database/rest/retrieve-data
Firebase stores its data as key-value pair rather than a list. As per your snapshot, a user has two main Hashmaps i.e. conversations and credentials. Therefore, you can create your models as:
public class User {
Hashmap<String, String> credentials;
Hashmap<String, Hashmap<String, String>> conversationList;
}
public class Credential implements Parcelable {
private String name="";
private String email="";
private String profilePicLink="";
public void setModel(Hashmap<String, String> data) {
//assign values to your model here
}
}
Related
Hi I would like to register the name and surname of the users in the database as an example using a model. The data is stored in the database, but does not send the names I use in the model as child names. Instead, it saves "a, b, c, d ..." What is the reason of this?
Created database:
"-LMqLmS09gGKjR-s9CML" : {
"a" : "Robin",
"b" : "Hood"
}
The database I want to create:
"-LMqLmS09gGKjR-s9CML" : {
"firstname" : "Robin",
"lastname" : "Hood"
}
User.java (Model):
public class User {
public String fistname;
public String lastnname;
public User(String fistname, String lastnname) {
this.fistname = fistname;
this.lastnname = lastnname;
}
public String getFistname() {
return fistname;
}
public void setFistname(String fistname) {
this.fistname = fistname;
}
public String getLastnname() {
return lastnname;
}
public void setLastnname(String lastnname) {
this.lastnname = lastnname;
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity {
String firstname="Robin";
String lastname="Hood";
private DatabaseReference mDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FirebaseApp.initializeApp(this);
mDatabase = FirebaseDatabase.getInstance().getReference();
String key = mDatabase.push().getKey();
User users = new User(firstname,lastname);
mDatabase.child(key).setValue(users);
}
}
I finally found the answer. It's because I used proguard for security. Proguard shuffles the code you type so that other people cannot see the code after creating the .APK. Firebase was automatically classified because it also confused the names of the child. I solved the problem by leaving the model classes out of the proguard.
Android Firebase stores custom object members with alphabet keys (e.g. "a", "b", "c") only when installed via a release apk
I have a class for users
public class User {
#SerializedName("username")
private String userName;
#SerializedName("email")
private String email;
#SerializedName("bags")
private List<Bag> bags;
.
.
.
And I have this data in my firebase DB
Before I added the "bags" items, the object was created fine, I'm using this method for retrieving the user by the uid:
public void retrieveUserByUid(String uid, FirebaseRetrieveUserListener listener){
Query userQuery = dbReference.child(FirebaseChild.users.name()).child(uid);
final FirebaseRetrieveUserListener dataListener = listener;
userQuery.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User user = dataSnapshot.getValue(User.class);
dataListener.retrieveUserByUid(user);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
As I said, this worked without the "bags" item, when I put it, the error I'm getting is this.
com.google.firebase.database.DatabaseException: Expected a List while deserializing, but got a class java.util.HashMap
This happens when I try to do this
User user = dataSnapshot.getValue(User.class);
I've searched a lot about how to retrieve a list, but all I find is retrieving a single list object, not a "mixed" object with "single data" and a list.
As you error says, while deserializing it was expected a HashMap and not a List. Because Firebase is a NoSQL database, everything in Firbease is structured as pairs of key and value. So every node in Firebase is a Map. In order to solve this, change the bags from List to HashMap and your problem will be solved.
You can also try this:
GenericTypeIndicator<List<YourClass>> t = new GenericTypeIndicator<List<Message>>() {};
List<YourClass> messages = snapshot.getValue(t);
Try this :
#SerializedName("bags")
private Map<String,Bag> bags;
I have a model class to store Firebase User information. Inside of the model class I have a HashMap to store all of the data inside. Once I have stored the data, the I push the Hashmap into the Firebase database. The values store fine, but I cannot access the values. Every time I try to access them, I get an error saying that I am attempting to invoke a virtual method on a null object reference.
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
// These two lines of code give the error.
User author = ChildSnapshot.child("profile").getValue(User.class);
String author_username = author.getUsername();
These give me the error. I am attempting to grab data from the child of the snapshot. Why is this giving me an error? Is there a better way to do this?
JSON Firebase snapshot:
Model class:
//TODO model class for the user. This way I can set the values for each user. I will be adding more values in the future.
public class User {
public HashMap<String, String> hashMap = new HashMap<String,String>();
public User() {
}
public User(String username) {
hashMap.put("username",username);
}
public String getUsername(){
return hashMap.get("username");
}
}
In case somebody else was struggling with this issue, I wanted to give an answer. Inside of my ChildEventListener, the profile is the key in this situation so when I use ChildSnapshot.child("profile").getValue(User.class) it returns a null value. Also, (I'm not quite sure why this is) the value of the username was stored in a different class called User_message which was used to store the message. so my updated code looks something like this:
mDatabase.child("users").child(mUserId).addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot ChildSnapshot, String s) {
User_message author = ChildSnapshot.getValue(User_message.class);
String author_username = author.getUsername();
I was facing the same problem and spent more than 5 hours. I added Default Constructor of the model and this solves my problem.
public class User {
public String email;
public String name;
public User() {
}
public User(String email, String name) {
this.email = email;
this.name = name;
}}
I hope this will help you. Thanks
I am new to Firebase and I am planning to switch from SQLite to Firebase.
I have 2 tables in SQLite.
First one is NAME OF REPOSITORIES. This will will be general for all users which is accessible to all the users of the application.
Second one is BOOKMARKS. This will be specific to a particular user . I know that there is no table structure in Firebase .
Question is, how can I structure this type of data in Firebase? I have tried understanding tree structure of Firebase, but didn't get help for this type of scenario.
To create two tables you have to create object of DatabaseReference for second table. Also you have to create second node.
public class MainActivity extends AppCompatActivity {
private DatabaseReference mFirebaseDatabase;
private FirebaseDatabase mFirebaseInstance;
//Create an object of DatabaseReference to create second table
private DatabaseReference mFirebaseDatabase1;
private String userId;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mFirebaseInstance = FirebaseDatabase.getInstance();
// get reference to 'RepositoryName' node
mFirebaseDatabase = mFirebaseInstance.getReference("RepositoryName");
// get reference to 'Bookmarks' node
mFirebaseDatabase1 = mFirebaseInstance.getReference("Bookmarks");
// Save / update the user
btnSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String name = inputName.getText().toString();
String email = inputEmail.getText().toString();
String password = inputPassword.getText().toString();
String confirmPassword = inputConfirmPassword.getText().toString();
// Check for already existed userId
if (TextUtils.isEmpty(userId)) {
createUser(name, email, password, confirmPassword);
}
}
});
}
/**
* Creating new user node under 'users'
*/
private void createUser(String name, String email, String password, String confirmPassword) {
// TODO
// In real apps this userId should be fetched
// by implementing firebase auth
if (TextUtils.isEmpty(userId)) {
/*userId store the unique key like KYNGnlMMIf3w11VukqD
in this key store usename and email as JSON format in firebase cloud database*/
// "mFirebaseDatabase" is for table1(i.e RepositoryName)
//userId = mFirebaseDatabase.push().getKey();
// "mFirebaseDatabase1" is for table2(i.e Bookmarks)
userId = mFirebaseDatabase1.push().getKey();
}
User user = new User(name, email, password, confirmPassword);
//insert data in firebase database RepositoryName
mFirebaseDatabase.child(userId).setValue(user);
//insert data in firebase database Bookmarks
mFirebaseDatabase1.child(userId).setValue(user);
}
}
Hope this helps you :)
Hello at the first you should try with understanding the basic concept of denormalizing data. You can check one of the blog post.
Again, for more information of stucturing data in detail is here.
You can start structuring data using these links again. You have to have denormalised structure to developer best experience in firebase.
Coming to you point, Two tables.
You need to create 2 nodes in firebase. First one is with NAME OF REPOSITORIES and BOOKMARKS. If you are having any relations for both the table create a new node with that relation lets say USERBOOKMARK and try adding reference to the node.
Taking reference from FireChat app I used FirebaseRecyclerAdapter in my app, it is working fine but I need to filter data which equals to specific user ID.
In populateView if I does that data is getting filtered but a blank recycler Item item is also getting created.
mFirebaseAdapter = new FirebaseRecyclerAdapter<Tags, TagsViewHolder>(
Tags.class,
R.layout.item_message,
TagsViewHolder.class,
mFirebaseDatabaseReference.child("tags")) {
#Override
protected void populateViewHolder(TagsViewHolder viewHolder, Tags tags, int position) {
mProgressBar.setVisibility(ProgressBar.INVISIBLE);
if((tags.getUserid()).equals(mFirebaseUser.getUid()))
viewHolder.tagTextView.setText(tags.getTagname());
}
};
Is there any way I can filter it before a view gets created?
my POJO class is:
public class Tags {
private String userid;
private String tagname;
private HashMap<String, Object> timestampCreated;
public Tags() {
}
public Tags(String userid, String tagname, HashMap<String, Object> timestampCreated) {
this.userid = userid;
this.tagname = tagname;
this.timestampCreated = timestampCreated;
}
public String getUserid() {
return userid;
}
public String getTagname() {
return tagname;
}
public HashMap<String, Object> getTimestampCreated() {
return timestampCreated;
}
}
Thank you!
Client-side filtering is an open feature request for FirebaseUI. See https://github.com/firebase/FirebaseUI-Android/issues/15.
Client-side filtering of data, means that the app first download data and then doesn't show it to the user. This is wasteful and most users of mobile apps will appreciate it if your app only downloads data that it shows to them.
The best ways to deal with displaying a subset of the data is to either model the data in a way so that you can directly access the subset of data that you want to display, or to use Firebase queries to limit the data that is retrieved.