1

Need to retrieve Latitude and Longitude for each specific event from Firebase where the user when creating en event also picks event location (Latitude and Longitude) by setting marker at a specific location.

The problem that I am having is that the last event saved overrides all other existing event locations and so when you hit the TextView to take you to GoogleMaps to show you where the event will be taking place only last event's location saved comes up. But obviously each event has its own specific location.

For example, if I create three events and their locations are Rome, Berlin, and Moscow, the only marker that will be created on GoogleMap will be of event in Moscow because that was the last location saved.

I would like for when the second user hits the TextView using each event-specific postid for that event to be found in the database and for its specific coordinates to show up on the map. Can someone please help me to achieve this? I have been trying to achieve this with datasnapshot, but I haven't been able to find other event locations. I always just get the last event's location saved for all posts. Is there a better way to do it than datasnapshot?

Picture below hope helps clear up how my data structure is organized.

Firebase data structure

MapsActivityUser.java

public class MapsActivityUser extends FragmentActivity implements OnMapReadyCallback {

    private GoogleMap map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_maps_user);

        SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {
        map = googleMap;

        final DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Post post = snapshot.getValue(Post.class);
                    if (post != null) {
                        double latitude = post.getLocation().getLatitude();
                        double longitude = post.getLocation().getLongitude();

                        LatLng location = new LatLng(latitude, longitude);
                        map.addMarker(new MarkerOptions().position(location).title("Event location"));
                        map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 10));
                    } else {
                        Toast.makeText(MapsActivityUser.this, "Event doesn't have location on Map", Toast.LENGTH_SHORT).show();
                    }
                }
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }
}
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
JMB
  • 313
  • 2
  • 9
  • If comment this line `map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 10));` and you increase the zoom, do you see all markers? – Alex Mamo Jan 27 '20 at 15:22
  • @AlexMamo Yeah you're right I see all the markers. How can I make it so just the marker for the location of that specific event comes up and the others don't? – JMB Jan 28 '20 at 17:41
  • Please check my answer below. – Alex Mamo Jan 29 '20 at 11:46

2 Answers2

1

The problem in your code is the use of the following line of code:

map.moveCamera(CameraUpdateFactory.newLatLngZoom(location, 10));

Inside the for loop, which basically means that your camera will be moved to the last location that is iterated in the loop. However, if you increase the zoom, you'll be able to see all locations on the map. According to your last comment:

How can I make it so just the marker for the location of that specific event comes up and the others don't?

In this case, you should use a Query. Basically you'll tell Firebase to return only a single location that matches your query. This should look like this:

Query query = reference.orderByChild("locationName").equalTo("locationName");

Now, simply attach a listener on this query and add the marker on the map. In this case is recommended to move the camera to the location, since you get only a single location. But be aware that this query will work if you have unique location names. If you are also storing the id of a location, then you can use only a DatabaseReference that looks like this:

DatabaseReference locationRef = reference.child(locationId);

Attach a listener and add the marker on the map.

Edit:

To get the latitude and longitude, please use the following lines of code:

Query query = reference.orderByChild("postid").equalTo("-LzNDAXtnT6NXYK2XYPK");
ValueEventListener valueEventListener = new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        for(DataSnapshot ds : dataSnapshot.getChildren()) {
            double latitude = ds.child("location").child("latitude").getValue(Double.class);
            double longitude = ds.child("location").child("longitude").getValue(Double.class);
            Log.d(TAG, latitude + ", " + longitude);
        }
    }

    @Override
    public void onCancelled(@NonNull DatabaseError databaseError) {
        Log.d(TAG, databaseError.getMessage()); //Don't ignore errors!
    }
};
query.addListenerForSingleValueEvent(valueEventListener);
Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • Okay, one question--if the location is a node that has a two child nodes (```Latitude``` and ```Longitude```) which stores the location data then do I just do ```DatabaseReference locationRef = reference.child(location);```. Because the locations aren't saved as city names, they're saved as a ```Longitude``` and ```Latitude``` coordinates – JMB Jan 29 '20 at 16:01
  • In the picture above you can see how the location data is stored in Firebase – JMB Jan 29 '20 at 16:09
  • You don't think that it would be better if I did ```DatabaseReference reference = FirebaseDatabase.getInstance.getReference("Posts").child(postid);```??? – JMB Jan 29 '20 at 16:18
  • I have updated my answer with the code that gets the `latitude` and `longitude`. Please check it. – Alex Mamo Jan 29 '20 at 17:40
  • Alex, won't that just return the location of only that particular postid ```"-LzNDAXtnT6NXYK2XYPK"```?? I need for when the user clicks on the post, ANY post for that post's specific location to come back... and each post has it's own unique postid... – JMB Jan 29 '20 at 17:46
  • Should it be something like this? ```Query query = reference.orderByChild("postid").equalTo(post.getPostid);```?? to get each post's specific id – JMB Jan 29 '20 at 17:47
  • Yes should be that way, I just showed you an example. **[This](https://stackoverflow.com/questions/48622480/showing-firebase-data-in-listview)** how you display in a `ListView` and **[this](https://stackoverflow.com/questions/49383687/how-can-i-retrieve-data-from-firebase-to-my-adapter/49384849)** is how you display in a `RecyclerView`. – Alex Mamo Jan 29 '20 at 17:49
  • Dude I've been looking at this since you posted your answer and I have no idea how to make it work... ```Query query = reference.orderByChild("postid").equalTo("-LzNDAXtnT6NXYK2XYPK")``` the ```.equalTo("-LzNDAXtnT6NXYK2XYPK")``` I legit have no idea how to make it work so that the post just brings back one location the one location of that event... Anyways... – JMB Jan 29 '20 at 19:19
  • I even tried other things like storing ```postid``` in ```SharedPreferences``` to make it usable throughtout the whole app, but that's not working either... Idk how to fix it man – JMB Jan 29 '20 at 19:21
  • I just provided you some guidelines to solve this issue. You should make your own attempt given the information in the answer and ask another question if something else comes up. – Alex Mamo Jan 29 '20 at 19:25
  • Yeah you're right, I do want to solve it on my own. Do you mind if we chat for a moment? Just want to ask you why you sent me the how to display in ListView and RecyclerView – JMB Jan 29 '20 at 19:38
  • So it can help you display data in a list, this is only if you need it. – Alex Mamo Jan 29 '20 at 19:40
0

Listen for collection callback (Query Snapshot), inside callback run forloop, there you will get documentchanges class where you will get added, removed, modified indicator this indicates when data added, remove and modified, accordingly perform your logic. to get document use getId where it will return all document id present in collections. I'm not in front of pc, just check on Google.

i'll edit solution soon.

user8119020
  • 117
  • 3
  • Can you edit your answer to reflect the code that you're talking about? I still don't know how to go about doing it. Thanks – JMB Jan 28 '20 at 16:35