【问题标题】:Location permission for Android above 6.0 with Xamarin.Forms.Maps具有 Xamarin.Forms.Maps 的 Android 6.0 以上的位置权限
【发布时间】:2018-01-28 14:20:11
【问题描述】:

我正在尝试使用 Xamarin.Forms.Maps 实现 Xamarin.Forms 应用程序,但是我总是陷入异常:

Java.Lang.SecurityException:我的位置需要权限 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION

我已经尝试按照本教程https://blog.xamarin.com/requesting-runtime-permissions-in-android-marshmallow/ 中的步骤进行操作,但没有得到结果。

有没有人有更一致的东西可以帮助我?

我打算使用一个非常接近优步的应用程序,如果我无法获得位置权限,我就无法进步。

我的主页面在我的 PCL 中如下所示:

public partial class MainPage: ContentPage
    {
        public MainPage ()
        {
            InitializeComponent ();
            var map = new Map ()
            {
                MapType = MapType.Street,
                IsShowingUser = true
            };

            var stack = new StackLayout {Spacing = 0};
            stack.Children.Add (map);

            Content = stack;
        }
    }

我在 Xamarin.Android 中的 MainActivity 类如下所示:

[Activity (Label = "ExampleGeolocation", Icon = "@ drawable / icon",
              Theme = "@ style / MainTheme", MainLauncher = true,
              ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

    public class MainActivity: global :: Xamarin.Forms.Platform.Android.FormsAppCompatActivity, ActivityCompat.IOnRequestPermissionsResultCallback
    {
        View layout;
        const int RequestLocationId = 0;
        readonly string [] PermissionsLocation = {Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation};

        protected override void OnCreate (Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;

            base.OnCreate (bundle);

            global :: Xamarin.Forms.Forms.Init (this, bundle);
            global :: Xamarin.FormsMaps.Init (this, bundle);

            Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;

            SetStatusBarColor (Android.Graphics.Color.Black);
            LoadApplication (new App ());
        }

        public override async void OnRequestPermissionsResult (int requestCode, string [] permissions, [GeneratedEnum] Permission [] grantResults)
        {
            switch (requestCode)
            {
                case RequestLocationId:
                    {
                        if (grantResults [0] == Permission.Granted)
                        {
                            var snack = Snackbar.Make (layout, "Location Permission is Available.", Snackbar.LengthShort);
                            snack.Show ();

                            await GetLocationAsync ();
                        }
                        else
                        {
                            var snack = Snackbar.Make (layout, "Location Permission Denied", Snackbar.LengthShort);
                            snack.Show ();
                        }
                    }

                    break;
            }
        }

        async Task TryGetLocationAsync ()
        {
            if ((int) Build.VERSION.SdkInt <23)
            {
                await GetLocationAsync ();
                return;
            }

            await GetLocationPermissionAsync ();
        }

        async Task GetLocationPermissionAsync ()
        {
            const string permission = Manifest.Permission.AccessFineLocation;

            if (CheckSelfPermission (permission) == Permission.Granted)
            {
                await GetLocationAsync ();
                return;
            }

            if (ShouldShowRequestPermissionRationale (permission))
            {
                Snackbar.Make (layout, "You must allow the application to access your location options.", Snackbar.LengthIndefinite)
                        .SetAction ("OK", v => RequestPermissions (PermissionsLocation, RequestLocationId))
                        .Show();

                return;
            }

            RequestPermissions (PermissionsLocation, RequestLocationId);
        }

        async Task GetLocationAsync ()
        {
            try
            {
                var locator = CrossGeolocator.Current;
            }
            catch (Exception e)
            {
                e.ToString ();
                throw new NotImplementedException ();
            }
        }
    };

【问题讨论】:

  • 您是否将权限添加到清单中?另外在您的代码中的哪一点引发异常?
  • 另外,当你写“我......没有得到结果”时,你是什么意思?你得到许可对话框了吗?您从 CheckSelfPermission 获得哪个返回码?请提供更多信息
  • 我使用IsShowingUser属性=true时调用地图的代码

标签: c# xamarin xamarin.forms xamarin.android


【解决方案1】:

具有 Xamarin.Forms.Maps 的 Android 6.0 以上的位置权限

你写了很多关于权限的代码,但是我找不到你在哪里请求权限,你需要在使用之前请求权限。

当你将IsShowingUser属性设置为true时,你应该先请求权限,这里有三种解决方案。

解决方案 1:

我注意到您在代码中使用了PermissionsPlugin,如果您需要在PCL 中请求此权限,您可以参考PermissionsPlugin official sample

将此代码添加到您的MainActivity

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

在需要时请求许可:

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

        var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
        status = results[Permission.Location];
     }

     if (status == PermissionStatus.Granted)
     {
         //Permission granted, do what you want do.
     }
     else if(status != PermissionStatus.Unknown)
     {
         await DisplayAlert("Location Denied", "Can not continue, try again.", "OK");
     }
}
catch (Exception ex)
{
    //...
}

解决方案 2:

当你打开你的应用程序时,首先请求权限,在MainActivityOnStart方法中:

protected override void OnStart()
{
    base.OnStart();

    if (ContextCompat.CheckSelfPermission(this, permission) != Permission.Granted)
    {
        ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.AccessCoarseLocation, Manifest.Permission.AccessFineLocation }, 0);
    }
    else
    {
        System.Diagnostics.Debug.WriteLine("Permission Granted!!!");
    }
}

解决方案 3:

在需要的时候使用DependencyService请求权限,这里是你读过的tutorial相关的sample。在本例中,它在执行此行时请求权限:

buttonGetLocation.Click += async (sender, e) => await TryGetLocationAsync();

【讨论】:

  • 解决方案2:ContextCompat.CheckSelfPermission(this, permission)中没有定义“permission”参数
【解决方案2】:

在 android MainActiviy OnCreate() 中添加这个

Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;

将此添加到android mainactivity:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
    Plugin.Permissions.PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

然后此代码将起作用,提示用户提供位置权限。

                var locator = CrossGeolocator.Current;
                locator.DesiredAccuracy = 1000;
                var position = await locator.GetPositionAsync(timeoutMilliseconds: 10000);

参考:

https://jamesmontemagno.github.io/GeolocatorPlugin/

【讨论】:

  • iOS 呢??
【解决方案3】:

确保您已设置所有必要的权限。如果您想在 Android 上使用 Xamarin.Forms.Maps,请确保您在项目的 AndroidManifest.xml 文件中设置了以下权限:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

您还可以通过在 Android 项目上单击鼠标右键并选择 Properties 来设置权限。转到标签Android Manifest 并标记所有必要的权限。

还要确保您在应用程序标签中添加了以下两个语句:

<meta-data android:name="com.google.android.geo.API_KEY" android:value="ADD_YOUR_KEY_HERE" />
<meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />

【讨论】:

    【解决方案4】:

    此视频可以帮助您在 xamarin 表单中获得运行时权限 https://www.youtube.com/watch?v=IWdpzpFChUQ

    【讨论】:

    猜你喜欢
    • 2017-01-26
    • 1970-01-01
    • 2015-12-13
    • 2016-02-25
    • 2016-11-22
    • 2016-10-07
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多