Toast name and distance of city closest to center of map - java

I'm creating a map of some cities in Sweden and would like some functionality added to it. I would like to display the city name and the distance in kilometers of the city closest to the center of the map, where I have placed a crosshairs through an ImageView in my layout XML file. Is there a proper way of accomplishing this?
This is the code I'm currently using to create my map and place my city markers:
public class MyMap extends Activity implements OnMapReadyCallback
{
public final Context context = this;
private String fileString = "";
private String coordsFileName = "coords";
private GoogleMap myMap = null;
private LatLngBounds bounds = null;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_map);
// Gets the map fragment from the xml file
MapFragment mapFragment = (MapFragment) getFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// Load strings from file
fileString = ReadFromFile(coordsFileName);
}
#Override
public void onMapReady(GoogleMap map)
{
myMap = map;
List<Marker> markers = new ArrayList<Marker>();
String[] locations = fileString.split(";");
for (String location : locations)
{
try
{
String[] cityLatLng = location.split(":|,");
String cityName = cityLatLng[0];
Double lat = Double.parseDouble(cityLatLng[1]);
Double lng = Double.parseDouble(cityLatLng[2]);
LatLng cityPos = new LatLng(lat, lng);
// Create marker
Marker marker = myMap.addMarker(new MarkerOptions()
.position(cityPos)
.title(cityName));
// Add new marker to array of markers
markers.add(marker);
}
catch(Exception e)
{
System.out.println("Error 3: " + e.getMessage());
}
}
// Move the camera to show all markers
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers)
{
builder.include(marker.getPosition());
}
bounds = builder.build();
myMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback()
{
#Override
public void onMapLoaded()
{
// Pixel offset from edge of map
int padding = 30;
// Move the camera
myMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, padding));
}
});
}
}
And this is my layout xml file:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<fragment
android:id="#+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.google.android.gms.maps.MapFragment"/>
<ImageView
android:id="#+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_action_locate"
android:layout_gravity="center_vertical"
android:layout_centerInParent="true"
android:contentDescription="#string/crosshairs"/>
</RelativeLayout>

One of the probable solution is to first find the center coordinates of the map by using
map.getCenter();
This will return the latlang object. Then you can compare the distance of the center with each of the position markers (that represents cities) using the Google Distance Matrix API, find out the min by using a minDist() method and return the coordinates of marker at minimum distance (which is the name of the city)
Hope that would help!!!

I actually managed to solve it using Location objects and GoogleMap.setOnCameraChangeListener() to recalculate each time the user navigates the map. Below is the code I managed to put together to achieve this.
myMap.setOnCameraChangeListener(new OnCameraChangeListener()
{
#SuppressLint("DefaultLocale") #Override
public void onCameraChange(CameraPosition position)
{
// Get the latlng of the map center
LatLng mapCenter = myMap.getCameraPosition().target;
// Create a centerlocation based on the map's latlng
Location centerLocation = new Location("CenterLocation");
centerLocation.setLatitude(mapCenter.latitude);
centerLocation.setLongitude(mapCenter.longitude);
// Location for storage of the city closest to the map
Location closestCity = new Location("ClosestCity");
float distance = 0;
for (City city : cities)
{
Location cityLocation = new Location(city.getCityName());
cityLocation.setLatitude(city.getLatitude());
cityLocation.setLongitude(city.getLongitude());
float currentCityDistance = cityLocation.distanceTo(centerLocation);
if(distance == 0)
{
distance = currentCityDistance;
closestCity = cityLocation;
}
if(currentCityDistance < distance)
{
distance = currentCityDistance;
closestCity = cityLocation;
}
}
// Convert from meters to kilometers
float distanceKm = distance / 1000;
String kilometersString = String.format("%.2f", distanceKm);
// Present a toast with information
Toast.makeText(getBaseContext(), "Distance to " + closestCity.getProvider() + ": " + kilometersString + " km", Toast.LENGTH_SHORT).show();
}
});

Related

Android: Here maps sdk's map is showing not accurate coordinates

I am using the HERE Maps Lite SDK for Android as a library in my project.
I want to show MapView, and add overlays of all shelters I have in my database, in their specific coordinates.
The map works well, but the shown coordinates are not accurate. I tried to geocode the coordinates in lat-long website, and they are correct, but in the map they are shown right to their real location.
My code:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shelters_map);
mapView = findViewById(R.id.mapview);
mapView.onCreate(savedInstanceState);
ActivityCompat.requestPermissions(SheltersMapActivity.this, new String[] {
Manifest.permission.ACCESS_FINE_LOCATION}, 123);
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Permission is not granted
Toast.makeText(getApplicationContext(), "אנא אפשר גישה לשירותי מיקום", Toast.LENGTH_SHORT).show();
ActivityCompat.requestPermissions(this,
new String[]{ACCESS_FINE_LOCATION},
1);
} else // premission is granted
{
GPStracker g = new GPStracker(getApplicationContext());
userLocation = g.getLocation();
}
loadMapScene();
addSheltersOverlay();
// loadMapScene();
}
private void loadMapScene() {
// Load a scene from the SDK to render the map with a map style.
mapView.getMapScene().loadScene(MapStyle.NORMAL_DAY, new MapScene.LoadSceneCallback() {
#Override
public void onLoadScene(#Nullable MapScene.ErrorCode errorCode) {
if (errorCode == null) {
mapView.getCamera().setTarget(new GeoCoordinates(userLocation.getLatitude(),
userLocation.getLongitude()));
mapView.getCamera().setZoomLevel(15);
} else {
Log.d("data1", "onLoadScene failed: " + errorCode.toString());
}
}
});
}
private void addSheltersOverlay() {
db = new DatabaseHandler(this);
ArrayList<Shelter> places = this.db.getAllPlaces();
Shelter userLocationPlace = new Shelter("המיקום שלך", "", userLocation, null, 0, "");
places.add(userLocationPlace);
int size = places.size();
for(int i = 0; i < size; i++) {
TextView textView = new TextView(this);
textView.setTextColor(Color.parseColor("#FFFFFF"));
textView.setText(places.get(i).getName());
LinearLayout linearLayout = new LinearLayout(this);
if (places.get(i) instanceof Basement)
linearLayout.setBackgroundColor(Color.BLACK);
else if (places.get(i) instanceof Stairs)
linearLayout.setBackgroundColor(Color.GREEN);
else
linearLayout.setBackgroundColor(Color.BLUE);
linearLayout.setPadding(10, 10, 10, 10);
linearLayout.addView(textView);
GeoCoordinates geoCoordinates = new GeoCoordinates(places.get(i).getLocation().getLatitude(),
places.get(i).getLocation().getLongitude());
MapOverlay<LinearLayout> mapOverlay = new MapOverlay<>(linearLayout, geoCoordinates);
mapView.addMapOverlay(mapOverlay);
}
}
The shown map:
.
I can see the streets names in the shown map itself, and I see that it is not the accurate point.
Anybody help?
From the code it looks correct, but I cannot see the location vs. the expected location. By default, MapOverlays are drawn centered on the coordinates. You can set an anchor point to move the overlay in relation to the coordinates. This could help if there is always an offset between the coordinates in your database and the location on the map.
Maybe, can you try to render a small MapCircle item onto the map at the expected location? Then you can more easily see where that location lies on the map. You can compare the results with https://www.latlong.net/.

How to read a txt file in android studio?

I have a text file speedVan.txt in my assets folder in android studio which stores coordinates, However when I run it the markers do not appear on the map. My code is below, thank you.
This is the content of the text file, there are no spaces between the text lines:
52.2651 -9.7112 52.2791 -9.7024
52.2800 -9.7675 52.2746 -9.8096
52.1407 -10.1748 52.1296 -10.2493
52.0724 -9.5753 52.1005 -9.6231
52.1021 -9.6276 52.1065 -9.6425
52.0812 -9.2470 52.0542 -9.3850
52.1134 -9.5169 52.1437 -9.5543
52.4096 -9.5167 52.4208 -9.5078
52.4428 -9.4105 52.4491 -9.4474
This is my activity:
public class MapsActivity extends FragmentActivity implements OnMapReadyCallback {
private GoogleMap mMap;
#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);
}
#Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(getAssets().open("speedVan.txt")));
String line;
//Log.e("Reader Stuff",reader.readLine());
while ((line = reader.readLine()) != null) {
Log.e("code",line);
String[] ar1 = line.split(" ");
double startLat = Double.parseDouble(ar1[0]);
double startLong = Double.parseDouble(ar1[1]);
double endLat = Double.parseDouble(ar1[2]);
double endLong = Double.parseDouble(ar1[3]);
LatLng start = new LatLng(startLat, startLong);
LatLng end = new LatLng(endLat, endLong);
mMap.addMarker(new MarkerOptions().position(start).title(""));
mMap.addMarker(new MarkerOptions().position(end).title(""));
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(start,14));
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Change SupportMapFragment to MapFragment. Something like this
MapFragment mapFragment = (MapFragment) getFragmentManager() .findFragmentById(R.id.map);
Please remove the ;; that you have used and put a single ;
And instead of:
int startLat = Integer.parseInt(ar1[0]);
int startLong = Integer.parseInt(ar1[1]);;
int endLat = Integer.parseInt(ar1[2]);;
int endLong = Integer.parseInt(ar1[3]);;
Please put:
double startLat = Double.parseDouble(ar1[0]);
double startLong = Double.parseDouble(ar1[1]);
double endLat = Double.parseDouble(ar1[2]);
double endLong = Double.parseDouble(ar1[3]);
We are using double because the constructor of LatLng takes two double arguements.
And please note that because of your first statement Log.e("Reader Stuff",reader.readLine()); the first line of the text file will not be parsed because a line is being read and logged and the next time you call reader.readLine(), you will get the second line.
Edit:
Maybe you are not able to see the markers because you haven't moved the map camera. To move the camera to any marker:
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(start,14));
start is the LatLng and 14 is the Zoom level.

How to clear polyline when tap on another marker

I am creating an app and i am drawing a route from current marker to nearby markers. when i tap on nearby marker it created a route, and when i again tap on another marker previous route still show. so i want to remove the previous route and draw a new route from current marker to nearby marker. Please help me using my source code....
mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
#Override
public View getInfoWindow(Marker arg0) {
return null;
}
#Override
public View getInfoContents(Marker marker) {
//for direction Route
if(CurrentMarker != null) {
LatLng origin = CurrentMarker.getPosition();
LatLng dest = marker.getPosition();
String url = getDirectionsUrl(origin, dest);
DownloadPar downloadPar = new DownloadPar();
// Start downloading json data from Google Directions API
downloadPar.execute(url);
}
View myContentsView = getLayoutInflater().inflate(R.layout.details, null);
TextView tvTitle = ((TextView)myContentsView.findViewById(R.id.title));
tvTitle.setText(marker.getTitle());
TextView tvSnippet = ((TextView)myContentsView.findViewById(R.id.snippet));
tvSnippet.setText(marker.getSnippet());
return myContentsView;
}
});
Please help me...
Thanks
Declare a variable:
private Polyline polyline;
Then in your method when you initially add the Polyline to the Map:
polyline = mMap.addPolyline(lineOptions);
Then when you want to update the Polyline I believe you can use:
polyline.setPoints(newPoints);
Otherwise, remove the polyline by calling polyline.setMap(null) and create a new one like you have done above.
For more information regarding Polyline, see the documentation
protected void onPostExecute(List>> result) {
ArrayList points = null;
PolylineOptions lineOptions = null;
// MarkerOptions markerOptions = new MarkerOptions();
//markerOptions.position(latLng);
// markerOptions.title("Find Location");
// markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED));
// FindMarker = mMap.addMarker(markerOptions);
// Traversing through all the routes
for (int i = 0; i < result.size(); i++) {
points = new ArrayList<LatLng>();
lineOptions = new PolylineOptions();
// Fetching i-th route
List<HashMap<String, String>> path = result.get(i);
// Fetching all the points in i-th route
for (int j = 0; j < path.size(); j++) {
HashMap<String, String> point = path.get(j);
double lat = Double.parseDouble(point.get("lat"));
double lng = Double.parseDouble(point.get("lng"));
LatLng position = new LatLng(lat, lng);
points.add(position);
}
// Adding all the points in the route to LineOptions
lineOptions.addAll(points);
lineOptions.width(8);
lineOptions.color(Color.GRAY);
}
// Drawing polyline in the Google Map for the i-th route
mMap.addPolyline(lineOptions);
}
}

How To Use ClickListener for Starting Marker position in Android Studio?

This application purposed to get the distance from 2 points of coordinate. The ways is just to click in the map of the position place that you want to count the distance. But there's problem in the point's start, where the application cannot changes the position place.
this is my code:
public class MapsActivity extends FragmentActivity {
// the Google Map object
private GoogleMap mMap;
//ArrayList markerPoints;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// we set the layout for the Activity
setContentView(R.layout.activity_maps);
// the geocoder is instantiated for the first time
geocoder=new Geocoder(this);
// if there isn't a map, it will be created
setUpMapIfNeeded();
}
// LatLng objects store a pair of terrestrial coordinates (latitude and longitude)
private static LatLng STARTING_MARKER_POSITION =new LatLng(3.099465, 101.717111);
/* distanceFrom indicates the starting point to calculate the distance from.
It's initialized with STARTING_MARKER_POSITION
*/
private LatLng distanceFrom= STARTING_MARKER_POSITION;
// line will be drawn at the click event
private Polyline line=null;
// A Geocoder can transform a pair of latitude/longitude into a street address and viceversa.
// We'll use it in the listener
private static Geocoder geocoder=null;
private GoogleMap.OnMapClickListener clickListener=new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(final LatLng pos) {
// this method is called when the user taps the map
// if a line already appears, it's removed
if (line!=null)
line.remove();
// a new line is created
line = mMap.addPolyline(new PolylineOptions()
.add(distanceFrom, pos)
.width(9) // width of the line
.color(Color.BLUE)); // line color
// call the converter object for geocoding invocation and distance calculation
new AddressConverter().execute(distanceFrom, pos);
}
};
#Override
protected void onResume() {
super.onResume();
// the availability of the GoogleMap will be checked before the Activity starts interacting with the user
setUpMapIfNeeded();
}
private void setUpMapIfNeeded() {
// the map is created only it has not been initialized
if (mMap == null) {
// the map is located in the layout
mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
// if a map exists, we proceed with initialization
if (mMap != null) {
setUpMap();
}
}
}
// Now it's time to configure the map. We can add markers, shapes, event handlers and so on
private void setUpMap() {
// the camera will be positioned according to the new coordinates
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(STARTING_MARKER_POSITION, 14));
// we choose the type of the map: Satellite in this case
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
// markerOptions describes the marker we want to place
MarkerOptions markerOptions=new MarkerOptions()
.position(STARTING_MARKER_POSITION)
.draggable(true);
// the marker has to be draggable as we'll move it
// the marker is rendered on the map
mMap.addMarker(markerOptions);
// we define the object to invoke when the marker is dragged
mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener()
{
#Override
public void onMarkerDragStart(Marker arg0)
{
// this method is called when the drag starts
// the operation we need is the cancellation of a preexisting line
if (line!=null)
line.remove();
}
#Override
public void onMarkerDragEnd(final Marker pos)
{
// we get the final position of the marker
distanceFrom=pos.getPosition();
}
#Override
public void onMarkerDrag(Marker arg0)
{
// operations performed during the movement. Nothing to do
}
});
// the callback to invoke is set
mMap.setOnMapClickListener(clickListener);
}
// we want to know which address corresponds to this location
// we use AsyncTask to perform slower operations on a separate thread
private class AddressConverter extends AsyncTask<LatLng,Void,String>
{
// The ProgressDialog window we'll show during the calculation
private ProgressDialog progress=null;
// this method is called before the background job starts. It works on the main thread
#Override
protected void onPreExecute() {
// ProgressDialog is shown
progress= ProgressDialog.show(MapsActivity.this,"Distance calculator","We are calcultating the distance...", true,false);
}
// this method works on a separate thread
// it performs geocoding operations to retrieve the address of the points and calculates the distance in meters between them
#Override
protected String doInBackground(LatLng... params) {
float[] distance=new float[1];
try {
// the Location class contains what we need to calculate distances
Location.distanceBetween(params[0].latitude,params[0].longitude,params[1].latitude,params[1].longitude,distance);
// geocoding operations
List<Address> fromResult=geocoder.getFromLocation(params[0].latitude,params[0].longitude,1);
List<Address> toResult=geocoder.getFromLocation(params[1].latitude,params[1].longitude,1);
// the message informs the user about the distance from the marker to the point selected with the click
// if we have got both the addresses, we use them to compose the message, otherwise we show only the distance
if (fromResult.size()>0 && toResult.size()>0)
{
// ((TextView) findViewById(R.id.tvDuration)).setText(route.duration.text);
return "The distance between " + getAddressDescription(fromResult.get(0)) + " and " + getAddressDescription(toResult.get(0)) + " is " + Math.round(distance[0]) + " meters";
}
else
return "The distance is " + Math.round(distance[0]) + " meters";
}
catch (IOException e) {
return "The distance is " + Math.round(distance[0]) + " meters";
}
}
#Override
protected void onPostExecute(String message)
{
if (progress!=null)
progress.dismiss();
// The builder of the window is instantiated
AlertDialog.Builder builder=new AlertDialog.Builder(MapsActivity.this);
builder.setTitle("Distance");
builder.setMessage(message);
// the Alert dialog appears
builder.show();
}
}
// this method only formats the message with addresses
private String getAddressDescription(Address a)
{
String city=a.getLocality();
String address=a.getAddressLine(0);
return "'"+address+"' ("+city+")";
}}
Use distanceBetween() method, It will give you exact distance in meters.
Location.distanceBetween(double startLatitude, double startLongitude,
double endLatitude, double endLongitude, float[] results);

How to calculate existence of longitude / latitude in current view

i am really stuck on this:
I have longitude / latitude points to draw on a google map within an android app.
Therefor I created a class extending Overlay...
I get the current longitude/latitude portion of view via:
GeoPoint topLeft = proj.fromPixels(0, 0);
GeoPoint bottomRight = proj.fromPixels(width-1, height-1);
int topLat = topLeft.getLatitudeE6();
int topLon = topLeft.getLongitudeE6();
int bottomLat = bottomRight.getLatitudeE6();
int bottomLon = bottomRight.getLongitudeE6();
The following works (only latitudes):
if(latLon[0] >= bottomLat && latLon[0] <= topLat){ // do something; }
but this does not work (longitudes):
if(latLon[1] >= topLon && latLon[1] <= bottomLon) { // do something; }
latLon[0] is the latitude I want to check
latLon[1] is the longitude I want to check
Anybody an idea?
Greetz!
Longitude numbers are negative from the 0 meridian in England, westward. They're negative in North America and South America.
Use a google map and insert your marker on it.
See below :
public class MapActivity extends GeolocationActivity implements GoogleMap.OnInfoWindowClickListener{
private final String TAG = "MapFragment";
private MapView _mapView;
private GoogleMap _gmap;
/**
* the logo of the marker on the map
*/
private Bitmap _littlePin;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.map);
_mapView = (MapView) findViewById(R.id.location_map);
_mapView.onCreate(savedInstanceState);
_gmap = _mapView.getMap(); // initalise the map
if (_gmap != null)
{
setUpMap();
}
}
/**
* set up the map; Add the market on it with a blue dot for the location of the user in real time
* #return false if something goes wrong, true otherwise
* _latitude = latitude of the user, get from the GeolocationActivity
* _longitude = longitude of the user, get from the GeolocationActivity
*/
private boolean setUpMap()
{
// Gets to GoogleMap from the MapView and does initialization stuff
_gmap.getUiSettings().setMyLocationButtonEnabled(false);
_gmap.setMyLocationEnabled(true);
if (_gmap == null) {
Toast.makeText(this, "Google Maps not available", Toast.LENGTH_LONG).show();
return false;
}
// Needs to call MapsInitializer before doing any CameraUpdateFactory calls
MapsInitializer.initialize(this);
BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.pin); // file stored in /res/drawable/
Bitmap bitmap = bitmapDrawable.getBitmap();
_littlePin = Bitmap.createScaledBitmap(bitmap, 96, 96, false); // 96/96px
_gmap.setOnInfoWindowClickListener(this);// add listener on this class
// here the _lat and _long should be the user of this cafe, at the moment I am using the one of the user
this.addMarker("Cafe", "Best cafe in London", new LatLng(_latitude, _longitude));
// camera, 13 if the zoon, you can change it manually, or dynamically in order to see all your markers
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(new LatLng(_latitude, _longitude), 13);
_gmap.animateCamera(cameraUpdate); // zoom effect
return true;
}
/**
* Add markers on the map view
* #param title title of place / marker
* #param description short description
* #param position geposition, LatLng object, filled with latitude and longitude.
*/
private void addMarker(String title, String description, LatLng position)
{
_gmap.addMarker(new MarkerOptions()
.position(position)
.title(title)
.snippet(description)
.icon(BitmapDescriptorFactory.fromBitmap(_littlePin)));
}
/**
* The user click on the marker on the map, this callback is called
* #param marker clicked marker
*/
#Override
public void onInfoWindowClick(Marker marker) {
Log.d(TAG, "onMarkerClick " + marker.getTitle());
}
#Override
public void onResume() {
_mapView.onResume();
super.onResume();
}
#Override
public void onDestroy() {
super.onDestroy();
_mapView.onDestroy();
}
#Override
public void onLowMemory() {
super.onLowMemory();
_mapView.onLowMemory();
}
}
Here is a good example which gonna help you.
and the github with the code sample is here.
Hope this help.

Categories