Xamarin Forms:如何在 Xamarin ios 应用程序中检查 GPS 是打开还是关闭?

Xamarin Forms: How to check if GPS is on or off in Xamarin ios app?

每当我打开我的应用程序时,我都需要检查 GPS 是打开还是关闭。如果 GPS 关闭,我需要将用户重定向到位置设置页面。我已经使用 完成了 android 部分,如下所示。

ILocSettings

public interface ILocSettings
{
    void OpenSettings();

    bool isGpsAvailable();
}

Android实施

[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 checking the GPS Status
bool gpsStatus = DependencyService.Get<ILocSettings>().isGpsAvailable();
//For opening the location settings 
DependencyService.Get<ILocSettings>().OpenSettings();

对于 ios 我怎样才能实现相同的功能?我试过如下:

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

位置设置页面在 ios 模拟器上打开,但不知道如何检查 GPS 状态。

更新1

我已经尝试了 CLLocationManager 代码,但它没有按预期工作。它 returns 始终为真,即使 location 关闭或打开。

OpenSettings() 函数代码 (UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));) 也没有按预期工作,如果 GPS 关闭,它正在重定向到其他 page, I need to open the location settings page

此外,我正在请求位置许可,如下所示:

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

android 中,正在请求位置权限,但在 ios 中,没有请求权限。

更新2

我已经尝试了新代码,但始终将错误值作为 GPS 状态。我已经在 info.plist 上添加了所有位置权限,如下所示:

但是位置权限不会在 运行 应用程序时询问(甚至一次都不会)。我试过 Permissions.LocationWhenInUse 而不是 Permissions.LocationAlways,但没有成功。

更新 3

以下是我检查位置权限、检查GPS状态和打开设置的完整流程。权限状态值始终为 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();
    }
}

我已尝试使用以下 2 个代码来请求或检查权限。在这两种情况下,状态值都是禁用的。如果我卸载该应用程序并重新安装它,得到相同的状态并且不显示任何权限弹出窗口 window。

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

不同于Android系统,iOS可以单独设置GPS开关,并且只能获取定位服务是否开启的状态。其余的具体定位方式留给iOS系统选择。

一开始我们需要看一下iOS中location的状态:

CLAuthorizationStatus 枚举

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.

从现在开始,iOS只支持这种方式来显示应用程序的自定义设置。有两个有用的讨论,你可以看看。 and Open Location Settings Not working in ios 11 Objective c?.

如果重定向到其他页面如下:

这意味着您的应用程序在安装应用程序后不会对定位服务进行任何设置。 因此,您不需要打开设置页面,因为它不会在您应用的设置页面下方显示定位服务。现在 CLAuthorizationStatus 应该是 NotDetermined。您可以使用 CLLocationManager.RequestWhenInUseAuthorization 来请求权限, 位置服务的弹出窗口 window 将显示供客户在应用程序内选择。

如果客户第一次select不允许,这意味着下次打开应用程序检查定位服务时会显示拒绝 状态。现在您需要使用 UIApplicationOpenSettingsURLString 打开设置页面,然后会在应用程序的自定义设置列表中看到位置服务。

最后,LocationShare的最终代码如下:

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

类似,如果CLAuthorizationStatusDenied(与Forms中的status == PermissionStatus.Unknown相同),如下代码在表单中不起作用。

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

仅当 CLAuthorizationStatusNotDetermined 时有效。而且你最好请求Permissions.LocationWhenInUse而不是Permissions.LocationAlways,这应该是更好的推荐选项。

============================更新#2============== ==================

我修改了上面的代码,你会看到如果CLLocationManager.LocationServicesEnabled为false,我们只能让用户重定向到系统设置页面手动开启服务。因为从iOS10开始,iOS不支持从非系统应用导航到系统设置页面。

============================更新#3============== ========================

如果启用定位服务,当使用UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));方法时,您将看到类似如下的屏幕截图:

Loaction 选项将显示在列表中。