Firebase onDataChange method on null object reference - android

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.

Related

Firebase Iterate through entire database

I am trying to receive all the data from a firebase database, so I can place it into a Users class however I do not know how I will iterate through the entire database as I cannot interger (the i variable in the for loop) insert values into the child field.
My code is this:
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if(dataSnapshot.exists())
{
String fullname = (String) dataSnapshot.child(userId).child("Fullname").getValue();
String country = (String) dataSnapshot.child(userId).child("Country").getValue();
String profilePicture = (String) dataSnapshot.child(userId).child("ProfilePicture").getValue();
String username = (String) dataSnapshot.child(userId).child("Username").getValue();
Toast.makeText(getApplicationContext(), "Testing with: " + fullname + country + profilePicture + username, Toast.LENGTH_SHORT).show();
Toast.makeText(getApplicationContext(), "Count : (4) - " + dataSnapshot.getChildrenCount(), Toast.LENGTH_SHORT).show();
showProfiles(dataSnapshot);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
Database:
{
"Users" : {
"4PdlTlv3qjZ3BmDvrJyUut9Fnq43" : {
"Country" : "xx",
"Fullname" : "hh",
"ProfilePicture" : "htm/o/Images%2FSearchAdapter%2F4PdlTlv3qjZ3BmDvrJyUut9Fnq43%2FProfilePicture%2FProfilePic_2019.03.06.10.47.54.jpg.jpg?alt=media&token=b647708e-c6d5-4b45-bef0-3dc40301b73a",
"Username" : "hmack001"
},
"COg4r4io9hezhFpmK3adPucUXA93" : {
"Country" : "spain",
"Fullname" : "nat",
"ProfilePicture" : "hcom/o/Images%2FSearchAdapter%2FCOg4r4io9hezhFpmK3adPucUXA93%2FProfilePicture%2FProfilePic_2019.03.06.19.14.17.jpg.jpg?alt=media&token=8620b321-5cef-42f0-a828-dbb7c37c8e7d",
"Username" : "nat"
},
"Tw1xRxViygNsLqrQiaaMAvAduIu1" : {
"Country" : "uk",
"Fullname" : "harvey\n",
"ProfilePicture" : "t.com/o/Images%2FUsers%2FTw1xRxViygNsLqrQiaaMAvAduIu1%2FProfilePicture%2FProfilePic_2019.03.03.05.26.35.jpg.jpg?alt=media&token=c290e75a-5f92-4271-bcb5-c644fe1b14ef",
"Username" : "RGB"
},
"vOxr1RoDqgWogKK1lp9pfpTHc6w2" : {
"Country" : "scotland ",
"Fullname" : "greg greg",
"ProfilePicture" : "ot.com/o/Images%2FSearchAdapter%2FvOxr1RoDqgWogKK1lp9pfpTHc6w2%2FProfilePicture%2FProfilePic_2019.03.04.12.30.22.jpg.jpg?alt=media&token=27b024cf-0691-4121-8a27-26acf101ebc2",
"Username" : "greg"
},
"xecUOPeyMcQaQrgkU9ouDgK90Ai1" : {
"Country" : "ggh",
"Fullname" : "Da apply ",
"ProfilePicture" : "2FProfilePic_2019.03.03.04.58.50.jpg.jpg?alt=media&token=f35854c2-3ff9-4d18-9f7a-10c13f066c68",
"Username" : "gg"
}
}
}
I am aware that there is no attempt in this code to retrieve information from all the users fields, I do not understand the logic behind iterating through the database as I dont see where I can do Item 1, Item 2 etc.
Use this
for (DataSnapshot childSnapshot : dataSnapshot.getChildren()) {
System.out.println(childSnapshot.getKey());
System.out.println(childSnapshot.child("Country").getValue(String.class));
}

Firebase Data Posting

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);

Firebase database how to create list from nodes like WhatsApp Chats page

I am trying to create chat app with Firebase database. I'm reading docs and watching tutorials but there is one thing I could not figure out how to do. When user sends message to another user, creating a chat room with key: "senderUserId_receiverUserId" You can see my structure below.
{
"chat_rooms" : {
"nTAHqCTmLRcLOM8CTfnHF4lRjLf2_oTLYaHMOMibh3ZqOcmpcWDtSCKp1" : {
"-KtQEGK38lhZrgnNxmqb" : {
"date" : "07/09/2017 10:28",
"message" : “Thanks for helping !”,
"photoUrl" : "http://www.clker.com/cliparts/B/R/Y/m/P/e/blank-profile-hi.png",
"receiverName" : "Ali”,
"receiverUid" : "oTLYaHMOMibh3ZqOcmpcWDtSCKp1",
"senderName" : “John”,
"senderUid" : "nTAHqCTmLRcLOM8CTfnHF4lRjLf2"
},
"-KtQEKK2BmIMzwruN-21" : {
"date" : "07/09/2017 10:28",
"message" : “Another Test Message“,
"photoUrl" : "http://www.clker.com/cliparts/B/R/Y/m/P/e/blank-profile-hi.png",
"receiverName" : “John”,
"receiverUid" : "nTAHqCTmLRcLOM8CTfnHF4lRjLf2",
"senderName" : "Ali",
"senderUid" : "oTLYaHMOMibh3ZqOcmpcWDtSCKp1"
},
"-KtQIGDk5zE4JZuE9pIQ" : {
"date" : "07/09/2017 10:45",
"message" : “Test message !“,
"photoUrl" : "http://www.clker.com/cliparts/B/R/Y/m/P/e/blank-profile-hi.png",
"receiverName" : “John”,
"receiverUid" : "nTAHqCTmLRcLOM8CTfnHF4lRjLf2",
"senderName" : "Ali",
"senderUid" : "oTLYaHMOMibh3ZqOcmpcWDtSCKp1"
}
}
},
"users" : {
"nTAHqCTmLRcLOM8CTfnHF4lRjLf2" : {
"address" : “istanbul”,
"cell_phone" : “none”,
"email" : “john#gmail.com",
"home_phone" : “none”,
"name" : “John”,
"photoUrl" : "http://www.clker.com/cliparts/B/R/Y/m/P/e/blank-profile-hi.png",
"userId" : "nTAHqCTmLRcLOM8CTfnHF4lRjLf2"
},
"oTLYaHMOMibh3ZqOcmpcWDtSCKp1" : {
"address" : “istanbul”,
"cell_phone" : “none”,
"email" : "ali#gmail.com”,
"home_phone" : “none”,
"name" : "Ali",
"photoUrl" : "http://www.clker.com/cliparts/B/R/Y/m/P/e/blank-profile-hi.png",
"userId" : "oTLYaHMOMibh3ZqOcmpcWDtSCKp1"
}
}
}
With this way everything works fine but I don't know how to list user's all conversations at list like WhatsApp's Chats page. I mean when user clicks the conversations item, related conversation will be open.
I'm sending private messages with code below:
public void sendMessageToFirebaseUser(final Context context, final ChatMessageModel chat, final String receiverFirebaseToken) {
final String room_type_1 = chat.getSenderUid() + "_" + chat.getReceiverUid();
final String room_type_2 = chat.getReceiverUid() + "_" + chat.getSenderUid();
final DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference();
databaseReference.child(Constants.ARG_CHAT_ROOMS)
.getRef()
.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.hasChild(room_type_1)) {
Log.e("aaa", "sendMessageToFirebaseUser: " + room_type_1 + " exists");
databaseReference.child(Constants.ARG_CHAT_ROOMS)
.child(room_type_1)
.push()
.setValue(chat);
} else if (dataSnapshot.hasChild(room_type_2)) {
Log.e("aaa", "sendMessageToFirebaseUser: " + room_type_2 + " exists");
databaseReference.child(Constants.ARG_CHAT_ROOMS)
.child(room_type_2)
.push()
.setValue(chat);
} else {
Log.e("aaa", "sendMessageToFirebaseUser: success");
databaseReference.child(Constants.ARG_CHAT_ROOMS)
.child(room_type_1)
.push()
.setValue(chat);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
Thank you for reading my post.
If you want to show a list of chat rooms for the current user, you should model your data to allow that. The easiest way to do this is to add a list of chat rooms for each user to your data model:
"userChatrooms" : {
"nTAHqCTmLRcLOM8CTfnHF4lRjLf2" : {
"nTAHqCTmLRcLOM8CTfnHF4lRjLf2_oTLYaHMOMibh3ZqOcmpcWDtSCKp1": true
},
"oTLYaHMOMibh3ZqOcmpcWDtSCKp1" : {
"nTAHqCTmLRcLOM8CTfnHF4lRjLf2_oTLYaHMOMibh3ZqOcmpcWDtSCKp1": true
}
}

Firebase android, location

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
}
}

Retrieve firebase data in the same order as its added

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);
}

Categories

Resources