How do I retrieve the firebase list in the same order as it is added.
Looks like I’m getting them in a random order. I need to have them in order to draw my polyline in correct order.
List<LatLng> latLngList = new ArrayList<>();
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot direction : snapshot.getChildren()) {
if (direction.getKey().equals(firebaseKey)) {
MyLatLng wantedDirection = direction.getValue(MyLatLng.class);
for (Waypoints waypoint : wantedDirection.getWaypoints().values()) {
double lat = waypoint.getLatitude();
double lang = waypoint.getLongitude();
LatLng latLng = new LatLng(lat, lang);
latLngList.add(latLng);
}
I want the JSON file to be in the same order as it the entries were added to the firebase list:
{
"timeStamp" : "2016-05-03 23:06:05",
"waypoints" : {
"-KGsf4xB_rZbsAMW4I2D" : {
"latitude" : 58.338713,
"longitude" : 11.90885
},
"-KGsf5M9YtZn6Yq22Kts" : {
"latitude" : 58.339218,
"longitude" : 11.910351
},
"-KGsf5qSV3X7cAIBtANF" : {
"latitude" : 58.340572,
"longitude" : 11.915417
},
"-KGsf6oww79POAY_e7kf" : {
"latitude" : 58.342271,
"longitude" : 11.921562
},
"-KGsf7JBaac5o7VMEZMh" : {
"latitude" : 58.344006,
"longitude" : 11.926909
},
"-KGsf7nGpMEgPA0j1rRl" : {
"latitude" : 58.345594,
"longitude" : 11.929302
},
"-KGsf8HjFtn7Dxpx-DpO" : {
"latitude" : 58.347846,
"longitude" : 11.931577
},
"-KGsf8ltvEBeqXE_me8Z" : {
"latitude" : 58.350397,
"longitude" : 11.932334
}
}
}
DataSnapshot.getChildren() will return the children in the order in which you've queried them from the database. If you're not specifying orderByChild() or orderByPriority() explicitly, that order will be by key, which means they will be iterated in the order they were inserted.
But for the waypoints, you are defining your own order:
for (Waypoints waypoint : wantedDirection.getWaypoints().values()
The values() of a Map are not going to be in a specific order afaik.
Update
To see the order in which the items are retrieved from Firebase, you can traverse the DataSnapshot:
public void onDataChange(DataSnapshot snapshot) {
for (DataSnapshot direction: snapshot.getChildren()) {
DataSnapshot waypoints = direction.child("waypoints");
for (Waypoints waypoint: waypoints.getChildren()) {
double lat = waypoint.child("latitude").getValue(Double.class);
double lon = waypoint.child("longitude").getValue(Double.class);
LatLng latLng = new LatLng(lat, long);
latLngList.add(latLng);
}
}
Alternatively, you can look for a map that returns its entries in the order of its keys.
This worked for me:
for (Map.Entry<String, Waypoints> waypoint : wantedDirection.getWaypoints().entrySet()) {
String key = waypoint.getKey();
Waypoints value = waypoint.getValue();
double lat = value.getLatitude();
double lang = value.getLongitude();
LatLng latLng = new LatLng(lat, lang);
latLngRealList.add(latLng);
}
Related
I am using firebase realtime database in my first android app. I'm trying to retrieve data from firebase as an arraylist of "username" but i'm constantly having the Query returning a null result. i'm very new to firebase so i'm really struggling with data retrieval errors.
"Marchand" : {
"Taha" : {
"adress" : "58 avenu St Eugène ",
"blockage" : false,
"latitude" : 35.7498635,
"longitude" : -0.5566705,
"mail" : "mailmail#gmail.com ",
"password" : "123456",
"signalement" : 0,
"telephone" : "0666666666",
"username" : "Taha"
},
"Yasmine" : {
"adress" : "Address kkdndbdk ",
"blockage" : false,
"latitude" : 35.7498636,
"longitude" : -0.5566704,
"mail" : "randommail#gmail.com",
"password" : "bobo",
"signalement" : 0,
"telephone" : "06999999",
"username" : "Yasmine"
}
.
.
.
This is one of my attempts, i tried to use the order-by-child method to iterate through the multiple nods that i have but i'm sure that it's not the right way to do this, this gives me null poiter exceptions because the datasnapshot is returning a NULL value :
referenceMarchand = rootNode.getReference("Marchand");
final ArrayList<String> types = new ArrayList<>();
Query users = referenceMarchand.orderByChild("username");
users.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
types.add(dataSnapshot.child("username").toString());
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
lets make use of some functions of firebase, Lets see it works for you.
part 1)
we will save it another way around
"Merchant" : {"Name" : "Taha"
"ID" :"-KSMCMCMnnkd"},//Firebase generated id
{"Name" : "Yasmine"
"ID" :"-KSMCMccccnkd"},//Firebase generated Id
...........
Part 2)
And Save the Details
"Details" : {
"ID" : "-KSMCMCMnnkd" //Firebase generated id
"adress" : "58 avenu St Eugène ",
"blockage" : false,
"latitude" : 35.7498635,
"longitude" : -0.5566705,
"mail" : "mailmail#gmail.com ",
"password" : "123456",
"signalement" : 0,
"telephone" : "0666666666",
"username" : "Taha"},
{
"ID":"-KSMCMccccnkd" //Firebase generated id
"adress" : "Address kkdndbdk ",
"blockage" : false,
"latitude" : 35.7498636,
"longitude" : -0.5566704,
"mail" : "randommail#gmail.com",
"password" : "bobo",
"signalement" : 0,
"telephone" : "06999999",
"username" : "Yasmine"}
In Part 1)
DatabaseRefrence ref = FirebaseDatabase.getInstance("/Path");
String id = ref.child("Merchant").push().getKey(); //Firebase generated id
Merchant merchant = new Merchant();
merchant.setId(id);
merchant.setName("SomeName");
ref.child("Merchant").child(id).setValue(merchant);
Part 2)
Detail detail = new Detail();
detail.setAddress("Some Address");
detail.setBlockage("false");
detail.setLatitude("SomeValue");
detail.setEmail("someText#gmail.com");
......
ref.child("Details").child(id).setValue(detail);
Now
List<Merchant> merchants = new ArrayList<>();
List<Detail> details = new ArrayList<>();
ref.child("Merchant").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(Datasnapshot snapshot:dataSnapshot){
Merchant merchant = snapshot.getValue(Merchant.class);
merchants.add(merchant);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
ref.child("Details").addValueEventListener(new ValueEventListener(){
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(Datasnapshot snapshot:dataSnapshot){
Detail detail = snapshot.getValue(Detail.class);
details.add(detail);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Now you can get the details for some merchant or save it in local database for later querying.
I am trying to post data on a particular structure in firebase database but not able to get the expected result. Need the structure like:
ABC->DEVICE_ID-COORDINATES->DATE->PUSHKEY (EX:-KSHJDWFQ)->NOW CHILD LATITUDE AND LONGITUDE.
I am not able to push the child to date as the expected pattern.
Expected pattern:
{
"ABC" : {
"1_861645036247906" : { ///device id
"co-ordinates" : { ///coordinates
"15-11-2017" : { ///date
"KSHJDWFQ" : { ///push key
"latitude" : 4564564,
"longitude" : 45454545
},
"khgjhkhjk" : {
"latitude" : 456456456,
"longitude" : 435345345
}
},
"16-11-2017" : {
"KSHJDWFQ" : {
"latitude" : 4564564,
"longitude" : 45454545
},
"khgjhkhjk" : {
"latitude" : 456456456,
"longitude" : 435345345
}
}
},
"driver_details" : {
"driver_id" : 1,
"driver_name" : "avik"
}
}
},
}
My result is coming like this:
{
"ABC" : {
"2_861645036247906" : {
"-Kz8lFh9B86pCj62gcN3" : {
"coordinates" : {
"17-11-2017" : {
"latitude" : "22.5735875",
"longitude" : "88.431699"
}
}
},
"-Kz8ldboHvGS5QabIVZY" : {
"coordinates" : {
"17-11-2017" : {
"latitude" : "22.5735875",
"longitude" : "88.431699"
}
}
}
}
}
}
This is the code I have done:
Driver driver = new Driver();
String child_node = KPUtils.get_driver_IdPreference(mContext) + "_" + KPUtils.getdeviceid(mContext);
Firebase ref = new Firebase("https://pool------").child(child_node);
String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date());
Map<String, String> m_coordinates = new HashMap<>();
m_coordinates.put("latitude", st_latitude);
m_coordinates.put("longitude", st_longitude);
Map<String, Map<String, String>> gens = new HashMap<>();
gens.put(date, m_coordinates);
Map<String, String> m_driverdetails = new HashMap<>();
m_driverdetails.put("driver_id", "1");
m_driverdetails.put("driver_name", "Avik");
driver.setCoordinates(gens);
//driver.setDriver_details(m_driverdetails);
ref.push().setValue(driver);
You may try this...
ref.child("abc")
.child("device id")
.child("coordinates")
.child(date)
.push()
.setValue(m_coordinates);
I need to set up all markers on my map from my firebase database, I do it in onMapReady method:
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
DatabaseReference db = FirebaseDatabase.getInstance().getReference();
db.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()){
double allLat = (double) child.child("lat").getValue();
double allLng = (double) child.child("lng").getValue();
mMap.addMarker(new MarkerOptions().position(new LatLng(allLat, allLng)).title("Пользователь"));}
}
#Override
public void onCancelled(DatabaseError databaseError) {
Toast.makeText(MapsActivity.this, "Не найдены пользователи", Toast.LENGTH_SHORT).show();
}
});
I get an error:
java.lang.NullPointerException: Attempt to invoke virtual method 'double java.lang.Double.doubleValue()' on a null object reference
Your code expects the database to be structured as shown below, where each child location contains a lat and a lng value that is a double. If the database does not have this structure, or one of the lat/lng properties is missing, child.child("lat").getValue() will return null, and an exception will be thrown.
You can eliminate the cast to double with this change:
double allLat = child.child("lat").getValue(Double.class);
double allLng = child.child("lng").getValue(Double.class);
Also, you should use addListenerForSingleValueEvent() instead of addValueEventListener(). You only need the data once, you don't want to leave the listener attached.
{
"key1" : {
"lat" : 33.0,
"lng" : 110.0
},
"key2" : {
"lat" : 34.0,
"lng" : 111.0
},
"key3" : {
"lat" : 35.0,
"lng" : 112.0
},
"key4" : {
"lat" : 36.0
// error: lng is missing, will be read as null, causing exception
}
}
This is my firebase database and further more is there. I just want to fetch all latitude and longitude of the users, but i cant pass through the UID
"user"
"ODs4wO19sLcht8bobUKFRVkIzu73" : {
"Email" : "jik#gmail.com",
"First Name" : "Dummy",
"Last Name" : "Name",
"Latitude" : "22.31179464",
"Longitude" : "73.18581206",
"Owner Address" : "bskksos",
"Profile Image" : "https://firebasestorage.googleapis.com/v0/b/streetfood2-4bd8a.appspot.com/o/Profile+Images%2Fcropped-1678023661.jpg?alt=media&token=43a13ac5-3dec-46b4-a38c-3c14475d42fa"
},
"OQu7N7hqJ6SLipqFwqutRozDtrz1" : {
"Email" : "fhfhd#gnail.com",
"First Name" : "shiv",
"Last Name" : "singh",
"Latitude" : "22.31179464",
"Longitude" : "73.18581206",
"Mobile Number" : "00000000",
"Password" : "qwerty",
"Profile Image" : "https://firebasestorage.googleapis.com/v0/b/streetfood2-4bd8a.appspot.com/o/Profile+Images%2Fcropped1324744850.jpg?alt=media&token=20a0efad-fb57-409d-a0d8-d6249366830d"
},
If you're looking to loop over all users:
DatabaseReference users = FirebaseDatabase.getInstance().getReference().child("Users");
users.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot userSnapshot: dataSnapshot.getChildren()) {
double lat = userSnapshot.child("latitude").getValue(Double.class);
double lon = userSnapshot.child("longitude").getValue(Double.class);
System.out.println(lat+","+lon);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
throw databaseError.toException();
}
});
This Is how I want it to look but I'm getting null object reference
inside of (DataSnapshot wayPointsChild : wayPointsSnapshotChild.getChildren()) {
Those two property crashes everything
"timeStamp" : "2016/04/27 18:28:52",
"travelType" : "work"
JSON FROMAT
"waypoints" : {
"-KHB1VjqUdO90vxj9XCh" : {
"timeStamp" : "2016/04/27 18:28:52",
"travelType" : "work"
"-KHB1VjqUdO90vxj9XCi" : {
"latitude" : 58.337679,
"longitude" : 11.912757
},
"-KHB1ZykbwgXM9sPNie9" : {
"latitude" : 58.281384,
"longitude" : 12.294495
},
},
"-KHpPe06hLpPttuGZ0rZ" : {
"timeStamp" : "2016/04/27 18:28:52",
"travelType" : "private"
"-KHpPe07pE5ZYn4JGiZ1" : {
"latitude" : 58.281384,
"longitude" : 12.294495
},
"randomid1212" : {
"latitude" : 57.689903,
"longitude" : 11.989792
},
"randomid1213" : {
"latitude" : 57.689905,
"longitude" : 11.989795
},
}
The current onDataChange() method
mUserRef.addValueEventListener(new ValueEventListener() {
//this keeps per-user list of points
List<MyWaypoint> userWayPointsList = new ArrayList<MyWaypoint>();
#Override
public void onDataChange(DataSnapshot wayPointsDataSnapshot) {
if (wayPointsDataSnapshot.getChildrenCount() > 0) {
for (DataSnapshot wayPointsSnapshotChild : wayPointsDataSnapshot.getChildren()) {
Log.i("FireBaseTester", "For-Loop :: wayPointsSnapshotChild.getValue() : " + wayPointsSnapshotChild.getValue());
if (wayPointsSnapshotChild.getChildrenCount() > 0) {
// Temporary list
List<String> latLngListTemp = new ArrayList<>();
// THIS Gives me the error because it get used in the next for loop for some reason.
wayPointsSnapshotChild.child("timeStamp").getValue();
for (DataSnapshot wayPointsChild : wayPointsSnapshotChild.getChildren()) {
//this is where we get the Lat and Lon
double latitude = Double.parseDouble(wayPointsChild.child("latitude").getValue().toString());
double longitude = Double.parseDouble(wayPointsChild.child("longitude").getValue().toString());
Log.i("FireBaseTester", "latitude = " + latitude + " , longitude = " + longitude);
latLngListTemp.add(latitude + ", " + longitude);
}
// List containing a nested List<List<String>>
latitudeNlongitude.add(latLngListTemp);
}
}
}
//here you can assign the points to the user
Log.i("FireBaseTester", "There are " + userWayPointsList.size() + " Points for User");
}
#Override
public void onCancelled(FirebaseError firebaseError) {
Log.e("FireBaseTester", "onCancelled - wayPointRef Error is " + firebaseError.getMessage());
}
});
} else {
Log.i("FireBaseTester", "No WayPoints Data Received");
}
LOGCAT
FATAL EXCEPTION: main
Process: com.example.rasmusjosefsson.rjcar, PID: 25446
java.lang.NullPointerException: Attempt to invoke virtual method
'java.lang.String java.lang.Object.toString()' on a null object
reference
at
com.example.rasmusjosefsson.rjcar.demo.MapListActivityRealBack2$1.onDataChange(MapListActivityRealBack2.java:122)
at
com.firebase.client.core.ValueEventRegistration.fireEvent(ValueEventRegistration.java:56)
at com.firebase.client.core.view.DataEvent.fire(DataEvent.java:45)
at
com.firebase.client.core.view.EventRaiser$1.run(EventRaiser.java:38)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5417)
at java.lang.reflect.Method.invoke(Native Method)
at
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
These lines demonstrate the problem:
wayPointsSnapshotChild.child("timeStamp").getValue();
for (DataSnapshot wayPointsChild : wayPointsSnapshotChild.getChildren()) {
{
double latitude = Double.parseDouble(wayPointsChild.child("latitude").getValue().toString());
Calling getChildren on wayPointSnapshotChild will return the timestamp value as one of the children, which doesn't have a child called latitude.
You could structure your data like this:
"waypoints" : {
"-KHB1VjqUdO90vxj9XCh" : {
"timeStamp" : "2016/04/27 18:28:52",
"travelType" : "work"
"points": {
"-KHB1VjqUdO90vxj9XCi" : {
"latitude" : 58.337679,
"longitude" : 11.912757
},
"-KHB1ZykbwgXM9sPNie9" : {
"latitude" : 58.281384,
"longitude" : 12.294495
}
}
}
Then in your for loop call it:
wayPointsSnapshotChild.child("points").getChildren()
Then the inner loop would only receive wayPointChild objects which contain latitude and longitude properties.