I have previously asked the similar question where I had issue with saving the data in the firebase cloud. I managed to store the latitude & longitude data in the firebase database using following code
#Override
public void onMapReady(GoogleMap map) {
mMap = map;
// Use a custom info window adapter to handle multiple lines of text in the
// info window contents.
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
// Return null here, so that getInfoContents() is called next.
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
// Inflate the layouts for the info window, title and snippet.
View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents,
(FrameLayout)findViewById(R.id.map), false);
TextView title = ((TextView) infoWindow.findViewById(R.id.title));
title.setText(marker.getTitle());
TextView snippet = ((TextView) infoWindow.findViewById(R.id.snippet));
snippet.setText(marker.getSnippet());
return infoWindow;
}
});
// Turn on the My Location layer and the related control on the map.
updateLocationUI();
// Get the current location of the device and set the position of the map.
getDeviceLocation();
}
// Gets the current location of the device, and positions the map's camera.
private void getDeviceLocation() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference databaseReference = database.getReference();
Intent intent = getIntent();
callingActivity = intent.getIntExtra( "callingActivity",0 );
//If the map has been called from ScanActivity
if (callingActivity == 1) {
// Get the best and most recent location of the device
if (mLocationPermissionGranted) {
mLastKnownLocation = LocationServices.FusedLocationApi
.getLastLocation( mGoogleApiClient );
scanString = intent.getStringArrayListExtra( "beaconList" );
nameList = intent.getStringArrayListExtra( "nameList" );
addressList = intent.getStringArrayListExtra( "addressList" );
RssiList = intent.getIntegerArrayListExtra( "RssiList" );
for ( int i=0; i < scanString.size(); i++) {
addBeacon.name = nameList.get( i );
addBeacon.address = addressList.get( i );
addBeacon.Rssi = RssiList.get( i );
addBeacon.latitude = mLastKnownLocation.getLatitude();
addBeacon.longitude = mLastKnownLocation.getLongitude();
databaseReference.child( "foo" ).child(addBeacon.address).setValue( addBeacon);
}
}
}
But the problem is when I try to retrieve the location I see is my device's location instead of the saved latlong value in the firebase data base. I have 2 calling activities i.e. 1 is for storing the lat long to firebase and 2 for retrieving it. I can successfully save the value under unique id and update it whereas I am unable to retrieve the latlong. I am using following code for retrieval
else {
DatabaseReference latlong= FirebaseDatabase.getInstance().getReference().child( "foo" ).child( "08:9E:08:B4:57:18" );
mFirebaseDatabase.keepSynced(true);
al ValueEventListener beaconListener = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
LatLng newLocation = new LatLng(
dataSnapshot.child("latitude").getValue(Long.class),
dataSnapshot.child("longitude").getValue(Long.class));
//LatLng mRetrieved = new LatLng(dataSnapshot.getValue(beacon.class).latitude, dataSnapshot.getValue(beacon.class).longitude);
//mLastKnownLocation.setLatitude( dataSnapshot.getValue(beacon.class).latitude );
// mLastKnownLocation.setLatitude(60.192059);
mMap.addMarker( new MarkerOptions()
.position( newLocation)
.title( dataSnapshot.getKey()));
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
databaseReference.addValueEventListener( beaconListener );
Here i am changing the lat long value of 1 particular child name "08:9E:08:B4:57:18" manually in database to check if i can see the marker in the map at that location but it just shows my device's current location.
I can provide further screen shot of my database n the application if required. Thanks in advance. Hope to have some valuable pointers.
Please add this code after adding marker, so that the marker will move to the location which you added
try {
CameraUpdate center = CameraUpdateFactory.newLatLng(new LatLng(lat, lng));
CameraUpdate zoom = CameraUpdateFactory.zoomTo(12);
googleMap.moveCamera(center);
googleMap.animateCamera(zoom);
} catch (Exception e) {
Log.getStackTraceString(e);
}
Related
I was trying to implement a simple search bar in google maps that points the map's camera to the location that is entered in the search box, I've attached the code but whenever I run it, The application ends up crashing. The code is given below. (Also I'm new to Android Development, Please do help me out).
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;
// creating a variable
// for search view.
SearchView searchView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// initializing our search view.
searchView = findViewById(R.id.idSearchView);
// 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);
//***** Searching Part starts from here*********
// adding on query listener for our search view.
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
// on below line we are getting the
// location name from search view.
String location = searchView.getQuery().toString();
// below line is to create a list of address
// where we will store the list of all address.
List<Address> addressList = null;
// checking if the entered location is null or not.
if (location != null || location.equals("")) {
// on below line we are creating and initializing a geo coder.
Geocoder geocoder = new Geocoder(MapsActivity.this);
try {
// on below line we are getting location from the
// location name and adding that location to address list.
addressList = geocoder.getFromLocationName(location, 1);
} catch (IOException e) {
e.printStackTrace();
}
// on below line we are getting the location
// from our list a first position.
Address address = addressList.get(0);
// on below line we are creating a variable for our location
// where we will add our locations latitude and longitude.
LatLng latLng = new LatLng(address.getLatitude(), address.getLongitude());
// on below line we are adding marker to that position.
mMap.addMarker(new MarkerOptions().position(latLng).title(location));
// below line is to animate camera to that position.
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 10));
}
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
return false;
}
});
// at last we calling our map fragment to update.
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;
}
}
}
}
Instead of implementing a SearchView, add the places API from google in your grade file as follows:
implementation 'com.google.android.libraries.places:places:2.3.0'
and use AutocompleteSupportFragment as follows:
try {
if (!Places.isInitialized()) {
Places.initialize(getActivity().getApplicationContext(), GlobalVariables.google_api_key);
}
// Initialize the AutocompleteSupportFragment.
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment) getChildFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);
autocompleteFragment.getView().setBackground(ContextCompat.getDrawable(getContext(), R.drawable.bginfo_whit));
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME, Place.Field.LAT_LNG));
autocompleteFragment.setCountry("ET");
autocompleteFragment.setMenuVisibility(false);
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
LatLng newLatLng = place.getLatLng();
mMap.moveCamera(CameraUpdateFactory.newLatLng(newLatLng));
mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
}
#Override
public void onError(Status status) {
// TODO: Handle the error.
//Log.i(TAG, "An error occurred: " + status);
}
});
}
catch (Exception e)
{}
i am trying to run a geoquery everytime someone select a place from PlaceAutoComplete fragment and show the markers on the map. It is working fine for the first.When i start the app the icons are are all fine the geoquery is running fine, but when i enter a location second time the app crashes showing an error llegalArgumentException: Unmanaged descriptor below is what i am trying to do.
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
SupportPlaceAutocompleteFragment autocompleteFragment =
(SupportPlaceAutocompleteFragment)
getChildFragmentManager().findFragmentById
(R.id.place_autocomplete_fragment);
autocompleteFragment.setOnPlaceSelectedListener(new
PlaceSelectionListener() {
#Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Toast.makeText(getContext(),place.getAddress(),Toast.LENGTH_LONG).show();
Log.i(TAG, "Place: " + place.getName());
Double latitude1 = place.getLatLng().latitude;
Double longitude1 =place.getLatLng().longitude;
LatLng latLng = new LatLng(latitude1,longitude1);
getPeople(latLng); // method to call geofire query
}
#Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i(TAG, "An error occurred: " + status);
}
});
return mMainView;
}
public void getPeople(LatLng latLng1){
mMap.clear();
mMap.addCircle(new CircleOptions()
.center(latLng1)
.radius(2000)
.strokeColor(Color.BLACK)
.fillColor(0x220000FF)
.strokeWidth(1)
);
DatabaseReference ref =
FirebaseDatabase.getInstance().getReference().child("Location");
GeoFire geoFire = new GeoFire(ref);
GeoQuery geoQuery = geoFire.queryAtLocation(new
GeoLocation(latLng1.latitude, latLng1.longitude), 2);
geoQuery.addGeoQueryEventListener(new GeoQueryEventListener() {
#Override
public void onKeyEntered(final String key, GeoLocation location) {
UIDLocation.put(key,location);
marker.setIcon(BitmapDescriptorFactory.fromResource
(R.drawable.ic_mapmarker2));
markers.put(key, marker);
for (Map.Entry<String,GeoLocation> entry : UIDLocation.entrySet())
{
final Marker marker = markers.get(entry.getKey());
if (marker != null) {
DatabaseReference mUser =
FirebaseDatabase.getInstance().getReference().child("People")
.child(string);
mUser.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot)
{
String display_name =
dataSnapshot.child("name").getValue().toString();
String status =
dataSnapshot.child("status").getValue().toString();
String image =
dataSnapshot.child("image").getValue().toString();
PeopleInfo info = new PeopleInfo();
info.setName(display_name);
info.setStatus(status);
info.setImage(image);
marker.setTag(info);
String iconName = dataSnapshot.child("iconName")
.getValue().toString();
Context context = getContext();
int id = context.getResources().getIdentifier(iconName, "drawable",
context.getPackageName());
String s = String.valueOf(id);
Bitmap icon = BitmapFactory.decodeResource(context.getResources(),id);
marker.setIcon(BitmapDescriptorFactory.fromResource(id));
}
#Override
public void onCancelled(DatabaseError
databaseError) {
}
});
}
}
#Override
public void onMapReady(final GoogleMap googleMap) {
mMap = googleMap;
mUiSettings = mMap.getUiSettings();
mUiSettings.setZoomControlsEnabled(true);
mFusedLocationClient =
LocationServices.getFusedLocationProviderClient(getContext());
Task task= mFusedLocationClient.getLastLocation()
.addOnSuccessListener(getActivity(), new
OnSuccessListener<Location>() {
#Override
public void onSuccess(Location location) {
if (location != null) {
double latitude = location.getLatitude();
double longitude = location.getLongitude();
LatLng latLng = new LatLng(latitude, longitude);
myPosition = new LatLng(latitude, longitude);
markeroptn = new MarkerOptions();
markeroptn.position(myPosition);
markeroptn.title("You are Here");
mMap.moveCamera(CameraUpdateFactory.newLatLng(myPosition));
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(myPosition,10));
getWorkMen(myPosition);
}
}
});
So far what i have learned from the posts on SO that its because the program is trying to set the icon on marker which is already there. I tried clear() map in the begining of getPeople() but still it is showing the same error.It works fine first time. i also tried remove() also but its also not working.
The problem may come from the way you manage the Marker variables. In the code, you store a marker variable as global outside of the method scope. When calling map.clear(), it makes the marker variable invalid and if somehow you still use this variable to set something, it may cause the exception. The same thing happens with the markers Map you use to map key and Marker, it's not being cleared when map.clear().
Try to manage your map elements more carefully, clear each map element dependently and avoid using map.clear().
Suggestion approach:
Create new marker
private void addMarker(String key, LatLng latLng) {
// Clear the current marker before add the new one
if (marker != null) {
marker.remove();
marker = null;
}
// Store new marker to the variable
marker = mMap.addCircle(new CircleOptions()
.center(latLng)
.radius(2000)
.strokeColor(Color.BLACK)
.fillColor(0x220000FF)
.strokeWidth(1)
);
// Add to markers map if needed
markers.put(key, marker);
}
Clear all markers (clear manually every marker variable available, don't use map.clear:
public synchronized void clear() {
// markers is the marker map
for (Marker marker : markers.values()) {
try {
marker.remove();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
}
// Clear all the marker map
markers.clear();
// Marker is the your global marker variable
marker.remove();
}
I am developing an app which has an activity having map in it. When users open this activity from their devices, their current location coordinates is saved in the Firebase and then are retrieved instantly and a marker is shown on their current location. This procedure is happening successfully.
Here's how I'm retrieving the latitude and longitude from firebase:
acceptingUserReference.child(requestID).child(key).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot.getValue() != null) {
final Map<String, String> newAcceptedUser = (Map<String, String>) dataSnapshot.getValue();
nameOfP.add(newAcceptedUser.get("pName"));
cLatP.add(newAcceptedUser.get("cLat").trim());
cLngP.add(newAcceptedUser.get("cLng").trim());
currentLat.add(newAcceptedUser.get("currentLat").trim());
currentLng.add(newAcceptedUser.get("currentLng").trim());
addMarkers();
//Check map is loaded
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
#Override
public void onMapLoaded() {
mMap.getUiSettings().setZoomControlsEnabled(true);
mMap.getUiSettings().setMapToolbarEnabled(true);
mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
mMap.setMaxZoomPreference(19.0f); mMap.setMyLocationEnabled(true);
}
});
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
Here's how:
public void addMarkers() {
mMap.clear();
venueMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.parseDouble(venueLat), Double.parseDouble(venueLng)));
markersList.add(venueMarker);
for (int i = 0; i < nameOfP.size(); i++) {
p = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.valueOf(cLatP.get(i)), Double.valueOf(cLngP.get(i)))).title(nameOfP.get(i).trim()).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
markersList.add(pMarker);
}
}
The problem arises when I the users moves and their location changes. Now, I want to remove the marker from their previous location and show it on their updated current location. For doing this, I'm using LocationRequest to get location and then saving the updated location in Firebase.
Here's how:
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
currentLtAU = mCurrentLocation.getLatitude();
currentLnAU = mCurrentLocation.getLongitude();
aReference.child(rID).child(userID).child("currentLat").setValue(String.valueOf(currentLtAU));
aReference.child(rID).child(userID).child("currentLng").setValue(String.valueOf(currentLnAU));
updateMarkers();
}
Now, to update markers based on this updated location, I'm trying this:
public void updateMarkers() {
mMap.clear();
venueMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.parseDouble(venueLat), Double.parseDouble(venueLng)));
markersList.add(venueMarker);
for (int i = 0; i < nameOfP.size(); i++) {
p = mMap.addMarker(new MarkerOptions().position(new LatLng(Double.valueOf(currentLat.get(i)), Double.valueOf(currentLng.get(i)))).title(nameOfP.get(i).trim()).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED)));
markersList.add(pMarker);
}
}
but on doing this, many markers are getting added and also the app is getting crashed giving this error: java.lang.IndexOutOfBoundsException: Invalid index 2, size is 2 and also addMarkers() gets called everytime.
Please help me to figure out what is going wrong here and how to achieve what I want.
I have some questions of CameraUpdateFactory.
Q1 :
I am trying to do a function that when i click the button it executes function "mapList()"
My "mapList()" is just to change my camera position. // run successfully but not work!!!!
So I use the Google Map API's functions.
My code below -> mapList()
public void mapList(View view) {
Intent intentMap = new Intent(this, MapsActivity.class);
// start map component
LatLng tagCYCU = new LatLng(24.956867, 121.242846);
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(tagCYCU)
.zoom(17)
.build();
CameraUpdateFactory.newLatLng(tagCYCU) ;
CameraUpdateFactory.newCameraPosition(cameraPosition) ;
startActivityForResult(intentMap, 0);
}
Q2 :
In my Maps activity, I want to try to read the informations from other fragments.Because I need it to do something. ( also change camera position )
So I do this code , but always "ERROR" // null object
My code below -> MapsActivity()
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
TextView getTextAddress ;
Spinner getName ;
String addrRestaurant = "", nameRestaurant = "" ;
private GoogleMap mMap;
private GoogleApiClient googleApiClient;
// Location
private LocationRequest locationRequest;
private Location currentLocation;
private Marker currentMarker, itemMarker;
#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(map);
mapFragment.getMapAsync(this);
}
/**
* 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;
// ------------------------------- Get current location ---------------------------------
LocationManager locationManager = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, android.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;
}
Location location = locationManager.getLastKnownLocation(locationManager
.getBestProvider(criteria, false));
double currentLatitude = location.getLatitude();
double currentLongitude = location.getLongitude();
LatLng currentHere = new LatLng(currentLatitude,currentLongitude) ;
mMap.addMarker(new MarkerOptions().position(currentHere).title("Current Here"));
// --------------------------------------------------------------------------------------
// ---------------------------- Tag all restaurants from SQLite--------------------------
String addrRestaurant = "" ;
getTextAddress = (TextView)findViewById(R.id.textViewAddress);
// what i get , camera change to that position
// bur textViewAddress is in other fragments !!
addrRestaurant = getTextAddress.getText().toString();
DBHelper dbHelper = new DBHelper(this);
SQLiteDatabase db = dbHelper.getReadableDatabase();
String selectQuery = "SELECT " +
Restaurant.KEY_ID + "," +
Restaurant.KEY_name + "," +
Restaurant.KEY_type + "," +
Restaurant.KEY_price + "," +
Restaurant.KEY_phone + "," +
Restaurant.KEY_addr + "," +
Restaurant.KEY_score +
" FROM " + Restaurant.TABLE;
Cursor cursor = db.rawQuery(selectQuery, null);
int sizeDB = (int) DatabaseUtils.queryNumEntries(db, "Restaurant");
String infoAddress = "", infoName = "" ;
for( int indexDB = 0 ; indexDB < sizeDB ; indexDB ++ ) {
cursor.moveToPosition(indexDB);
infoName = cursor.getString(cursor.getColumnIndex(Restaurant.KEY_name));
infoAddress = cursor.getString(cursor.getColumnIndex(Restaurant.KEY_addr)) ;
Geocoder geoCoder = new Geocoder(this);
List<Address> addressLocation ;
try {
addressLocation = geoCoder.getFromLocationName(infoAddress, 1);
double latitude = addressLocation.get(0).getLatitude();
double longitude = addressLocation.get(0).getLongitude();
LatLng tag = new LatLng(latitude, longitude);
addMarker(tag, "Foody Restaurants",infoName ); // get mark !
if(addrRestaurant.equals(infoAddress) == true){
// change camera position according to what i get fom other activity
mMap.moveCamera(CameraUpdateFactory.newLatLng(tag));
moveMap(tag);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
// --------------------------------------------------------------------------------------
}
private void moveMap(LatLng place) {
CameraPosition cameraPosition =
new CameraPosition.Builder()
.target(place)
.zoom(17)
.build();
mMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
private void addMarker(LatLng place, String title, String snippet) {
BitmapDescriptor icon =
BitmapDescriptorFactory.fromResource(R.mipmap.ic_tag);
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.position(place)
.title(title)
.snippet(snippet)
.icon(icon);
mMap.addMarker(markerOptions);
}
Locat
Process: com.example.user.foody, PID: 2896
java.lang.NullPointerException:
Attempt to invoke virtual method 'java.lang.CharSequence android.widget.TextView.getText()' on a null object reference
at com.example.user.foody.MapsActivity.onMapReady(MapsActivity.java:121)
MapsActivity.java:121 -> ( addrRestaurant = getTextAddress.getText().toString(); )
at com.google.android.gms.maps.SupportMapFragment$zza$1.zza(Unknown Source)
I really need help !! Please :( thank you ..
You can check this sample on GitHub on how to change the camera position for the map. This code snippet runs when the Animate To Sydney button is clicked.
public void onGoToSydney(View view) {
if (!checkReady()) {
return;
}
changeCamera(CameraUpdateFactory.newCameraPosition(SYDNEY), new CancelableCallback() {
#Override
public void onFinish() {
Toast.makeText(getBaseContext(), "Animation to Sydney complete", Toast.LENGTH_SHORT)
.show();
}
#Override
public void onCancel() {
Toast.makeText(getBaseContext(), "Animation to Sydney canceled", Toast.LENGTH_SHORT)
.show();
}
});
}
Regarding Fragments, check the documentation about adding a Fragment object to the Activity that will handle the map.
Check this SO post on how to fix and what are the possible causes of the NullPointerException.
"The best way to avoid this type of exception is to always check for null when you did not create the object yourself." If the caller passes null, but null is not a valid argument for the method, then it's correct to throw the exception back at the caller because it's the caller's fault.
I have this code that is working exactly as I want. I mean I have a map fragment that displays 5 marker category, I can filter them as I want by category and everything works fine. As you might observe marker 1 and marker 8 will appear in more than one category. Here is the code and I will continue my problem afterwards:
Boolean mSetCameraPosition;
Boolean checkBox1Checked, checkBox2Checked, checkBox3Checked, checkBox4Checked, checkBox5Checked;
private int mapTypeSelected;
CheckBox cbAllDay, cbBefore12, cbBetween1216, cbBetween1620, ccbAfter20;
AlertDialog dialog;
List<Marker> firstCategoryList = new ArrayList<>();
List<Marker> secondCategoryList = new ArrayList<>();
List<Marker> thirdCategoryList = new ArrayList<>();
List<Marker> fourthCategoryList = new ArrayList<>();
List<Marker> fifthCategoryList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
checkLocationPermission();
}
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
if (savedInstanceState == null) {
mapTypeSelected = GoogleMap.MAP_TYPE_NORMAL;
mSetCameraPosition = true;
} else {
mapTypeSelected = savedInstanceState.getInt("the_map_type", GoogleMap.MAP_TYPE_NORMAL);
mSetCameraPosition = false;
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
if (mSetCameraPosition) {
initialLocation(TOULOUSE_LAT, TOULOUSE_LNG, 12);
}
mMap.setMapType(mapTypeSelected);
if (initialMarkers) {
addMarkers2Map();
}
public void addMarkers2Map() {
// Markers location
LatLng marker1 = new LatLng(43.607044, 1.450307);
LatLng marker2= new LatLng(43.571505, 1.417759);
LatLng marker3= new LatLng(43.607469, 1.447162);
LatLng marker4= new LatLng(43.600723, 1.455917);
LatLng marker5= new LatLng(43.604892, 1.476562);
LatLng marker6= new LatLng(43.604496, 1.474924);
LatLng marker7= new LatLng(43.604781, 1.474502);
// Markers All day long
firstCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker1).title("First Place ").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 8.30 - 22.30")));
// Markers Before 12 PM
secondCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker2).title("Second Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 10.30 - 11.30")));
// Markers Between 12-16
thirdCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker3).title("Third Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.30 - 16.30")));
thirdCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker4).title("Fourth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.00 - 16.00")));
// Markers Between 16-20
fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker5).title("Fifth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 15.30 - 16.30")));
fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker6).title("Sixth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 16.30 - 17.30")));
fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker7).title("Seventh Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 18.30 - 19.30")));
fourthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker8).title("Eighth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 17.30 - 18.30\nHH:21.30 - 22.30")));
// Markers After 20
fifthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker8).title("Eighth Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 17.30 - 18.30\nHH:21.30 - 22.30")));
fifthCategoryList.add(mMap.addMarker(new MarkerOptions().position(marker1).title("First Place").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 8.30 - 22.30")));
public void filterTheMarkers(View view) {
if (dialog == null){
AlertDialog.Builder builder;
builder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
#SuppressLint("InflateParams") View checkBoxView = inflater.inflate(R.layout.markers_filtering, null);
builder.setView(checkBoxView);
cbAllDay = (CheckBox) checkBoxView.findViewById(R.id.checkBox1);
if (checkBox1Checked != null) {
cbAllDay.setChecked(checkBox1Checked);
}
cbBefore12 = (CheckBox) checkBoxView.findViewById(R.id.checkBox2);
if (checkBox2Checked != null) {
cbBefore12.setChecked(checkBox2Checked);
}
cbBetween1216 = (CheckBox) checkBoxView.findViewById(R.id.checkBox3);
if (checkBox3Checked != null) {
cbBetween1216.setChecked(checkBox3Checked);
}
cbBetween1620 = (CheckBox) checkBoxView.findViewById(R.id.checkBox4);
if (checkBox4Checked != null) {
cbBetween1620.setChecked(checkBox4Checked);
}
ccbAfter20 = (CheckBox) checkBoxView.findViewById(R.id.checkBox5);
if (checkBox5Checked != null) {
ccbAfter20.setChecked(checkBox5Checked);
}
dialog = builder.create();
}
dialog.show();
}
public void displaySelectedMarkers(View view) {
dialog.dismiss();
Log.i("TAG", "All Day " + cbAllDay.isChecked() + " Before 12 " + cbBefore12.isChecked() + " Between 12-16 " + cbBetween1216.isChecked() + " Between 16-20" + cbBetween1620.isChecked() + " After 20 " + ccbAfter20.isChecked());
//according these check boxes status execute your code to show/hide markers
if (cbAllDay.isChecked() && cbBefore12.isChecked() && cbBetween1216.isChecked() && cbBetween1620.isChecked() && ccbAfter20.isChecked()) {
// show all markers
for (Marker marker : firstCategoryList) {
marker.setVisible(true);
}
for (Marker marker : secondCategoryList) {
marker.setVisible(true);
}
for (Marker marker : thirdCategoryList) {
marker.setVisible(true);
}
for (Marker marker : fourthCategoryList) {
marker.setVisible(true);
}
for (Marker marker : fifthCategoryList) {
marker.setVisible(true);
}
} else if (cbAllDay.isChecked() && !cbBefore12.isChecked() && !cbBetween1216.isChecked() && !cbBetween1620.isChecked() && !ccbAfter20.isChecked()) {
// show only All Day Markers
for (Marker marker : firstCategoryList) {
marker.setVisible(true);
}
for (Marker marker : secondCategoryList) {
marker.setVisible(false);
}
for (Marker marker : thirdCategoryList) {
marker.setVisible(false);
}
for (Marker marker : fourthCategoryList) {
marker.setVisible(false);
}
for (Marker marker : fifthCategoryList) {
marker.setVisible(false);
}
}
//....and it goes like this for a while until I finish all the possibilities
Now what I want to do is open a new activity for every markers info window clicked so the solution that I found is to add all the markers to a HashMap and give a name for every marker so that I can add it to the HashMap and to the ArrayList, like this:
private Map<Marker, Class> allMarkersMap = new HashMap<>();
Marker markerMarker1 = mMap.addMarker(new MarkerOptions().position(marker1).title("BAR ACASA").icon(BitmapDescriptorFactory.fromResource(R.drawable.beer_marker)).snippet("HH: 8.30 - 22.30"));
firstCategoryList.add(markerMarker1);
allMarkersMap.put(markerMarker1, Marker1.class);
Now on onMapReady I am adding this code and I create a class for every marker Marker1.java, Marker2.java.....:
mMap.setOnInfoWindowClickListener(MyOnInfoWindowClickListener);
GoogleMap.OnInfoWindowClickListener MyOnInfoWindowClickListener = new GoogleMap.OnInfoWindowClickListener() {
#Override
public void onInfoWindowClick(Marker marker) {
Class cls = allMarkersMap.get(marker);
Intent intent = new Intent(MainActivity.this, cls );
startActivity(intent);
}
};
Everything works fine for the markers that appear only in one category, but for the ones that are in more than one category the filter is not working anymore, displaying only the markers that were last added to the HashMap(hopefully you understand what I am saying here).
So, can I do this and still have my filter functioning? As I am imagining that what is happening is the fact that once I define a marker and put it in the Arraylist it moves the marker there, and afterwards when I put it in the HashMap it moves it again to the HashMap so when I filter for arraylists the marker is not in the list anymore...
What would be the best solution for my info window opening a different activity for each marker displayed?
I won't write to much code for my solution because I think it would be better for you to write it and I think the idea behind it is more important than the code itself.
First of all, a small suggestion for you, whenever you start developing UI things that display information, try to find a generic description or a rule that describes the information that will be displayed. When you found that rule/description it means you found a model class.
I strongly suggest to use custom classes created by you that hold information required for your UI.
Now back to your example, from what I understand, you have markers that would be added to a category and based on that category you display them on the map.
What I would do I would create a custom class, called let's say MyAwesomeMarker that has a Marker member and a ArrayList<String> category.
Something like this:
public class MyAwesomeMarker {
private Marker mMarker;
private List<String> mMarkerCategories; // here you can mark if a marker is in more than one categories.
// constructors
public MyAwesomeMarker(Marker marker, String category) {
mMarker = marker;
mMarkerCategories = new ArrayList<String>();
mMarkerCategories.add(category);
}
public void addNewCategory(String category) {
if(category != null && !mMarkerCategorie.contains(category)) {
mMarkerCategories.add(category);
}
}
public void toggleMarkerIfHasCategory(String theCategory) {
for(String category : mMarkerCategories) {
if(category.equals(theCategory) {
marker.setVisible(true);
}
else {
marker.setVisible(false);
}
}
}
// setters getters
}
Then in your main class I would have a list of MyAwesomeMarker, let's call it myMarkers
Now you want to display all the markers that are in a category named awesomness.
for(MyAwesomeMarker marker : myMarkers) {
marker.toggleMarkerIfHasCategory("awesomness");
}
Now the only thing you have to do, is generate your lit of custom markers and you're done.