0

Whenever I am opening my app I need to check the GPS is on or off. If the GPS is off, I need to redirect the user to the location settings page. I have done the android part using the dependency service like below.

ILocSettings

public interface ILocSettings
{
    void OpenSettings();

    bool isGpsAvailable();
}

Android implementation

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

Finally from the shared project called like below:

//For checking the GPS Status
bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
//For opening the location settings 
DependencyService.Get<ILocSettings>().OpenSettings();

For ios how I can I do the same features? I tried like below:

[assembly: Dependency(typeof(LocationShare))]
namespace Projectname.iOS.Serivces
{
    class LocationShare : ILocSettings
    {
        public bool isGpsAvailable()
        {
            //how to check the GPS is on or off here
        }

        public void OpenSettings()
        {
            UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
        }
    }
}

Location settings page opening on ios simulators, but don't know how to check the GPS status.

Update1

I have tried the CLLocationManager code and it is not working as expected. It returns true always even if the location is off or on.

OpenSettings() function code (UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));) is also not working as expected, it is redirecting to some other page, I need to open the location settings page if the GPS is off.

Also, I am requesting location permission like below:

var status = await Permissions.RequestAsync<Permissions.LocationAlways>();

In android, location permission is asking, but in ios, no permissions are asking.

Update2

I have tried the new codes and getting false value always as GPS status. I have added all the location permission on the info.plist like below:

enter image description here

But location permission is not asking when running the app (not even a single time). I have tried Permissions.LocationWhenInUse instead of Permissions.LocationAlways, but no luck.

Update 3

Following is my complete flow for checking location permission, checking GPS status, and open settings. The permission status value is always Disabled.

//Requesting permission like below:
var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
if (status == PermissionStatus.Granted)
{
    //Then checking the GPS state like below
    bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
    if (!gpsStatus)
    {
        //show a message to user here for sharing the GPS
        //If user granted GPS Sharing, opening the location settings page like below:
        DependencyService.Get<ILocSettings>().OpenSettings();
    }
}

I have tried the below 2 codes for requesting or checking permission. In both cases, the status value is Disabled. If I uninstall the app and reinstall it again, getting the same status and not showing any permission pop-up window.

var status = await Permissions.RequestAsync<Permissions.LocationAlways>();
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
Sreejith Sree
  • 3,055
  • 4
  • 36
  • 105
  • use [Essentials](https://learn.microsoft.com/en-us/xamarin/essentials/geolocation?context=xamarin%2Fxamarin-forms&tabs=ios#using-geolocation) and check for FeatureNotEnabledException – magicandre1981 Nov 21 '20 at 14:24

1 Answers1

3

Unlike the Android system, iOS can set the GPS switch separately, and can only get the status of whether the location service is turned on. The rest of the specific positioning method will be left to the iOS system to choose.

At the beginning, we need to have a look at the status of location in iOS:

CLAuthorizationStatus Enum

enter image description here

UIApplicationOpenSettingsURLString: Used to create a URL that you can pass to the openURL: method. When you open the URL built from this string, the system launches the Settings app and displays the app’s custom settings, if it has any.

From now, iOS only support this way to displays the app’s custom settings. There are two helpful discussion, you could have a look. How to jump to system setting's location service on iOS10? and Open Location Settings Not working in ios 11 Objective c?.

If it is redirecting to some other page as follows:

enter image description here

That means your app not do any settings about the location service after installing the app . Therefore, you not need to open the setting page, because it will not show the location service bellow the setting page of your app. Now the CLAuthorizationStatus should be NotDetermined. You could use CLLocationManager.RequestWhenInUseAuthorization to request the permission, the popup window of location service will show for customer to choose inside the app.

enter image description here

If customer select Don't Allow first time, that means next time opening the app to check the location service that will show Denied status. Now you will need to use UIApplicationOpenSettingsURLString to open the settings page and will see the location service inside the app’s custom settings list.

At last, the final code of LocationShare is as follows:

public class LocationShare : ILocSettings
{
    public bool isGpsAvailable()
    {
        bool value = false;

        if ( CLLocationManager.LocationServicesEnabled )
        {
            if(CLLocationManager.Status == CLAuthorizationStatus.Authorized || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedAlways || CLLocationManager.Status == CLAuthorizationStatus.AuthorizedWhenInUse)
            {//enable
                value = true;
            }
            else if (CLLocationManager.Status == CLAuthorizationStatus.Denied)
            {
                value = false;
                OpenSettings();
            }
            else{
                value = false;
                RequestRuntime();
            }
        }
        else
        {
            //location service false
            value = false;
            //ask user to open system setting page to turn on it manually.
        }
        return value;
    }


    public void RequestRuntime()
    {
        CLLocationManager cLLocationManager = new CLLocationManager();
        cLLocationManager.RequestWhenInUseAuthorization();
    }

    public void OpenSettings()
    {

        UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
    }
}

Similarly, if CLAuthorizationStatus is Denied (the same as status == PermissionStatus.Unknown in Forms), the following code will not work in Forms.

var status = await Permissions.RequestAsync<Permissions.LocationAlways>();

It only works when CLAuthorizationStatus is NotDetermined. And you'd better request Permissions.LocationWhenInUse instead of Permissions.LocationAlways, this should be the better recommanded option.

============================Update #2================================

I have modified the above code, and you will see that if CLLocationManager.LocationServicesEnabled is false, we only can ask user to redirect to the system setting page to turn on the service manually. Because from iOS 10, iOS not supports to navigate to system setting page from non-system app.

============================Update #3======================================

If location service is enabled, when using UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString)); method you will see the similar screenshot as follows:

enter image description here

The Loaction option will show in the list.

Junior Jiang
  • 12,430
  • 1
  • 10
  • 30
  • I have updated my question with new findings, could you please have a look? – Sreejith Sree Nov 23 '20 at 15:34
  • @SreejithSree Okey, it seems I forget some situations, I have updated the answer. – Junior Jiang Nov 24 '20 at 06:21
  • I have tried the new codes, but no luck, could you please have a look on Update2 on the question? – Sreejith Sree Nov 24 '20 at 14:06
  • @SreejithSree Okey, that's strang. Do you run the app in a physical device? – Junior Jiang Nov 25 '20 at 01:35
  • Yes I am running on physical devices. – Sreejith Sree Nov 25 '20 at 06:25
  • @SreejithSree Okey, what device is uesed to test? And if you remove the installed app, and use `Permissions.RequestAsync();` to check whether can show the permission popup. – Junior Jiang Nov 25 '20 at 06:43
  • @SreejithSree Oh, if `CLLocationManager.LocationServicesEnabled` is false, you only need to ask customer to go to Settings page manually. Because, from iOS 10, iOS not support non-system app to redirect to system setting page. I will update the code of my answer. – Junior Jiang Nov 25 '20 at 07:09
  • My ios version is 14.2, I uninstall and reinstalled the app, but no permission pop up is showing. Is it an issue on the latest version? – Sreejith Sree Nov 25 '20 at 08:00
  • I have added all the permissions on the info.plist file. https://drive.google.com/file/d/1if5pxk_Di069_0sQP9oCWIBejASNpFmi/view?usp=sharing – Sreejith Sree Nov 25 '20 at 08:02
  • I have tried the below 2 codes for requesting or checking permission. In both cases, the status value is `Disabled`. If I uninstall the app and reinstall it again, getting the same status and not showing any permission pop-up window. `var status = await Permissions.RequestAsync(); var status = await Permissions.CheckStatusAsync();` – Sreejith Sree Nov 25 '20 at 08:27
  • @SreejithSree Unfortunately, I misunderstood your problem in the beginning. This is not an issue, it's a limitation from iOS 10. You only can suggest user to turn on location service manually. You could have a look at my last update answer. – Junior Jiang Nov 25 '20 at 08:44
  • So for ios 14.2, it will not ask permission as a pop up the first time? – Sreejith Sree Nov 25 '20 at 10:13
  • I have added the complete flow in question(Update 3), could you please have a look? – Sreejith Sree Nov 25 '20 at 13:35
  • @SreejithSree Hi, you could have a check with my answer, then you will know that `Permissions.RequestAsync()` will not work if location service is disabled, it only works when `status == PermissionStatus.Unknown` in forms or `CLAuthorizationStatus == NotDetermined` in native iOS. In addition, location service should be opened manually there is no way to open that programmatically. – Junior Jiang Nov 26 '20 at 01:24
  • @SreejithSree I have updated answer, you could have a look. – Junior Jiang Nov 26 '20 at 01:34