Разрешение местоположения для Android выше 6.0 с Xamarin.Forms.Maps
Я пытаюсь реализовать приложение Xamarin.Forms, используя Xamarin.Forms.Maps, однако я всегда падаю в исключение:
Java.Lang.SecurityException: мое местоположение требует разрешения ACCESS_FINE_LOCATION или ACCESS_COARSE_LOCATION
Я уже пытался выполнить действия, описанные в этом руководстве, https://blog.xamarin.com/requesting-runtime-permissions-in-android-marshmallow/ но не получил результатов.
Будет ли кто-нибудь более последовательным, чтобы помочь мне?
Я намерен использовать приложение, очень близкое к Uber, и я не смогу прогрессировать, если не смогу получить разрешения на местоположение.
Моя главная страница выглядит так в моем 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;
}
}
Мой класс MainActivity в Xamarin.Android выглядит так:
[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 ();
}
}
};
3 ответа
Разрешение местоположения для Android выше 6.0 с Xamarin.Forms.Maps
Вы написали много кода о разрешении, но я не могу найти, где вы запрашиваете разрешение, вам нужно запросить разрешение, прежде чем использовать его.
Когда вы установите IsShowingUser
свойство true, вы должны сначала запросить разрешение, вот три решения.
Решение 1:
Я заметил, что вы используете PermissionsPlugin в своем коде, если вам нужно запросить это разрешение в PCL
, вы можете сослаться на официальный образец PermissionsPlugin.
Добавьте этот код в свой 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:
Когда вы открываете свое приложение, сначала запросите разрешение, в MainActivity
OnStart
метод:
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, чтобы запрашивать разрешение, когда вам это нужно, вот пример, связанный с прочитанным вами учебником. В этом примере он запрашивает разрешение при выполнении этой строки:
buttonGetLocation.Click += async (sender, e) => await TryGetLocationAsync();
Добавить это внутри Android MainActiviy OnCreate()
Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity = this;
добавить это к основной активности Android:
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);
Ссылаться на:
Убедитесь, что вы установили все необходимые разрешения. Если вы хотите использовать Xamarin.Forms.Maps
на Android убедитесь, что у вас есть следующие разрешения, установленные в 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" />
Это видео может помочь вам получить разрешение во время выполнения в формах xamarin https://www.youtube.com/watch?v=IWdpzpFChUQ