Xamarin Essentials Permissions.RequestAsync does not return - xamarin

When calling Permissions.RequestAsync<Permissions.LocationWhenInUse>() I do not get any result and the App is getting stuck. No matter, if the user accepts or denies the request.
I've set up MainActivity as described in the documentation:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
Now I'm trying to get the permissions the following way. But the RequestAsync call is just getting stuck and I never recieve an answer. Once the permission is granted and the app is being restarted, everything works as expected.
public async Task CheckPermissions()
{
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if (status != PermissionStatus.Granted)
{
status = await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
if (status == PermissionStatus.Granted)
{
HasLocationPermissions = true;
}
else if (status != PermissionStatus.Unknown)
{
HasLocationPermissions = false;
}
}

A synchronous blocking call further up your call stack can cause this; e.g., .Wait(), .Result, or .GetAwaiter().GetResult(). This is the classic deadlock situation described on my blog.
Since you are writing a Xamarin application, you may find this technique helpful - it's a way to start an asynchronous operation (synchronously), show a "loading..." state, and then update when the asynchronous operation completes.

Related

PickPhotoAsync - the first time it doesn't work

The first time I use the application after confirming the permission to access the photos saved on the gallery, pickphoto async seems to do nothing.
in my opinion the problem is that it does not wait for user authorization.
in order to work correctly I have to click on the upload button of the photo more than once.
i am working with android with the latest version of the library.
await CrossMedia.Current.Initialize();
if (!CrossMedia.Current.IsPickPhotoSupported)
{
await DisplayAlert("Oops", "You Cannot pick an image", AppResources.Label_OK);
return;
}
var file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
{
PhotoSize = PhotoSize.MaxWidthHeight,
MaxWidthHeight = 800,
SaveMetaData = false
});
You could ask for the runtime permission before you load the page. After that, you do not need to click on the upload button of the photo more than once.
protected override void OnAppearing()
{
base.OnAppearing();
RunTimePermission();//ask for the runtime permission
}
I thank the people who answered me.
I found the error:
Wrong Code:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
Correct code:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Plugin.Geolocator exits method (deadlock?)

I'm building a Xamarin app and for the geolocation, I'm using the GeolocatorPlugin
The problem is that once the code wants to get the position, the code exists without warning.
My class fields:
private Position position;
private IGeolocator locator = CrossGeolocator.Current;
My page constructor:
public MainPage()
{
InitializeComponent();
locator.PositionChanged += Locator_PositionChanged;
locator.PositionError += Locator_PositionError;
}
OnAppearing event is calling the getLocationPermission:
private async Task GetLocationPermission()
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.LocationWhenInUse);
if (status != PermissionStatus.Granted)
{
//Not granted, request permission
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.LocationWhenInUse))
{
// This is not the actual permission request
await DisplayAlert("Need your permission", "We need to access your location", "Ok");
}
// This is the actual permission request
var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.LocationWhenInUse);
if (results.ContainsKey(Permission.LocationWhenInUse))
status = results[Permission.LocationWhenInUse];
}
//Already granted, go on
if (status == PermissionStatus.Granted)
{
//Granted, get the location
GetLocation();
await GetVenues();
await locator.StartListeningAsync(TimeSpan.FromMinutes(30), 500);
}
else
{
await DisplayAlert("Access to location denied", "We don't have access to your location.", "OK");
}
}
The permission is granted and gets to the GetLocation() method:
private async void GetLocation()
{
//var locator = CrossGeolocator.Current;
try
{
var myPosition = await locator.GetPositionAsync();
position = new Position(myPosition.Latitude, myPosition.Longitude);
}
catch (Exception ex)
{
throw;
}
if (position == null)
{
//Handle exception
}
}
Once the line is reached with locator.GetPositionAsync(), it stops. No exception is thrown, also the PositionError isn't raised.
I have no idea why, but in the beginning it worked once, never worked after that.
The location settings in de Android Emulator are as follow:
Based on my research, you did not acheved that Location Changes like this link
I wrote a demo about Location changes. This is running screenshot.
This is my demo
https://github.com/851265601/GeolocationDemo

Xamarin.Forms - Android : OnRequestPermissionsResult is never called

Under Android I need some permissions to use the Google-Map API. I use the PermissionsPlugin :
https://www.nuget.org/packages/Plugin.Permissions/
Here some code :
async void RequestPermissions()
{
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Location);
if (status != PermissionStatus.Granted)
{
if (await CrossPermissions.Current.ShouldShowRequestPermissionRationaleAsync(Permission.Location))
{
//NavigationHelper.CurrentPage.DisplayAlert("Need location", "Gunna need that location", "OK");
}
var results = await CrossPermissions.Current.RequestPermissionsAsync(Permission.Location);
//Best practice to always check that the key exists
if (results.ContainsKey(Permission.Location))
status = results[Permission.Location];
}
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
PermissionsImplementation.Current.OnRequestPermissionsResult(requestCode, permissions, grantResults);
//base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
But I also noticed that the method "OnRequestPermissionsResult" is never called, and there is no dialog that ask me for permissions !!
Also, the permissions are in the manifest file too !
Any idea to solve this ?

A very long message for LUIS dialog resets dialog state

Using bot framework emulator v.3.5.36, if a user sends long text (about 1K characters), emulator silently resets dialog stack back to root dialog, without any errors or warnings. (see the screenshot below.)
Is there a declared message limit for bot framework?
Is there a way for bot to handle such situations and warn user instead of this silent something?
There is nothing really specific about the code at all:
[LuisModel("{GUID}", "{CODE}", LuisApiVersion.V2, domain: "westeurope.api.cognitive.microsoft.com", threshold: 0.5)]
[Serializable]
public class LuisSearchDialog2 : LuisDialog<object>
{
[LuisIntent("")]
[LuisIntent("None")]
public async Task None(IDialogContext context, LuisResult result)
{
await context.PostAsync(JsonConvert.SerializeObject(result));
context.Wait(this.MessageReceived);
}
}
A simple approach would be to check the length of your message in the MessageController and decide whether you want to process it or not.
public async Task<HttpResponseMessage> Post([FromBody]Activity activity)
{
if (activity.Type == ActivityTypes.Message)
{
MicrosoftAppCredentials.TrustServiceUrl(activity.ServiceUrl);
var connector = new ConnectorClient(new Uri(activity.ServiceUrl));
if (activity.Text != null && activity.Text.Length > 200)
{
var errorReply = activity.CreateReply();
errorReply.Text = "Well well, that is too much of data. How about keeping it simple? How can I help you?";
await connector.Conversations.ReplyToActivityAsync(errorReply);
}
else
{
await Conversation.SendAsync(activity, () => new Dialogs.RootDialog());
}
}
}
The reason is that base LuisDialog doens't handle failed API requests (in case if query is too long, it returns 414 code). So the simplest way to handle such errors is to override MessageReceived as follows:
[Serializable]
public class LuisSearchDialog2 : LuisDialog<object>
{
protected override async Task MessageReceived(IDialogContext context, IAwaitable<IMessageActivity> activity)
{
try
{
await base.MessageReceived(context, activity);
}
catch(HttpRequestException e)
{
// Handle error here
//await context.PostAsync("Error: " + e.ToString());
context.Wait(this.MessageReceived);
}
}
}

Reading Sim Number in Dual Sim Phone Xamarin.Form

Im always getting an error of Java.Lang.SecurityException: getLine1NumberForDisplay: Neither user 10710 nor current process has android.permission.READ_SMS. Even if I already Added the READ_SMS in AndroidManifest.xml
MyCode:
public string GetNumber()
{
TelephonyManager telephonyManager = (TelephonyManager)GetSystemService(TelephonyService);
return telephonyManager.Line1Number;
}
Thanks in Advance and Good Day :D
This is a really simple runtime permission request example.
I would highly recommend reading the Xamarin blog post and the Android doc linked below as you should show the user "why" you are requesting permission before the system dialog shows up.
[Activity(Label = "RunTimePermissions", MainLauncher = true, Icon = "#mipmap/icon")]
public class MainActivity : Activity
{
const int PermissionSMSRequestCode = 99;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Main);
Button button = FindViewById<Button>(Resource.Id.myButton);
button.Click += delegate {
if ((int)Build.VERSION.SdkInt < 23) // Permissions accepted by the user during app install
DoSomeWork();
var permission = BaseContext.CheckSelfPermission(Manifest.Permission.ReadSms);
if (permission == Android.Content.PM.Permission.Granted) // Did the user already grant permission?
DoSomeWork();
else // Ask the user to allow/deny permission request
RequestPermissions(new string[] { Manifest.Permission.ReadSms }, PermissionSMSRequestCode);
};
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PermissionSMSRequestCode)
{
if ((grantResults.Count() > 0) && (grantResults[0] == Android.Content.PM.Permission.Granted))
DoSomeWork();
else
Log.Debug("PERM", "The user denied access!");
}
}
protected void DoSomeWork()
{
Log.Debug("PERM", "We have permission, so do something with it");
}
}
Ref: Requesting Runtime Permissions in Android Marshmallow
Ref: Requesting Permissions at Run Time

Resources