.NET MAUI GeolocationRequest - What settings to provide? - android

I am using the following code to get the Lat/Long and display.
labelLatLong.Text = "Checking Lat Long. Please wait...";
var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(15));
CancellationTokenSource cts = new CancellationTokenSource();
try
{
var location = Geolocation.GetLocationAsync(request, cts.Token);
if (location != null)
{
labelLatLong.Text = $"Latitude: {location.Result.Latitude}, Longitude: {location.Result.Longitude}, Altitude: {location.Result.Altitude}";
}
}
catch {
labelLatLong.Text = "Unable to get location.";
}
For some reason, I am not getting the location value and there is no exception thrown and I cannot debug beyond the line 'GetLocationAsync', and the application says "App not responding"
I am using Visual Studio 17.4.3, Pixel 5 (API 33) android emulator.
I already gave permissions 'All the time' in the android emulator.
My laptop also has the location enabled.
Are there any other settings, I should be looking at?
Any suggestions? Appreciate your help. Thank you!

In your xaml.cs:
private async void Button_Clicked(object sender, EventArgs e)
{
try
{
var location = await Geolocation.GetLastKnownLocationAsync();
if (location == null)
{
location = await Geolocation.GetLocationAsync(new GeolocationRequest()
{
DesiredAccuracy = GeolocationAccuracy.High, Timeout = TimeSpan.FromSeconds(30)
});
}
if (location == null)
{
labelLatLong.Text = "Unable to get location.";
}
else
{
labelLatLong.Text = $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}";
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}

Related

is location detection required google play services android studio

I have built an app using location detection to get the current location
I am using LocationManager and LocationLiastener
the app works fine but when I tried to run it on advice without android play service it won't get the current Location and show the following dialog
enter image description here
this is the app link on Github
https://github.com/mostafa-n3ma/Pcm-helper1.0
By checking your code here https://github.com/mostafa-n3ma/Pcm-helper1.0/blob/master/app/build.gradle#L69
Are you sure you are not dependent on the google play service library?
this is the problem
private fun checkDeviceLocationSettingsAndGetLocationUpdates(resolve: Boolean = true) {
val locationRequest = com.google.android.gms.location.LocationRequest.create().apply {
priority = LocationRequest.QUALITY_LOW_POWER
}
val builder = LocationSettingsRequest.Builder().addLocationRequest(locationRequest)
val settingsClint = LocationServices.getSettingsClient(requireActivity())
val locationSettingsResponseTask = settingsClint.checkLocationSettings(builder.build())
locationSettingsResponseTask.addOnFailureListener { exeption ->
if (exeption is ResolvableApiException && resolve) {
try {
startIntentSenderForResult(
exeption.resolution.intentSender,
REQUEST_TURN_DEVICE_LOCATION_ON,
null,
0, 0, 0,
null
)
} catch (sendEx: IntentSender.SendIntentException) {
Log.d(TAG, "Error geting location settings resolution: " + sendEx.message)
}
} else {
Snackbar.make(
this.requireView(),
"Location services must be enabled to use the app", Snackbar.LENGTH_INDEFINITE
).setAction(android.R.string.ok) {
checkDeviceLocationSettingsAndGetLocationUpdates()
}.show()
}
}
locationSettingsResponseTask.addOnCompleteListener {
if (it.isSuccessful) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0.0f, locationListener
)
}
}
}
I am using the google services library to check Location setting if it was enabled or not
if the location is ON the location update request will be triggered
else it will ask the user to enable it and then trigger the location update request
if the services are not available nothing will happen and no location update will be requested
so I will try another way to check the location feature

how to get current Location with android studio

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
}

Xamarin android get address based on latitude and longitude

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();
}
}
}
}

CW Location Poller - Doesn't force the GPS to attempt a lock

I've asked a question about Commonware's location poller before and got it to work before. Its still working but there is a problem.
Yesterday, (after a bit of experimenting and code studying lol) I realized that in order to get location using both options (prefer GPS, but if not available use Network) I had to pass the extra as 'BOTH'.
After doing that however, the LocationPollerService doesn't FORCE the GPS to locate me. Let me describe the issue below.
Suppose I have my GPS on, and another app actively using the GPS and maintaining a lock. Now, if I use the LocationPollerService, it will return me the value from GPS. However, when my GPS in on, but isn't locked, LocationPollerService doesn't attempt a lock but merely moves on to Network-based Location which isn't what I need when I have GPS enabled.
I would've added code here but I believe this is question specific to cwac-locpoll and the code is already online.
Here's the link:
Commonware's Location Poller
My question? How do I force the service to attempt a location fix when GPS is on?
Update
Here's where I think it looks for GPS location but doesn't actually attempt one. If you could help, that would be great.
#Override protected void onPreExecute()
{
// Added in enabled check to even check if there is a provider
// enabled.
if (provider.equalsIgnoreCase("BOTH"))
{
if (!locMgr.isProviderEnabled(LocationManager.GPS_PROVIDER) && !locMgr.isProviderEnabled(LocationManager.NETWORK_PROVIDER))
{
Log.i(TAG, "Both providers are disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
Location lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
return;
}
}
else if (!locMgr.isProviderEnabled(provider))
{
Log.i(TAG, provider + " is disabled");
// There is no provider so fail with the LKL if possible
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Location Provider disabled!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, true);
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, locMgr.getLastKnownLocation(provider));
sendBroadcast(toBroadcast);
quit();
return;
}
onTimeout = new Runnable()
{
public void run()
{
Intent toBroadcast = new Intent(intentTemplate);
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR, "Timeout!");
toBroadcast.putExtra(LocationPoller.EXTRA_ERROR_PROVIDER_DISABLED, false);
Location lastLoc = null;
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Both provider timed out");
lastLoc = locMgr.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (lastLoc == null)
lastLoc = locMgr.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
}
else
{
Log.i(TAG, provider + " timed out");
lastLoc = locMgr.getLastKnownLocation(provider);
}
toBroadcast.putExtra(LocationPoller.EXTRA_LASTKNOWN, lastLoc);
sendBroadcast(toBroadcast);
quit();
}
};
handler.postDelayed(onTimeout, TIMEOUT);
try
{
Log.e(TAG, "Provider: " + provider);
if (provider.equalsIgnoreCase("BOTH"))
{
Log.i(TAG, "Adding both providers");
locMgr.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, listener);
locMgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, listener);
}
else
{
locMgr.requestLocationUpdates(provider, 0, 0, listener);
}
}
catch (IllegalArgumentException e)
{
// see http://code.google.com/p/android/issues/detail?id=21237
Log.w(TAG, "Exception requesting updates -- may be emulator issue", e);
quit();
}
}

Android: App crashes while entering invalid location

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.

Categories

Resources