I'm creating an Android app for the first time, I've got a simple Realtime Firebase Database with a couple of records in it. I have the following code;
public void onStart() {
super.onStart();
// Read from the database
databaseMatches.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for(DataSnapshot matchSnapshot : dataSnapshot.getChildren()) {
matches match = matchSnapshot.getValue(matches.class);
matchesList.add(match);
}
matchList adapter = new matchList (getActivity(), matchesList);
listViewMatch.setAdapter(adapter);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});
If I put a breakpoint on the databaseMatches.addValueEventListener(new ValueEventListener() { it shows me that the database connection has been set and is returning the correct object (In my view).
The challenge I have is the part after, the break points for public void onDataChange nor onCancelled ever get hit. I'm lost here and not sure what might be the next step as it appears to be connecting, but I am not able to retrieve records.
I'm doing this in a fragment instead of a activity. Any help is appreciated.
Detecting Connection State
it is useful for your app to know when it is online or offline. Firebase Realtime Database provides a special location at /.info/connected which is updated every time the Firebase Realtime Database client's connection state changes. Here is an example: If you are not sure.
https://firebase.google.com/docs/database/android/offline-capabilities#section-connection-state
DatabaseReference connectedRef =
FirebaseDatabase.getInstance().getReference(".info/connected");
connectedRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
boolean connected = snapshot.getValue(Boolean.class);
if (connected) {
System.out.println("connected");
} else {
System.out.println("not connected");
}
}
#Override
public void onCancelled(DatabaseError error) {
System.err.println("Listener was cancelled");
}
Firebase also loads and synchronizes data asynchronously
see Setting Singleton property value in Firebase Listener
Thanks.
There must have been some strange caching issue as the following morning when I ran the exact same code, no problem. And I've not had a problem since.
Related
I would to compare a value with a child of my Firebase Realtime Database but I don't know how to do. The structure of my database is:
This is the code that I wrote:
email = loadPreferences();
mAuth = FirebaseAuth.getInstance();
FirebaseDatabase database = FirebaseDatabase.getInstance();
final DatabaseReference myRef = database.getReference().child("users");
myRef.orderByChild("email").equalTo(email).addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
if(snapshot.getValue() != null) {
//loop through the keys
for(DataSnapshot datasnap : snapshot.getChildren()) {
if(!email.equalsIgnoreCase("")) {
myRef.child("users").child("email").child("address").setValue(getAddress());
}
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
I tried with debugger but when it arrived at "orderByChild()" it skip all and jumps to end. Anyone can help me? Thanks in advance
Data is loaded from Firebase asynchronously, because it needs to be loaded from the cloud. Instead of blocking the app for your users, Firebase instead loads the data in the background and lets your main code continue, which is what you see happening when you step through the code.
Instead of stepping through the code, place a breakpoint on the first line inside onDataChange, and allow the code to run. Then when the data is available, the debugger will hit your breakpoint and you can continue debugging.
You should also implement onCancelled, as you're now ignoring possible problems. At its minimum, this method should be:
public void onCancelled(#NonNull DatabaseError databaseError) {
throw databaseError.toException();
}
I am trying send my contacts to firebase one by one and checking if the user is present or not but due to the asynchronous behavior of firebase some information is showing twice.
I want to synchronize this method like this:
loop send one number to firebase, firebase response, save, and continue
for (int i=0 ; i< list.size();i++) {
Check_Contact(list.get(i));
}
public void Check_Contact(String number)
{
DatabaseReference myRef = database.getReference("user").child(number);
myRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() == null) {
}
else {
UserProfile row = dataSnapshot.getValue(UserProfile.class);
ls.add(row);
Adapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Can somebody tell me how to synchronize this method?
Firebase Structure
output coming
It is not the firebase async behaviour. You may have duplicate contents in your database. Please check ur database and update a screenshot of your database in your question.
It will be more helpful to understand your question.
I'm making an app and I've run into a problem with Firebase's Database and Authentication services.
After a while, while I am authenticated (using Firebase Auth) and using my app, my database ValueEventListeners don't seem to be called, even though there is data in the database.
How I'm adding my listeners:
FirebaseDatabase
.getInstance()
.getReference()
.child("my_child")
.addValueEventListener(new ValueEventListener()
{
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
Log.d("App", "onDataChange");
}
#Override
public void onCancelled(DatabaseError databaseError)
{
}
});
Stuff I've tried:
Checking the database rules (after a relog reading is fine - but simulated reads pass even while authenticated & unauthenticated)
keepSynced(true) on the DatabaseReferences
Adding the listeners in the Activity's onCreate instead of the Application's onCreate
Adding/removing/updating data in the database to trigger a sync
Rebooting
Any help would be much appreciated.
So, apparently the issue was that an API called "Token Service" was not enabled in my Google APIs dashboard.
Thanks to a helpful email from Firebase Support (thanks guys!), I've turned on debug logging by calling FirebaseDatabase.getInstance().setLogLevel(Logger.Level.DEBUG);
Lo and behold: D/PersistentConnection: pc_0 - Error fetching token: An internal error has occurred. [ �Token Service API has not been used in project <project-id> before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/securetoken.googleapis.com/overview?project=<project-id> then retry.
So by enabling the API, it seems to have fixed the error!
Create a reference to your child database, create a custom Chat class as per your requirement( essentially what you see in your firebase ).
addChildEventListener should give you all the changes happening with your my_child. Hope this helps you.
mFirebaseRef = new Firebase("https://yourapp.firebaseio.com/").child("my_child");
/**
* Firebase - Receives message
*/
mFirebaseRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
if (dataSnapshot != null && dataSnapshot.getValue() != null) {
try{
Chat model = dataSnapshot.getValue(Chat.class);
mChats.add(model);
mRecyclerView.scrollToPosition(mChats.size() - 1);
mAdapter.notifyItemInserted(mChats.size() - 1);
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Following situation:
User not registered, I save data while offline (Firebase setOffline())
Cannot read the local data (populate listview etc) - the ValueEventListener and ChildEventListener dont fire
I set setOnline() on Firebase instance
Data is synced with web and displayed (listeners fire)
I set setOffline() again.
I save local data and read local data, works (listeners fire)
Question:
How to read local data stored BEFORE going online?
Scenario is: User uses the android app offline and decides later to register
Scenario 1:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
FirebaseDatabase.getInstance().goOffline(); // <--------NOTE THIS
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("users").child(App.get().getUid()).child("items").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// THIS IS NOT FIRING
}
#Override
public void onCancelled(DatabaseError databaseError) {
...
}
});
After Scenario 1 I change code to this and run:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
FirebaseDatabase.getInstance().goOnline(); // <--------NOTE THIS
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("users").child(App.get().getUid()).child("items").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// THIS IS FIRING. ALL GOOD
}
#Override
public void onCancelled(DatabaseError databaseError) {
...
}
});
After this I change code to following and it works
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
FirebaseDatabase.getInstance().goOffline(); // <--------NOTE THIS
DatabaseReference mDatabase = FirebaseDatabase.getInstance().getReference();
mDatabase.child("users").child(App.get().getUid()).child("items").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// THIS IS FIRING. ALL GOOD
}
#Override
public void onCancelled(DatabaseError databaseError) {
...
}
});
I added 3 segments (code blocks).
I execute first block - does not work
Second block - works
Third block - works
Here is a gist with the code.
Problem is that first block does not work before being online with setOnline()
Since you force the client to go offline in scenario 1 before it has a chance to synchronize any data, I indeed expect it to not fire onDataChange() in that scenario. In the 3rd fragment it will fire, because it has had a chance to synchronize data to the local cache.
But why are you explicitly trying to manage online/offline state? By doing this you're digging a hole that you may find it hard to get out of.
If you want to avoid having the user sign-in, you can start off with Anonymous Authentication and then upgrade that to a email/password or social account later.
Just keep in mind that starting offline and only enabling synchronizing later is not an ideal way of working with the Firebase Database, which is primarily an online database that continues working offline.
I have been looking for a way to get one child object's data in Android Firebase.
I have found things like Firebase retrieve child Android. All the solutions are suggesting using a "ChildEventListener", however I need to get this data at this moment, not when it is moved, deleted, updated, etcetera.
My data is kept in https://.firebaseio.com/users//creation as a string. I figure there must be some simple way to access that without needing to do too much, because if I copy the exact URL to my browser, I can see the: 'creation: "2015/05/31 21:33:55"' right there in my "Firebase Forge Dashboard".
How can I access this without a listener?
Firebase listeners fire for both the initial data and any changes.
If you're looking to synchronize the data in a collection, use ChildEventListener. If you're looking to synchronize a single object, use ValueEventListener. Note that in both cases you're not "getting" the data. You're synchronizing it, which means that the callback may be invoked multiple times: for the initial data and whenever the data gets updated.
This is covered in Firebase's quickstart guide for Android. The relevant code and quote:
FirebaseRef.child("message").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
System.out.println(snapshot.getValue()); //prints "Do you have data? You'll love Firebase."
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
In the example above, the value event will fire once for the initial state of the data, and then again every time the value of that data changes.
Please spend a few moments to go through that quick start. It shouldn't take more than 15 minutes and it will save you from a lot of head scratching and questions. The Firebase Android Guide is probably a good next destination, for this question specifically: https://firebase.google.com/docs/database/android/read-and-write
You don't directly read a value. You can set it with .setValue(), but there is no .getValue() on the reference object.
You have to use a listener. If you just want to read the value once, you use ref.addListenerForSingleValueEvent().
Example:
Firebase ref = new Firebase("YOUR-URL-HERE/PATH/TO/YOUR/STUFF");
ref.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String value = (String) dataSnapshot.getValue();
// do your stuff here with value
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});
Source: https://www.firebase.com/docs/android/guide/retrieving-data.html#section-reading-once
just fetch specific node data and its working perfect for me
mFirebaseInstance.getReference("yourNodeName").getRef().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot postSnapshot : dataSnapshot.getChildren()) {
Log.e(TAG, "======="+postSnapshot.child("email").getValue());
Log.e(TAG, "======="+postSnapshot.child("name").getValue());
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.e(TAG, "Failed to read app title value.", error.toException());
}
});
I store my data this way:
accountsTable ->
key1 -> account1
key2 -> account2
in order to get object data:
accountsDb = mDatabase.child("accountsTable");
accountsDb.child("some key").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
try{
Account account = snapshot.getChildren().iterator().next()
.getValue(Account.class);
} catch (Throwable e) {
MyLogger.error(this, "onCreate eror", e);
}
}
#Override public void onCancelled(DatabaseError error) { }
});