So I am keeping track of a users taps on the screen and I have the user sign up with their email. However, when it comes to using the Firebase Database I am lost. I am not sure, how to save integers and then it load up when the user logs in. Can someone point me in the right direction?
I have watched a ton of videos and none show how to store information with an integer.
You don't need to do anything special for storing a integer or any other value in the Firebase DB.
You can use the uid of the current user and store the pojo/model directly into the the firebase DB.
For example, this can be your java model class:
public class Model {
private int tapCount=0;
public int getTapCount() {
return tapCount;
}
public void setTapCount(int tapCount) {
this.tapCount = tapCount;
}
}
When you want to insert the tap count into the Firebase db. You need to take the previous tap counts and add it with the current count update/create the Model object and set it into the Firebase db in the uid.
FirebaseDatabase.getInstance().getReference()
.child("user")
.child(FirebaseAuth.getInstance()
.getCurrentUser()
.getUid())
.setValue(model);
This code will insert the model under the user key and under user unique id.
Thanks,
Hope it helps.
Related
This question already has an answer here:
How to create auto incremented key in Firebase?
(1 answer)
Closed 4 years ago.
I want to append a String to my List on the Firebase Realtime Database.
(My code already works but there is a problem)
So the Database looks like this:
message:
0: "some string"
1: "another string"
2: "some string"
But I think the problem with this code would be, that if somebody reads the numbers of messages and then wants to write a message there would be a problem, when another user writes a message in the mean time (because the number of messages would change).
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference("message");
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
myRef.child(
String.valueOf(dataSnapshot.getChildrenCount())
).setValue("SOME STRING");
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Trying to use sequential numeric indexes (also often referred to as array indexes or auto-increment values) in a multi-user Firebase is an anti-pattern for a few reasons.
As you've already noted yourself, there's a chance of users overwriting each other's data. This is fixable however by using a transaction, which is the way to go if you need to property a value based on its existing value. The reference documentation for the JavaScript DatabaseReference.transaction method have this example that is pretty much what you need:
// Increment Ada's rank by 1.
var adaRankRef = firebase.database().ref('users/ada/rank');
adaRankRef.transaction(function(currentRank) {
// If users/ada/rank has never been set, currentRank will be `null`.
return currentRank + 1;
});
The syntax in Android is slightly more involved, but would work the same.
While a transaction works, this means that the application will only work when the user is connected to the server. When they're offline, the transaction will fail.
For these reasons Firebase apps typically use a different mechanism to generate their keys. The built-in push() method of the API generates a unique, always-incrementing key. While this key is not as readable as your sequential, numeric keys, they do address both of the above problems without the need for you to write more code for it yourself. With push() adding a message becomes as simple as:
final DatabaseReference myRef = database.getReference("message");
myRef.push().setValue("SOME STRING");
Note that this topic has been covered quite a bit already, so I recommend also checking out:
Best Practices: Arrays in Firebase
The 2^120 Ways to Ensure Unique Identifiers
How to create auto incremented key in Firebase?
Auto-increment a value in Firebase (has the transaction code for Android)
how do i auto increment a value in firebase
I have a node that I refresh every three days with some key-value pairs in my firebase realtime database. I want my app to get the new values only when I make changes in this node (so about every three days). I currently use this code to test :
mFirebaseDatabase.getReference().child("test").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long tsLong = System.currentTimeMillis();
Log.d("thatsdatasnapshot", "thatsdatasnapshot = " + tsLong.toString());
Log.d("thatsdatasnapshot", "thatsdatasnapshot = " + dataSnapshot.toString());
}
My issue is that my logs in this listener print very often even I don't change anything in my node, for example everytime I start the app. So I guess that all the values of my node are downloaded "very often", not only when I make change in my database. Am I wrong ? How to download the values of my node only when there is a change ? I thought it was what addValueEventListener() should do but I have a doubt when I see my logs printed so often.
Thank you,
Alex
The method addValueEventListener is only triggered when values in the realtime db change during your current run of the app, such as for every mRef.push() or mRef.child("someChild").setValue() method call in your app.
I had almost the same kind of problem with firebase realtime database and in the end, i resorted to creating an AsyncTask to update what you have to update during your app's runtime.
What you have to do is create an AsyncTask and make a REST call to your Firebase Database, and use it to update.
I am an experienced MySQL user but I am a newbie to json and firebase. I am trying to make an activity where a user is able to enter data and I save it to my db in firebase. I achieved my goal but here is the problem. When I save it(I think) I need to specify a child element with a string. Since this child element is static,every time a user enters a question it overwrites the existing one in my database. How can I fix this and how can I get the data back? Here is that part of my code.
private FirebaseAuth firebaseAuth;
private DatabaseReference databaseReference;
firebaseAuth=FirebaseAuth.getInstance();
if(firebaseAuth.getCurrentUser()==null){
finish();
startActivity(new Intent(this,LoginActivity.class));
}
FirebaseUser user=firebaseAuth.getCurrentUser();
databaseReference= FirebaseDatabase.getInstance().getReference();
Info info=new Info(question,answer,a,b,c,d);
databaseReference.child("secondQuestion").setValue(info);
//info is a new object which takes 6 string as an input.
// As you can see, I declare a string inside .child and it overwrites the data stored in it
As Andrew commented, it is indeed normal to add items to a (semi-chronological) list using push.
They're logically similar to a auto-increment field in MySQL, but have a (very) different format. See this post about why Firebase doesn't use the +1 style increments and this post on the push IDs.
If your questions already have a property that uniquely identifies them, you should probably use that as the key. So say that you're storing a list of Firebase Authentication users, you'd store each user under their uid. Or if the question text must be unique, you should probably store each question under (a hashed derivative of) their text.
I'm trying to migrate an app I had built which used Parse as its cloud backend. In my Parse backend database, I had a table which stored data as shown below:
Device ID | Contacts
xxxxx001 | "(800)-888-8888"
xxxxx002 | "(800)-888-8858"
xxxxx003 | "(800)-888-8868"
Over here, device ID is the android device ID and the Contacts are an ArrayList of strings which was generated through logic on the device. Basically, the user would select a contact (multiple in future iterations, hence it being an ArrayList, for testing I'm just keeping one item in the list) and that contact is saved for that DeviceID in the backend database. If the same DeviceID changes the contact, the contacts ArrayList in the database corresponding to its DeviceID would be replaced with the new ArrayList.
I'm trying to get something similar set up on Firebase, however right now it seems I only have a global variable on my databse which seems to get updated each time I press my button.
Here is my code for the button:
DatabaseReference mRootRef = FirebaseDatabase.getInstance().getReference();
DatabaseReference mContactsRef = mRootRef.child("contacts");
#Override
protected void onStart() {
super.onStart();
mButtonContactSave.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mContactsRef.setValue(contacts); //contacts is an arraylist with 1 item
}
});
}
Here is how it looks in Firebase after clicking the button 3 times:
Instead of updating the value, it seems to add another row(?) of to store the current phone number selected. How can I go about setting up a DeviceID->(Objects to be stored per device)
sort of setup?
You're looking for push(), which generates a unique ID for new items.
From the Firebase documentation on reading and writing lists of data:
// Create a new post reference with an auto-generated id
var newPostRef = postListRef.push();
newPostRef.set({
// ...
});
The new items will have complex-looking keys of the form -KTTHEScy82fpfNSCoYN. Read this article on why those are preferred over array indices and (if you're interested) this article that explains the format of these keys.
Consider a different data model
In general though you might want to consider a different data model. What you're storing is a collection of phone numbers. At first sight, storing those in an array-like list seems fine.
But typically you'll want these behaviors for this contact list:
each phone number can only be present once
you need to find whether a given phone number is already in the list
With your current structure you can only see if a number is already in the list by scanning all items in the list. Whenever that is the case, it is a good moment to consider using a set data structure instead.
In Firebase you'd model a set of phone numbers like this:
"contacts": {
"(800)-888-8858": true
"(800)-888-8868": true
"(800)-888-8888": true
}
While this structure initially looks less efficient, it is actually stored more efficiently than the array list in Firebase. And looking up whether an item exists is now a simple existence check instead of having to scan the array. And with this structure it is impossible to store the same number twice.
I've used the Real-Time Database with this setup:
->users
->uid
->name
->email
->other info
If I wanted to save the user data I would use my User class and then set the object in the database like this:
//assume variables have already been declared...
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
User user = new User(name, email, other values...);
mDBRef.child("users").child(mFirebaseUser.getUid()).setValue(user);
I tried it and it works fine.
But how can I retrieve these values from the database? For instance, once I set a User object as shown above, I may want to retrieve the user's email. I don't mean getting the email through the sign-in provider. I want the email through the real-time database. I've tried working this out for a while now but the documentation isn't helping much. All it shows is to setup listeners in order to wait for changes to the data. But I'm not waiting for changes, I don't want a listener. I want to directly get the values in the database by using the keys in the JSON tree. Is this possible via the real-time database? If so, how can it be done because either the documentation doesn't explain it or I'm just not understanding it. If not possible, am I supposed to be using the Storage database or something else? Thanks.
Firebase uses listeners to get data. That is just the nature of how it works. Although, you can use a single event listener (the equivalent of just grabbing the data once). It will fire immediately and get the data, and will not fire ever again. Here's a code example to get the current user's email:
//Get User ID
final String userId = getUid();
//Single event listener
mDatabase.child("users").child(userId).addListenerForSingleValueEvent(
new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// Get user value
User user = dataSnapshot.getValue(User.class);
//user.email now has your email value
}
});