Google maps plotting multiple markers from firebase database - java

Getting trouble of plotting my markers on maps , im able to fetch my Latitude and Longitude of my users from firebase and store it to my arraylist , my problem is how im i able to set my arraylist globally? here is my code .
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private GoogleMap googleMap;
private MarkerOptions options = new MarkerOptions();
private ArrayList<LatLng> latlngs = new ArrayList<>();
private ArrayList<String> Names = new ArrayList<>();
String Lat ,Lon,Names1;
double latitude , longitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Positions");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot chidSnap : dataSnapshot.getChildren()) {
Lat = String.valueOf(chidSnap.child("Latitude").getValue());
Lon = String.valueOf(chidSnap.child("Longitude").getValue());
Names1 = String.valueOf(chidSnap.getKey());
latitude= Double.parseDouble(Lat);
longitude= Double.parseDouble(Lon);
latlngs.add(new LatLng(latitude, longitude));
Names.add(Names1);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// System.out.println(Names);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
for (LatLng point : latlngs) {
options.position(point);
options.title("Users");
options.snippet("someDesc");
googleMap.addMarker(options);
}
}
}
I have no idea what is wrong with this thing , somehow my map is showing no marker and my list "latlngs" is showing "0.0,0.0"
I have no idea how to set my latlngs globally since it is inside the code of fetching the datas from firebase.

Query to Firebase is an asynchronous process. So, probably your onDataChange is executed after onMapReady. Try below:
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot chidSnap : dataSnapshot.getChildren()) {
....
}
if(mMap != null) {
for (LatLng point : latlngs) {
options.position(point);
options.title("Users");
options.snippet("someDesc");
mMap.addMarker(options);
}
}
}
Or call mapFragment.getMapAsync(MapsActivity.this); from inside onDataChange

Related

Adding Multiple Markers from Firestore Database on Google Maps in Android Studio using Java

I'm new to Android development and I wanted to ask how I would be able to add multiple markers to my application using the coordinates stored in Firebase. A screenshot of the Firebase is shown, but it helps me get only one marker for now. I want to get multiple markers by accessing the same document or suggestions that can help me manage places stored in firebase in a more organized way and display them on the map along with name and location. I've been able to retrieve on location, for now, screenshots of the app and firebase are attached.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private static final int REQUEST_LOCATION_PERMISSION = 1009;
private GoogleMap mMap;
private ActivityMapsBinding binding;
private FusedLocationProviderClient mFusedLocationClient;
//These Clusters were used to manage the marker Clusters that had images on maps too
private ClusterManager mClusterManager;
//Same is the case with these clusters
private MyClusterManagerRenderer myClusterManagerRenderer;
//Instantiating the Firestore Database
FirebaseFirestore db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initializing our firebase firestore.
db = FirebaseFirestore.getInstance();
binding = ActivityMapsBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
//Getting the device location over here
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
private void addMapMarkers(){
}
private void getLastKnownLocation() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return;
}
mFusedLocationClient.getLastLocation().addOnCompleteListener(new OnCompleteListener<Location>() {
#Override
public void onComplete(#NonNull Task<Location> task) {
if(task.isSuccessful()){
Location location = task.getResult();
}
}
});
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// creating a variable for document reference.
DocumentReference documentReference = db.collection("MapsData").document("7QWDor9vozLaHdFYV9kh");
// calling document reference class with on snap shot listener.
documentReference.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot value, #Nullable FirebaseFirestoreException error) {
if (value != null && value.exists()) {
// below line is to create a geo point and we are getting
// geo point from firebase and setting to it.
GeoPoint geoPoint = value.getGeoPoint("geoPoint");
// getting latitude and longitude from geo point
// and setting it to our location.
LatLng location = new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude());
// adding marker to each location on google maps
mMap.addMarker(new MarkerOptions().position(location).title("Name"));
// below line is use to move camera.
mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
} else {
Toast.makeText(MapsActivity.this, "Error found is " + error, Toast.LENGTH_SHORT).show();
}
}
});
//Adding custom maps style over here
//******** THIS PART OF CODE EXCLUSIVELY DESIGNED TO FETCH THE CUSTOM MAPS.JSON TEMPLATE**********
enableMyLocation();
try {
// Customise the styling of the base map using a JSON object defined
// in a raw resource file.
boolean success = googleMap.setMapStyle(
MapStyleOptions.loadRawResourceStyle(
this, R.raw.mapstyle));
if (!success) {
Log.e("MapsActivity", "Style parsing failed.");
}
} catch (Resources. NotFoundException e) {
Log.e("MapsActivity", "Can't find style. Error: ", e);
}
//******** MAP STYLING CODE ENDS OVER HERE **********
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
LatLng islamabad = new LatLng(33.68, 73.04);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Islamabad"));
//moving the camera position to Islamabad.
mMap.moveCamera(CameraUpdateFactory.newLatLng(islamabad));
}
//Getting the Users current Location
private void enableMyLocation() {
if (ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mMap.setMyLocationEnabled(true);
} else {
ActivityCompat.requestPermissions(this, new String[]
{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_LOCATION_PERMISSION);
}
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
// Check if location permissions are granted and if so enable the
// location data layer.
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode) {
case REQUEST_LOCATION_PERMISSION:
if (grantResults.length > 0
&& grantResults[0]
== PackageManager.PERMISSION_GRANTED) {
enableMyLocation();
break;
}
}
}
}
To be able to get multiple markers from Firestore, you need to read all the documents that exist under the MapsData collection. This means that you need to create a reference that points exact to the collection and then perform a get() call:
FirebaseFirestore db = FirebaseFirestore.getInstance();
db.collection("MapsData").get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if (task.isSuccessful()) {
for (QueryDocumentSnapshot document : task.getResult()) {
if (document != null) {
GeoPoint geoPoint = value.getGeoPoint("geoPoint");
LatLng location = new LatLng(geoPoint.getLatitude(), geoPoint.getLongitude());
mMap.addMarker(new MarkerOptions().position(location).title("Name"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(location));
}
}
} else {
Log.d(TAG, task.getException().getMessage()); //Never ignore potential errors!
}
}
});
Your code adds a single marker because you are creating only a DocumentReference object that contains only a single GeoPoint object. If you need to read them in real-time, then you can listen for real-time updates.

Firestore Google Maps Marker setOnClickListerner problem in Android Studio

Can you guys help me out.
My code shows same document when I click a marker.
I think there problem in my for loop.
I am creating a list of parking spots and when clicked i would show the details of Parking spots in modal bottom sheet
here is my code.
public class ParkingSpace extends AppCompatActivity implements OnMapReadyCallback{
private GoogleMap mMap;
Parking parking;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference parkingRef = db.collection("Parking Lots");
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parking_space);
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.mapView);
mapFragment.getMapAsync(this);
}
#Override
public void onMapReady(#NonNull GoogleMap googleMap) {
mMap = googleMap;
LatLng sydney = new LatLng(16.4023,120.5960);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(sydney,14));
parkingRef.get()
.addOnSuccessListener(new OnSuccessListener<QuerySnapshot>() {
#Override
public void onSuccess(QuerySnapshot queryDocumentSnapshots) {
for (QueryDocumentSnapshot documentSnapshot: queryDocumentSnapshots){
parking = documentSnapshot.toObject(Parking.class);
parking.setDocumentId(documentSnapshot.getId());
String lat = parking.getLatitude();
String lon = parking.getLongitude();
String title = parking.getparkingName();
String owner = parking.getName();
String documentId= parking.getDocumentId();
double latd = Double.parseDouble(lat);
double lond = Double.parseDouble(lon);
LatLng location = new LatLng(latd,lond);
mMap.addMarker(new MarkerOptions().snippet("Owner: " +owner).position(location).title(title));
mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(#NonNull Marker marker) {
parking = documentSnapshot.toObject(Parking.class);
String path = documentSnapshot.getReference().getPath();
Toast.makeText(ParkingSpace.this, "Document ID:" +documentId, Toast.LENGTH_SHORT).show();
BottomSheet bottomSheet = new BottomSheet();
Bundle bundle = new Bundle();
bundle.putString("lat",lat);
bottomSheet.setArguments(bundle);
bottomSheet.show(getSupportFragmentManager(),"bottomsheet");
return false;
}
});
}
}
});
}
}
You are effectively using the same Parking instance ( parking ) for all markers because each iteration of the loop sets it to the value of the next query result. So by the time the marker click event occurs the parking instance is the last one processed (for all markers).
An alternate approach is to associate a parking instance with the newly added marker and get that instance in the onMarkerClick.
Something like this:
// ... all your code up to this line remains same ....
// Here the `addMarker` method returns the newly added Marker to which we can associate
// any object needed - so associate the "parking" instance...
Marker m = mMap.addMarker(new MarkerOptions().snippet("Owner: " +owner).position(location).title(title));
m.setTag(parking);
Then in your onMarkerClick replace:
parking = documentSnapshot.toObject(Parking.class);
with
// Use the associated Parking object (saved as a tag) to get needed info
Parking p = (Parking) marker.getTag();
if (p == null) {
// some other marker on map
return;
}
String documentId = p.getDocumentId();
String lat = p.getLatitude();
// and any other data I may have missed should come from "p".

Google maps Markers Titles Showing is full list

Im working with google maps project now and im fetching my data from firebase ,im able to plot multiple markers with the help of all the kind developers in this site, one thing is when plotting those markers my markers title are the same , the "same" means that all my markers have the same Title please see my image
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private GoogleMap googleMap;
private MarkerOptions options = new MarkerOptions();
private ArrayList<LatLng> latlngs = new ArrayList<>();
private ArrayList<String> Names = new ArrayList<>();
String Lat ,Lon,Names1;
double latitude , longitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("Positions");
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot chidSnap : dataSnapshot.getChildren()) {
// System.out.println(chidSnap.getKey()); //displays the key for the node
// System.out.println(chidSnap.child("Latitude").getValue());
// System.out.println( chidSnap.child("Longitude").getValue()); //gives the value for given keyname
//some latitude and logitude value
// System.out.println(latlngs); //gives the value for given keyname
Lat = String.valueOf(chidSnap.child("Latitude").getValue());
Lon = String.valueOf(chidSnap.child("Longitude").getValue());
Names1 = String.valueOf(chidSnap.getKey());
latitude= Double.parseDouble(Lat);
longitude= Double.parseDouble(Lon);
latlngs.add(new LatLng(latitude, longitude));
Names.add(Names1);
}
if(mMap != null) {
for (LatLng point : latlngs) {
options.position(point);
options.title(String.valueOf(Names));
options.snippet("someDesc");
mMap.addMarker(options);
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
// System.out.println(Names);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
for (LatLng point : latlngs) {
options.position(point);
options.title(String.valueOf(Names));
options.snippet("someDesc");
googleMap.addMarker(options);
}
}
}
My MapsActivity above. What im expecting is one marker should be named to Lex B05 , and the other user should be amanda thank in advance for your help!..
That because you are passing same arrayList Names to all marker, Try below code while adding marker
for (int i=0;i< latlngs.size();i++) {
LatLng point=latlngs.get(i);
options.position(point);
options.title(Names.get(i));
options.snippet("someDesc");
mMap.addMarker(options);
}
Hope this will help!!

android null pointer exception when adding custom marker [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
When i am trying to add custom marker it throws NullPointerException,
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.model.Marker com.google.android.gms.maps.GoogleMap.addMarker(com.google.android.gms.maps.model.MarkerOptions)' on a null object reference
Here is my map activity
public class GoogleMapActivity extends AppCompatActivity
{
double latitude, longitude;
GoogleMap map;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_google_map);
SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
private void getCurrentLocation()
{
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
//Getting longitude and latitude
longitude = location.getLongitude();
latitude = location.getLatitude();
moveMap();
}
}
private void moveMap()
{
LatLng latLng = new LatLng(latitude, longitude);
map.addMarker(new MarkerOptions()
.position(latLng)
.draggable(true)
.title("Current Location"));
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
map.animateCamera(CameraUpdateFactory.zoomTo(15));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.googlemap, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_search) {
getCurrentLocation();
moveMap();
}
return super.onOptionsItemSelected(item);
}
}
How can i fix this problem?
private void getCurrentLocation()
{
Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (location != null) {
moveMap(location);
}
}
private void moveMap(Location location)
{
longitude = location.getLongitude();
latitude = location.getLatitude();
LatLng latLng = new LatLng(latitude, longitude);
map.addMarker(new MarkerOptions()
.position(latLng)
.draggable(true)
.title("Current Location"));
map.moveCamera(CameraUpdateFactory.newLatLng(latLng));
map.animateCamera(CameraUpdateFactory.zoomTo(15));
}
You don't have latitude and longitude in the scope of function you are trying to access in.
and you are also not implementing onMapReady() function. Seems like a lot of things are broken.
Example: https://github.com/googlemaps/android-samples/blob/master/tutorials/MapWithMarker/app/src/main/java/com/example/mapwithmarker/MapsMarkerActivity.java
public class MapsMarkerActivity extends AppCompatActivity
implements OnMapReadyCallback {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Retrieve the content view that renders the map.
setContentView(R.layout.activity_maps);
// Get the SupportMapFragment and request notification
// when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
}
/**
* Manipulates the map when it's available.
* The API invokes this callback when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user receives a prompt to install
* Play services inside the SupportMapFragment. The API invokes this method after the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap) {
// Add a marker in Sydney, Australia,
// and move the map's camera to the same location.
LatLng sydney = new LatLng(-33.852, 151.211);
googleMap.addMarker(new MarkerOptions().position(sydney)
.title("Marker in Sydney"));
googleMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
}
}

Drawing polylines between two points using an Arraylist of LatLng

I want to draw polylines between two points with using polylineoptions.addAll sending a parameter of ArrayList<LatLng>, but it doesn't show me the result.
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
private ArrayList<LatLng> arrayPoints = new ArrayList<>();
PolylineOptions polylineOptions=new PolylineOptions();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
mMap = ((SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map)).getMap();
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
LatLng point=new LatLng(-35,151);
LatLng point2=new LatLng(-40,151);
polylineOptions.color(Color.RED);
polylineOptions.width(3);
arrayPoints.add(point);
arrayPoints.add(point2);
polylineOptions.addAll(arrayPoints);
}
/**
* Manipulates the map once available.
* This callback is triggered when the map is ready to be used.
* This is where we can add markers or lines, add listeners or move the camera. In this case,
* we just add a marker near Sydney, Australia.
* If Google Play services is not installed on the device, the user will be prompted to install
* it inside the SupportMapFragment. This method will only be triggered once the user has
* installed Google Play services and returned to the app.
*/
#Override
public void onMapReady(GoogleMap googleMap)
{
}
}
Looks like you're not adding the polyline to the map
mMap.addPolyline(polylineOptions)

Categories