0

Whenever I am opening my app I need to check the location is on or off. If the location is off, I need to show an alert to the user to enable location share like the below screenshot:

enter image description here

I try this using the dependency service from this thread:

The interface on shared Project:

public interface ILocSettings
{
    void OpenSettings();
}

Android implementation

[assembly: Dependency(typeof(LocationShare))]
namespace ProjectName.Droid
{
    public class LocationShare : ILocSettings
    {
        public void OpenSettings()
        {
            //code1
            Android.App.Application.Context.StartActivity(new Android.Content.Intent(Android.Provider.Settings.ActionLocat‌​ionSourceSettings));
            
            //code2
            //LocationManager LM = (LocationManager)Android.App.Application.Context.GetSystemService(Context.LocationService);
            //if (LM.IsProviderEnabled(LocationManager.GpsProvider) == false)
            //{
            //    Context ctx = Android.App.Application.Context;
            //    ctx.StartActivity(new Intent(Android.Provider.Settings.ActionLocationSourceSettings));
            //}
        }
    }
}

Finally from the shared project called like below:

var myAction = await DisplayAlert("Location", "Please Turn On Location", "OK", "CANCEL");
if (myAction)
{
    if (Device.RuntimePlatform == global::Xamarin.Forms.Device.Android)
    {
        DependencyService.Get<ILocSettings>().OpenSettings();
    }
}
else
{
    await DisplayAlert("Alert", "User Denied Permission", "OK");
}

I am getting below exception when running this. (Getting the same exception for code1 and code2)

System.NullReferenceException: 'Object reference not set to an instance of an object.'

I need to show the alert only if the location is off. If the location is on, no need to do these things. How I can check the location is on or off?

Also, I need to implement the same feature for ios and windows platforms.

Update 1

Hi @Lucas Zhang - MSFT

I have tried your solution and got an alert like this. But after giving the location access, still the device's location is off. I need to on the device's location like this when the user taps the OK option in the alert (question screenshot). Either on the location directly or redirect to the location settings page.

Update 2

Tried GeolocatorPlugin and used the below code for checking the GPS is off or on. Always getting False value even if the GPS is on.

public bool IsLocationAvailable()
{
    if (!CrossGeolocator.IsSupported)
        return false;

    return CrossGeolocator.Current.IsGeolocationAvailable;
}

Made below modification on the android service and now I am able to open the location settings.

public class LocationShare : ILocSettings
{
    public void OpenSettings()
    {
        Intent intent = new Android.Content.Intent(Android.Provider.Settings.ActionLocat‌​ionSourceSettings);
        intent.AddFlags(ActivityFlags.NewTask);
        Android.App.Application.Context.StartActivity(intent);
    }
}

Before opening the location settings page, I need to verify the GPS is on or off (not the location permission).

Also I didn't understand the ios answer by Jack. So can you show me the ios dependency service like I did for android for opening ios location settings page?

Sreejith Sree
  • 3,055
  • 4
  • 36
  • 105
  • Hi, do you have a try with [Checking Permissions on runtime](https://learn.microsoft.com/en-us/xamarin/essentials/permissions?context=xamarin%2Fxamarin-forms&tabs=android#checking-permissions) before requesting the needed permission or navigate to the setting page? – Junior Jiang Nov 09 '20 at 03:22
  • @JuniorJiang-MSFT I have added `var status = await Permissions.CheckStatusAsync();` and `ACCESS_COARSE_LOCATION`, `ACCESS_FINE_LOCATION` permissions. But status value is always true when the location if off or on. – Sreejith Sree Nov 10 '20 at 11:26

1 Answers1

1

In your case you could use the plugin PermissionsPlugin from Nuget.

Usage

try
{
    var status = await CrossPermissions.Current.CheckPermissionStatusAsync<LocationPermission>();
    if (status != PermissionStatus.Granted)
    {
        if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
        {
            await DisplayAlert("Need location", "Gunna need that location", "OK");
        }

        status = await CrossPermissions.Current.RequestPermissionAsync<LocationPermission>();
    }

    if (status == PermissionStatus.Granted)
    {
        //Query permission
    }
    else if (status != PermissionStatus.Unknown)
    {
        //location denied
    }
}
catch (Exception ex)
{
  //Something went wrong
}

Update

It seems that you want to check if system location is open or not , right ? If so , you could try to achieve GPS info after you get the location permission . If the GPS info is still unavailable , that means the system setting is OFF .And you can invoke dependency service to open platform setting page.

public async void ShareLocation()
{
    var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
    if (status == PermissionStatus.Granted)
    {
        bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
        if (!gpsStatus)
        {
            var myAction = await DisplayAlert("Location", "Please turn on GPS for the proper working of the application.", "TURN ON", "CANCEL");
            if (myAction)
            {
                DependencyService.Get<ILocSettings>().OpenSettings();
            }
        }
    }
}
//ILocSettings
public interface ILocSettings
{
    void OpenSettings();

    bool isGpsAvailable();
}
//Android Dependency Service
[assembly: Dependency(typeof(LocationShare))]
namespace Projectname.Droid.Services 
{
    public class LocationShare : ILocSettings
    {
        public bool isGpsAvailable()
        {
            bool value = false;
            Android.Locations.LocationManager manager = (Android.Locations.LocationManager)Android.App.Application.Context.GetSystemService(Android.Content.Context.LocationService);
            if (!manager.IsProviderEnabled(Android.Locations.LocationManager.GpsProvider))
            {
                //gps disable
                value = false;
            }
            else
            {
                //Gps enable
                value = true;
            }
            return value;
        }

        public void OpenSettings()
        {
            Intent intent = new Android.Content.Intent(Android.Provider.Settings.ActionLocat‌​ionSourceSettings);
            intent.AddFlags(ActivityFlags.NewTask);
            Android.App.Application.Context.StartActivity(intent);
        }
    }
}

For iOS

public void CheckAuthorization(CLLocationManager manager, CLAuthorizationStatus status)
{

    switch (status)
    {
        case CLAuthorizationStatus.Authorized | CLAuthorizationStatus.AuthorizedAlways | CLAuthorizationStatus.AuthorizedWhenInUse:
            Console.WriteLine("Access");
            break;
        case CLAuthorizationStatus.Denied | CLAuthorizationStatus.NotDetermined | CLAuthorizationStatus.Restricted:
            Console.WriteLine("No Access");
            break;
        default:
            Console.WriteLine("No Access");
            break;
    }
}
UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
Sreejith Sree
  • 3,055
  • 4
  • 36
  • 105
Lucas Zhang
  • 18,630
  • 3
  • 12
  • 22