Reading data from firebase for android app [duplicate] - java

This question already has answers here:
Is it possible to read Firebase data without attaching any listeners?
(2 answers)
Closed 7 years ago.
I have been trying to get to understand how Firebase works with Android apps. I'm trying to read data from the database. I want to get all the child nodes and their corresponding key names of a particular Node. It seems like I can only read data once an event is triggered like a new child added or some value updated. What i want i to read data out without any event happening. Is there some way to this??
Bellow is the code i use in reading!
ref0 = myFirebaseRef.child("Users");
ref0.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot data : dataSnapshot.getChildren()){
System.out.print(String.valueOf(data.getKey())+", ");
}
}
#Override
public void onCancelled(FirebaseError firebaseError) {
}
});

thanks for the help! My code is actually correct! Just that for some strange reason the System.out.print won't display nothing.. I used Logs and voila!! it displayed the data.. I think Firebase should have named that method something else rather than onDataChange!!!! As it does the job but has a misleading convention. Thanks

Related

Can I order firebase addValueEventListeners so that they execute in a specific order? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
Hi I am working on a chat app in Java on Android Studio and trying to read data from firebase Realtime database which is structured like so
{
"Chats":{
"<chatID>":{
"<title>",
"<lastmessage>"
"<timestamp>"
"Users":{
"<user1ID>",
"<user2ID>"
}
}
},
"Users":{
"<userID>":{
"<name>",
"<email>",
"Contacts":{
"<contactID>",
},
"Chats":{
"<chatID>"
}
}
}
}
Currently I have 3 separate event listeners that add read data into a 2D array
ArrayList<ArrayList<String>> chatsDetails; //[("chatID","timestamp",userUID","userName","userEmail"),...]
The code is quite long but the titles of the event listeners (shortest code necessary to reproduce the problem) are like so
/*Listener 1- populate ArrayList with chat ID from Firebase database*/
databaseReference.child("users").child(mAuth.getCurrentUser().getUid()).child("chats").addValueEventListener(new ValueEventListener() {
});
/*Listener 2- populate 2d ArrayList with users uid and timestamp from Firebase database*/
databaseReference.child("chats").addValueEventListener(new ValueEventListener() {
//requires the chat id from listener 1
});
/*Listener 2- whenever values under users changes, update user email and name in 2D array*/
databaseReference.child("users").addValueEventListener(new ValueEventListener() {
//requires the user uid from listener 2
});
Specific problem:
The issue is when I do a Logd to the console, I realise that the listeners do not run in the order I require them to. This results in the name and email of the users not being retrieved and stored into the ArrayList.
Desired Behavior:
I want to know if there is any way to make the event listener go one after the other (So the log console should display Listener 1,2,3 executed in that order
I have tried to look for OnCompleteListeners but couldn't find any for this, and I tried nesting addValueEventListeners which didn't work. The issue is that when a new is added to the database it triggers all 3 listeners at the same time, so I'm not sure how to make them work in order. Any guidance would be appreciated, thankyou
.addValueEventListener()
when the database updates it does something that triggers this function to run .So lets say you have a copy of the Firebase data on the device
and everything is sync correctly then NOTHING happens (you dont iven use the internet connection to get data u just ask the db if it did any modifications or no) ,Now all the data you get from you db is from your local db version of your Firebase db.
this is just details aboute how firebase works systhematicaly.
If data gets inserted you get the modifications that happened only + the data that didn't got changed in your "local Firebase db" .
So now you need to store data in a List by clearing and refilling it when a modification happens on "remote Firebase db".
And then work on the Lists you have on your device .

Getting the data from Firebase and putting it there at the same time [duplicate]

I want to make an Android chat application. So I want to know how to get data from Firebase Firestore automatically, when new document create? Actually I do not wanna use add snapshot listener because of its give real-time data changes of a single document but want to find out real time updated Firebase Firestore document. Please suggest me.
I don't know if you can do this without a snapshot listener.
Check this code, if it is what you want.
private void addRealtimeUpdate() {
DocumentReference contactListener=db.collection("PhoneBook").document("Contacts");
contactListener.addSnapshotListener(new EventListener < DocumentSnapshot > () {
#Override
public void onEvent(DocumentSnapshot documentSnapshot,
FirebaseFirestoreException e) {
if (e != null) {
Log.d("ERROR", e.getMessage());
return;
}
if (documentSnapshot != null && documentSnapshot.exists()) {
Toast.makeText(MainActivity.this, "Current data:" +
documentSnapshot.getData(), Toast.LENGTH_SHORT).show();
}
}
});
}
To solve this, I recommend you to use CollectionReference's get() method. This is the correspondent addListenerForSingleValueEvent() method from Firebase real-time database.
Executes the query and returns the results as a QuerySnapshot.
If you want to use Firebase-UI library, this is a recommended way in which you can retrieve data from a Cloud Firestore database and display it in a RecyclerView using FirestoreRecyclerAdapter.
I don't know if you can do it with firestore but with realtime database you can use the .on(). If the rest of your app is using firestore, each project can use both a cloud firestore and a realtime database. The docs are really simple.

Android Firebase Query for near Timestamps (and close Locations if possible)

I'm a newbie with Firebase and I implemented it in my earthquake sensing Android app. My structure looks like
So, everytime my app senses an earthquake it makes an entry in Firebase like above. What I want to do though is use data from other devices as well to determine if the earthquake was legit or not. Specifially, every time 1 device senses one, I wanna check the firebase if in the last minute there was another entry from another device as well (ideally I would want to also check the coordinates to see if it's at a nearby location but I saw that this is more tough to accomplish so you can skip that). Any idea of how this is possible? Basically, I just want to check if new entries within 1 minute of my entry exist (I could also make a check after 1 minute, in case my device was the first to detect it).
Thanks a lot in advance.
Firebase Realtime Database queries are a multi-step process:
Order the data on a specific property value.
Determine a start node and/or end node to return (sometimes called a slice).
Optionally limit the number of nodes to return.
In Android that'd look something like:
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Earthquakes");
Query query = ref.orderByChild("timestamp").startAt("2020-11-03 18:12:00").endAt("2020-11-03 18:12:59").
query.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot quakeSnapshot: dataSnapshot.getChildren()) {
Log.i("DB", quakeSnapshot.getKey());
Log.i("DB", quakeSnapshot.child("eventType").getValue(String.class));
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
}
I highly recommend reading the Firebase documentation on reading and querying data, and taking the Codelab for Android developers.

Is it better to pass more information in an intent to an activity or call the database in the other activity

I'm making an application with Firebase where a User has to sign in to use the application. The MainActivity will only launch after the User has signed in, using FirebaseAuth and FirebaseAuth.AuthStateListener.
So in the Main Activity, I have all the information about the current User.
My question is, when navigating to other activities, is it better to pass more extras via Intents about the User (or any object) to SecondActivity, or is it better to read from the Firebase database in the SecondActivity?
(Both works fine for my app, but I'm thinking about good programming style / structure and thinking about resources, speed and performance)
Also worth mentioning, I want to keep in mind that almost all of the activities' screens / UI will be updated by the information about the current object, so I want the app to be as fast and responsive as possible. For some of the code I have in my project now, I have to use Thread.sleep(x), to let the UI wait for the database to finish reading before updating the UI. This is what I'm currently using in my Google Maps Activity.
The PK of the User is the Gmail, used for signing in. Each User has several ArrayLists (that contains objects) that will grow larger when using the application, so eventually, a lot of information will be passed.
Take a look at the example code below, but don't bother too much with the details, it's just some code that I put in there now. The important thing is the general structure of how to retrieve and pass information in each activity:
MainActivity:
Intent i = new Intent(this, SecondActivity.class);
i.putExtra("email", thisUser.getEmail());
startActivity(i);
SecondActivity:
private FirebaseDatabase Db;
private DatabaseReference destinationRef, userRef;
private String email;
private User thisUser;
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.SecondActivity);
email = getIntent().getStringExtra("email");
Db = FirebaseDatabase.getInstance();
userRef = Db.getReference().child("Users");
destinationRef = Db.getReference().child("Destinations");
getInfoFromDb();
}
private void getInfoFromDb(){
userRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
User u;
for(DataSnapshot data : dataSnapshot.getChildren(){
u = data.getValue(User.class);
u.setUid(data.getKey());
if(email.equalsIgnoreCase(u.getEmail())){
thisUser = u;
/* Update something else, based on this info */
}
}
}
#Override
public void onCancelled(DataSnapshot dataSnapshot) { }
});
destinationRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Destination d;
for(DataSnapshot data : dataSnapshot.getChildren()){
d = data.getValue(Destination.class);
d.setUid(data.getKey());
if(thisUser.getCurrentTrip().getDestinationName().equalsIgnoreCase(d.getDestinationName())){
/*Something else, update UI or whatever */
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) { }
});
}
Here is another (shorter) example:
MainActivity:
Intent i = new Intent(this, SecondActivity.class);
i.putExtra("email", thisUser.getEmail());
i.putExtra("rank", thisUser.getRank());
i.putExtra("points", thisUser.getPoints());
i.putExtra("someArray", thisUser.getSomeArray());
i.putStringArrayListExtra("somethingElse", thisUser.getSomeStringArrayList());
// And let's say we put in a lot more information
startActivity(i);
SecondActivity
thisEmail = getIntent().getStringExtra("email");
thisRank = getIntent().getStringExtra("rank");
thisEmail = getIntent().getIntExtra("points");
thisSomeArray = getIntent().getStringArrayExtra("someArray");
thisArrayList = getIntent().getStringArrayListExtra("somethingElse");
Which approach is better?
1) The first code example, where I read from the database in the SecondActivity to get info.
2) Send the whole thisUser-object (which can grow quite big, and serialization has to be used) from MainActivity to SecondActivity.
3) Pass more (can maybe be a lot) information from MainActivity with the Intents, to the other Activites.
Again, I'm thinking about good programming structure, practice, style and am concerned about speed, responsiveness and resources.
Thanks!
I would retrieve the data from the database, since you said it can be more information. So, its better to just retrieve the data from the database in the SecondActivity.
If you pass the data using intent it means you are sharing it between activities and not storing it.
Also lets say you want to do a query that involves more than one node (maybe two nodes under root(like a join) or nested nodes), you will have to retrieve the data from the database to be able to do that
Think of testing.
In one case, you need your test framework to pass in all this extra data to test just the second method. Coupling has been increased. The method is less cohesive, since it can’t operate independently.
In the other case, the test framework doesn’t need to pass in the extra data, because the method retrieves the required information itself. Coupling is decreased. The method is more cohesive.
My $0.02
Your question is very specific to the application being developed.
Passing data through intent or persisting it in DB is very subjective to what kind of data it is and what would be the action plan when you lose that data due to some reason.
Pros & Cons : Passing data in intent
Having data passed around in intent is good for transient or deduced data as it’s computed for taking some actions and shouldn’t be persisted or retrieved every time the activity is loaded.
Code will be more complicated as compared to DB approach as every time you traverse from one activity to another you have to add code to pass the intent or check the data passed or add new data in current activity. If system crashes you loose all data and state.
Pros & Cons : DB approach
having data in DB provides you a way to resume the state when there is crash or will act as checkpoint for future. It also means you have to maintain tables and code to handle them but it would be clean as the interfaces will be clean and defined. On same note, there can be multiple calls to save and retrieve data.
You also need to consider whether data is sensitive or not.
In nutshell, it’s purely upon your application needs and you have to identify what data is required for computation and what needs to be persisted and accordingly used mixed approach to achieve better performance with reliability.

How does Firebase config get the region/country for a device?

I have a problem and I need to know how does the firebase config gets the region/country for a user, is the region based on google account, or what ? also how does it get the region without any permission ?
I have met the problem when I try to get the device region. Here are many ways to get this region, you can use below ways:
use "ro.carrier" get the cid;
use Locale.getDefault().getCountry() get the short country name;
use (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE) to get the region of SIM card.
you may use all of them and given priority.
For Firebase, I have met a short code below, maybe this can help you:
String feature_url = "feature_config";
Log.d(TAG, "init, feature_url: " + feature_url);
mRootReference = FirebaseDatabase.getInstance().getReference();
mRootReference.child(feature_url).child(BuildConfiguration.DEBUG ? "debug" : "release")
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
Log.d(TAG, "onDataChange");
FeatureConfig.getInstance().updateConfig(dataSnapshot);
}
#Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG, "onCancelled");
}
});
this ie a method used to get the DataSnapShot and then get the region information from it.
Since I dont know whether this could help you, I dont past to much code here.
Hope it helps.
This may give you some idea!!!
You have your own FCM key is strictly required for native implementation.
While setup to get FCM key user should provide region/country
How to set up your own FCM keys:
1) Log in with your Google Account
Open https://console.firebase.google.com/ and log in using your Google account (if the page asks you to do so).
2) Click on Create New Project
In the next box that appears, click on Create New project.
3) Compose the Project Name and select your country/region
You’ll now be prompted with a modal box like the one shown below. Under Project name, write the name you want and below that, select your Country/region. Once you’ve done this, click on the Create Project.
For detail go through this

Categories

Resources