Assume the following situation:
The User chooses a country from a list. After clicking on a country, the map should zoom to the selected country.
How can I achieve the zoomToCountry in OSMDroid if I only know the country name from the list?
In the PHP API "GoogleMaps v3" there is a solution like
function findAddress(address) {
var geocoder = null;
geocoder = new google.maps.Geocoder();
if (!address)
var address=document.getElementById("countryselect").value;
if ((address != '') && geocoder) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
if (status != google.maps.GeocoderStatus.ZERO_RESULTS) {
if (results && results[0] && results[0].geometry && results[0].geometry.viewport)
map.fitBounds(results[0].geometry.viewport);
} else {
alert("No results found");
}
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
}
Is there any similar in OSMDroid or the OSMBonuspack?
The PHP solution is a call to geocoding service with the country name, to get country bounding box.
You can do something similar using Nominatim service. So OSMBonusPack GeocoderNominatim should be usable.
Roughly that (without error handling, AsyncTask and so on):
GeocoderNominatim coder = new GeocoderNominatim(ctx);
List<Address> results = coder.getFromLocationName(countryName, 1);
Address address = results.get(0);
Bundle extras = address.getExtras();
BoundingBoxE6 bb = extras.getParcelable("boundingbox");
Then:
mapView.zoomToBoundingBox(bb);
As simple as PHP/GoogleMaps solution, isn't it?
Related
I want get current location then i press one button in the app but it dont give me that instead it give unknown address but if i change my location to USA it gives the address? I dont get any errors everything is working good only the address dont show up? here is my code, If you could help me I would appreciate it.
try {
Geocoder geo = new Geocoder(this.getApplicationContext(), Locale.getDefault());
List<Address> addresses = geo.getFromLocation(currentLocation.getCoordinates().latitude, currentLocation.getCoordinates().longitude, 1);
if (addresses.isEmpty()) {
autocompleteFragmentFrom.setText(R.string.waiting_for_location);
} else {
addresses.size();
if (addresses.get(0).getThoroughfare() == null) {
pickupLocation.setName(addresses.get(0).getLocality());
} else if (addresses.get(0).getLocality() == null) {
pickupLocation.setName("unknown address");
} else {
pickupLocation.setName(addresses.get(0).getLocality() + ", " + addresses.get(0).getThoroughfare());
}
autocompleteFragmentFrom.setText(pickupLocation.getName());
}
} catch (IOException e) {
e.printStackTrace();
}
}
enter image description here
After request location permission and enable GPS use FusedLocationProviderClient.
private val mFusedLocationProviderClient: FusedLocationProviderClient by lazy {
LocationServices.getFusedLocationProviderClient(requireActivity())
}
mFusedLocationProviderClient.lastLocation?.addOnSuccessListener(this) { location:Location? ->
val lat = location?.latitude
val lon = location?.longitude
}
I am trying to get locations from the string which is being searched. But, in some cases addressList is returning size 0(i.e. H.M. education centre, kolkata). I don't have latitude and longitude to search the place. Needed help.
String addressString = (String) adapterView.getItemAtPosition(position);
String addressString1 = (String) adapterView.getItemAtPosition(position);
List<Address> addressList = null;
Address address = null;
if (!TextUtils.isEmpty(addressString))
{
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
try
{
addressList = geocoder.getFromLocationName(addressString, 1);
}
catch (IOException e)
{
e.printStackTrace();
addressString = addressString1;
}
//noinspection ConstantConditions
if(addressList != null && addressList.size() > 0)
{
address = addressList.get(0);
}
}
As alternative you can use Geocoding API or Places API web services. I checked your address 'H.M. education centre, kolkata' in Geocoding API web service request and figured out that coordinate can be found. Have a look at Geocoder tool with this address:
https://google-developers.appspot.com/maps/documentation/utils/geocoder/#q%3DH.M.%2520education%2520centre%252C%2520kolkata
In your Java code I can suggest using the Java Client for Google Maps Services hosted at Github:
https://github.com/googlemaps/google-maps-services-java
The code snippet to execute web service request with this client library is the following
GeoApiContext context = new GeoApiContext.Builder()
.apiKey("AIza...")
.build();
GeocodingResult[] results = GeocodingApi.geocode(context,
"H.M. education centre, kolkata").await();
The Javadoc for the current version of the library can be found at
https://googlemaps.github.io/google-maps-services-java/v0.2.7/javadoc/
Note also that places like this one can be found via Places API web service. In this case the code snippet will be
GeoApiContext context = new GeoApiContext.Builder()
.apiKey("AIza...")
.build();
TextSearchRequest req = PlacesApi.textSearchQuery(context, "H.M. education centre, kolkata");
try {
PlacesSearchResponse resp = req.await();
if (resp.results != null && resp.results.length > 0) {
//Process your results here
}
} catch(Exception e) {
Log.e(TAG, "Error getting places", e);
}
I hope this helps!
I am new to Android development, following is my code about use Geocoder to get city name of current location, it returns null:
private void updateCurrentLocation(Location location) {
double lat = 0.0, lng = 0.0;
if (location != null) {
lat = location.getLatitude();
lng = location.getLongitude();
Log.i("tag", "Latitute is" + lat + ", Longtitute is" + lng);
} else {
City_Name = "Unavailable";
}
List<Address> list = null;
Geocoder geocoder = new Geocoder(this.getActivity());
try {
list = geocoder.getFromLocation(lat, lng, 1);
} catch (IOException e) {
e.printStackTrace();
}
//may provide multiple locations.
if (list != null && list.size() > 0) {
Address address = list.get(0);
City_Name = address.getLocality();
}
Log.i("Try", "CityName:" + City_Name);
//send empty message
handler.sendEmptyMessage(1);
}
I opened GPS services, add ACCESS_FINE_LOCATION and INTERNET permission in Manifest already. Also, I searched similar questions in Stackoverflow about Geocoder returns null, but haven't found useful solutions. One of them is analyze JSON from Geocoder website, but it doesn't work either.
Can anyone help with this? Thank you!
BTW, is there any better solution to receive a city name? Thank you!
If the "getFromLocation" method gives you an empty set then it's because the server that is being looked up doesn't have the address information for the coordinates you're passing it. This is also noted in the docs. So I think that you should let it go and use another service like the Google Maps geocoding service or another one like Nominatim from the OpenStreetMap project.
Im new new to xamarin Android....I have an app which shows users current latitude and longitude which seems to be working...
Now, from latitude and longitude, Im trying to get address using API Geocoder. Im passing proper latitude and longitude but its not giving me any address though I cant see any error.
Following is my code :-
async Task<Address> ReverseGeocodeCurrentLocationAsync(double Latitude, double Longitude)
{
Geocoder geocoder = new Geocoder(this);
IList<Address> addressList = await
geocoder.GetFromLocationAsync(Latitude, Longitude, 10); // ???????? its not wrking....Here, Im properly able to pass latitude and longitude still issue getting adress.
IList<Address> testaddresses = await geocoder.GetFromLocationAsync(42.37419, -71.120639, 1); // ???????? i tried both sync and async method but not wrking....
Address address = addressList.FirstOrDefault();
return address;
}
// calling part
Address address = await ReverseGeocodeCurrentLocationAsync(location.Latitude, location.Longitude);
Also, you can find source code at :https://github.com/4pawan/XamarinDroidSample
Please let me know what I'm doing wrong and how to rectify ?
Regards,
Pawan
Always check if a Geocoder is available as this requires a background service to be available and it is possible that it is not available as it not included in the base Android framework:
Geocoder.IsPresent
Register your app in Google's Dev API Console
Add your Google Map API Key your your app's manifest
If you are using Google's fused location provider (via Google Play services) and need Geo-Coding, make sure your app has ACCESS_FINE_LOCATION permission:
Network connectivity is required to receive an address list from the Geocoder service.
Depending upon your device's Geocoder service, it can take more then one request before "Google" or your device's Geocoder service replies with a list of addresses.
Do not spam the service, you will get throttled, use an increasing time delay between requests.
Note: A extremely frequent response is:
`Timed out waiting for response from server`
In this case, wait a short peroid time and retry.
But there are a number of other errors that include, no addresses found, invalid lat/log, geocoder not currently available, etc...
Note: I normally use ReactiveUI to wrap the failures, retries and continuation, but here is a simple example:
Basic Geocode method (much like yours):
async Task<Address> ReverseGeocodeLocationAsync(Location location)
{
try
{
var geocoder = new Geocoder(this);
IList<Address> addressList = await geocoder.GetFromLocationAsync(location.Latitude, location.Longitude, 3);
Address address = addressList.FirstOrDefault();
return address;
}
catch (Exception e)
{
Log.Error(TAG, e.Message);
}
return null;
}
The Retry:
int retry = 0;
Address address = null;
do
{
address = await ReverseGeocodeLocationAsync(_currentLocation);
if (address != null)
{
Log.Info(TAG, $"Address found: {address.ToString()}");
// Do something with the address(es)
break;
}
retry++;
Log.Warn(TAG, $"No addresses returned...., retrying in {retry * 2} secs");
await Task.Delay(retry * 2000);
} while (retry < 10);
This is how you get the full address using Latitude and Longitude in Xmarin android
using Android.App;
using Android.OS;
using Android.Support.V7.App;
using Android.Runtime;
using Android.Widget;
using Xamarin.Essentials;
using System;
using System.Threading.Tasks;
using Android.Content.PM;
using System.Collections.Generic;
using System.Linq;
namespace GeoLocation
{
[Activity(Label = "#string/app_name", Theme = "#style/AppTheme", MainLauncher = true)]
public class MainActivity : AppCompatActivity
{
TextView txtnumber;
protected async override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.activity_main);
txtnumber = FindViewById<TextView>(Resource.Id.textView1);
double GmapLat = 0;
double GmapLong = 0;
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
var location = await Geolocation.GetLocationAsync(request);
txtnumber.Text = "finish get geolocation";
GmapLat = location.Latitude;
GmapLat=location.Longitude;
if (location != null)
{
var placemarks = await Geocoding.GetPlacemarksAsync(location.Latitude, location.Longitude);
var placemark = placemarks?.FirstOrDefault();
if (placemark != null)
{
// Combine those string to built full address... placemark.AdminArea ,placemark.CountryCode , placemark.Locality , placemark.SubAdminArea , placemark.SubLocality , placemark.PostalCode
string GeoCountryName = placemark.CountryName;
}
txtnumber.Text = "GPS: Latitude " + location.Latitude + " Longitude " + location.Longitude;
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get location
txtnumber.Text = ex.Message.ToString();
}
}
}
}
In my app, I have to find whether a given location comes under a specified area. I am taking Connaught Place, New Delhi as center point. and I got the addresses which come under area of 200 miles from center point. But, if I enter any invalid location, like "abcdfdfkc", the app crashes, because it is trying to find coordinates of this location and I want to avoid this.
Below I am posting the code:
public static boolean isServicedLocation(Context _ctx, String strAddress){
boolean isServicedLocation = false;
Address sourceAddress = getAddress(_ctx, "Connaught Place, New Delhi, India");
Location sourceLocation = new Location("");
sourceLocation.setLatitude(sourceAddress.getLatitude());
sourceLocation.setLongitude(sourceAddress.getLongitude());
Address targetAddress = getAddress(_ctx, strAddress);
Location targetLocation = new Location("");
if (targetLocation != null) {
targetLocation.setLatitude(targetAddress.getLatitude());
targetLocation.setLongitude(targetAddress.getLongitude());
float distance = Math.abs(sourceLocation.distanceTo(targetLocation));
double distanceMiles = distance/1609.34;
isServicedLocation = distanceMiles <= 200;
//Toast.makeText(_ctx, "Distance "+distanceMiles, Toast.LENGTH_LONG).show();
}
return isServicedLocation;
}
getAddress method:
public static Address getAddress(Context _ctx, String addressStr) {
Geocoder geoCoder = new Geocoder(_ctx, Locale.getDefault());
try {
List<Address> addresses = geoCoder.getFromLocationName(addressStr,
1);
if (addresses.size() != 0) {
return addresses.get(0);
}
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
It's because when you don't find an address from the GeoCoder (ie, if addresses.size() == 0), you return null.
Then, regardless of that, you dereference the value, which is what's crashing your app.
Address targetAddress = getAddress(_ctx, strAddress);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:
if (targetLocation != null) {
targetLocation.setLatitude(targetAddress.getLatitude());
^^^^^^^^^^^^^
You should probably also be checking targetAddress for null to avoid this (either in addition to (likely), or instead of (less likely), the check of targetLocation).
So I'd be looking at changing:
if (targetLocation != null) {
into:
if ((targetLocation != null) && (targetAddress != null)) {
That way, an invalid address automatically becomes an unserviced location.