Geolocation functionality of Xamarin Essentials wrong location results - xamarin

I am using the Geolocation functionality of Xamarin Essentials in my app as a foreground service running all the time and I have noticed on several devices that I sometimes get locations which are really far away from where they should actually be, looking like this (the marked location is far away from the real location):
public async Task Run(CancellationToken token)
{
await Task.Run(async () => {
while (!stopping)
{
token.ThrowIfCancellationRequested();
try
{
await Task.Delay(2000);
var request = new GeolocationRequest(GeolocationAccuracy.Best);
var location = await Geolocation.GetLocationAsync(request);
if (location != null)
{
var message = new LocationMessage
{
Latitude = location.Latitude,
Longitude = location.Longitude
};
Device.BeginInvokeOnMainThread(() =>
{
MessagingCenter.Send<LocationMessage>(message, "Location");
});
}
}
catch (Exception ex)
{
Device.BeginInvokeOnMainThread(() =>
{
var errormessage = new LocationErrorMessage();
MessagingCenter.Send<LocationErrorMessage>(errormessage, "LocationError");
});
}
}
return;
}, token);
}
result

Related

How to cancel skill's Dialog from Virtual Assistant while using MS Bot Framework V4

We are using bot-framework version 4.x
"botbuilder": "4.11.0",
"botbuilder-ai": "4.11.0",
"botbuilder-applicationinsights": "4.11.0",
"botbuilder-azure": "4.11.0",
"botbuilder-dialogs": "4.11.0",
"botbuilder-lg": "4.11.0",
"botbuilder-testing": "4.11.0",
"botframework-config": "4.11.0",
"botframework-connector": "4.11.0"
Case
We need to start a Dialog in Virtual Assistant and cancel any ongoing Skill dialog (If any)
Example
LiveChat - part of Virtual Assistant
CreateIncidentDialog - part of skill
Suppose we are in the middle of CreateIncidentDialog and the user wants to start LiveChat. We are supposed to start LiveChat and cancel current CreateIncidentDialog.
Sample Code
MainDialog.ts in Virtual Assistant
If current Dialog is a part of skill, we are starting a dialog with activity.type as EVENT for skill.
switch (gIntent) {
case 'Escalate': {
// Checking if current Dialog is a part of Skill
if (isSkill) {
const activity: Activity = innerDc.context.activity;
if ((activity.value === null || activity.value === undefined)) {
activity.value = { userState: userProfile };
};
activity.type = ActivityTypes.Event;
activity.name = "liveChat";
const skillDialogArgs: BeginSkillDialogOptions = {
activity: activity as Activity
};
await innerDc.beginDialog(EvaConfig.LUIS_DEFAULT_INTENT, skillDialogArgs);
} else {
await innerDc.cancelAllDialogs();
}
// code for starting LiveChat goes here
// .....
// .....
// .....
}
MainDialog.ts in Skill
If activity.type is EVENT and name is 'liveChat', cancel dialogs.
protected async onContinueDialog(innerDc: DialogContext): Promise<DialogTurnResult> {
try {
let activity = innerDc.context.activity;
if (innerDc.context.activity.type === ActivityTypes.Message) {
// .....
// .....
// .....
} else if (activity.type === ActivityTypes.Event) {
const ev = activity;
if (ev.name !== undefined && ev.name.trim().length > 0) {
switch (ev.name) {
case 'liveChat': {
await innerDc.cancelAllDialogs(true);
return await innerDc.endDialog();
}
}
}
}
return await super.onContinueDialog(innerDc);
} catch (e) {
console.log(`Error onContinueDialog ---> ${e} `);
return await this.hanldeException(innerDc);
}
}
Issue
The above code is not able to cancel the skill's dialog correctly. If we try to start a new dialog after the cancellation of skill dialog, it again sends an activity with activity.type as EVENT to routeStep method of MainDilaog.ts in Skill. Please find the sample code below for the same.
routeStep method of MainDialog.ts in Skill
protected async routeStep(stepContext: WaterfallStepContext): Promise<DialogTurnResult> {
console.log('skill routeStep');
if (activity.type === ActivityTypes.Message && activity.text !== undefined && activity.text.trim().length > 0) {
// .....
// .....
// .....
} else if (activity.type === ActivityTypes.Event) {
const ev = activity;
if (ev.name !== undefined && ev.name.trim().length > 0) {
switch (ev.name) {
case 'SampleAction': {
// .....
// .....
// .....
}
}
} else {
// If we try to start a new dialog, control comes here
await stepContext.context.sendActivity({
type: ActivityTypes.Trace,
text: 'An event with no name was received but not processed.'
});
}
}
} else {
await this.responder.replyWith(stepContext.context, MainResponses.responseIds.dontHavePermissionServiceNow);
await this.complete(stepContext);
}
return await stepContext.next();
}
Step to Reproduce
Step 1. Start a Dialog in Skill
Step 2. End the Dialog in the Skill and start a Dialog in VA
Step 3. Start a new Dialog
Thanks.
Edward

embedio - Post pdf with embedio in xamarin app - status is OK but the stream is 0

I have been using embedio and I would like to post pdf and display it in my Webview in my xamarin application. The pdf is as embedded resource in my application. It all seems to be ok, but the stream position is 0, however the status is 200 ok. and then At readTimeout I see
System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/Current/src/Xamarin.iOS/external/corert/src/System.Private.CoreLib/shared…
My initialization of embedio
public App()
{
Task.Factory.StartNew(async () =>
{
using (var server = new WebServer(HttpListenerMode.EmbedIO, "http://*:8089"))
{
Assembly assembly = typeof(App).Assembly;
server.WithLocalSessionManager();
server.WithWebApi("/api", m => m.WithController(() => new PdfSourceController()));
server.WithEmbeddedResources("/", assembly, "TestApp.html");
await server.RunAsync();
}
});
MainPage = new NavigationPage(new MainPage());
}
My controller
public class PdfSourceController : WebApiController
{
public PdfSourceController() : base()
{
}
[Route(HttpVerbs.Post, "/pdf")]
public async Task UploadFile()
{
var parser = new MultipartFormDataContent();
var fileContent = new StreamContent(new EmbeddedResourceDataStream("Assets/TestDoc.pdf").GetDataStream());
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
{Name = "result", FileName = $"\"{"test"}\""};
fileContent.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
parser.Add(fileContent);
}
private async Task TestPost()
{
try
{
var handler = new HttpClientHandler
{
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate ,
};
using (var client = new HttpClient(handler))
{
client.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("*"));
using (var response = await client.PostAsync($"{DefaultUrl}api/pdf", new MultipartFormDataContent() ).ConfigureAwait(false)) // calling controller?
{
response.Content.Headers.ContentType = new MediaTypeHeaderValue("api/pdf"); // stating what media type?
var responseString = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
response.Content = new StreamContent(responseString);
Pdf = ImageSource.FromStream(() => responseString);
}
}
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}

Unable to complete MSAL login in Xamarin app

I'm trying to get my feet wet with Xamarin and I'm having trouble adding in my organization's login. The screen shot below is as far as I can get attempting to login. When I click "Continue" the same page just loads again. Not really sure what's going on.
The image is the screen I'm stuck on.
I've added code that represents the app class and the code behind for the XAML page attempting to login, leaving out what I "think" is irrelvant.
Any suggestions?
public partial class App : Application
{
public static string AzureBackendUrl =
DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static bool UseMockDataStore = true;
public static IPublicClientApplication PCA = null;
public static string ClientID = "CLIENT_ID";
public static string[] Scopes = { "User.Read" };
public static string Username = string.Empty;
public static object ParentWindow { get; set; }
public App()
{
InitializeComponent();
if (UseMockDataStore)
DependencyService.Register<MockDataStore>();
else
DependencyService.Register<AzureDataStore>();
PCA = PublicClientApplicationBuilder.Create(ClientID)
.WithRedirectUri($"msal{App.ClientID}://auth")
//.WithParentActivityOrWindow(() => App.ParentWindow)
.Build();
MainPage = new MSAL_Example();
}
}
public partial class MSAL_Example : ContentPage
{
public static string tenant_name = "MY_TENANT_NAME";
public MSAL_Example()
{
InitializeComponent();
App.ParentWindow = this;
}
public async Task SignOutAsync()
{
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
try
{
while (accounts.Any())
{
await App.PCA.RemoveAsync(accounts.FirstOrDefault());
accounts = await App.PCA.GetAccountsAsync();
}
slUser.IsVisible = false;
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign in"; });
}
catch (Exception ex)
{
Debug.WriteLine("\tERROR {0}", ex.Message);
}
}
public async Task SignInAsync()
{
AuthenticationResult authResult = null;
IEnumerable<IAccount> accounts = await App.PCA.GetAccountsAsync();
// let's see if we have a user in our belly already
try
{
IAccount firstAccount = accounts.FirstOrDefault();
authResult = await App.PCA.AcquireTokenSilent(App.Scopes, firstAccount)
.ExecuteAsync();
await RefreshUserDataAsync(authResult.AccessToken).ConfigureAwait(false);
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign out"; });
}
catch (MsalUiRequiredException ex)
{
try
{
authResult = await App.PCA.AcquireTokenInteractive(App.Scopes)
.WithParentActivityOrWindow(App.ParentWindow)
.WithAuthority("https://login.microsoftonline.com/" + tenant_name)
.ExecuteAsync();
await RefreshUserDataAsync(authResult.AccessToken);
Device.BeginInvokeOnMainThread(() => { btnSignInSignOut.Text = "Sign out"; });
}
catch (Exception ex2)
{
Debug.WriteLine("\tERROR {0}", ex2.Message);
}
}
}
public async Task RefreshUserDataAsync(string token)
{
//get data from API
HttpClient client = new HttpClient();
HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Get, "https://graph.microsoft.com/v1.0/me");
message.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", token);
HttpResponseMessage response = await client.SendAsync(message);
string responseString = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
JObject user = JObject.Parse(responseString);
slUser.IsVisible = true;
Device.BeginInvokeOnMainThread(() =>
{
lblDisplayName.Text = user["displayName"].ToString();
lblGivenName.Text = user["givenName"].ToString();
lblId.Text = user["id"].ToString();
lblSurname.Text = user["surname"].ToString();
lblUserPrincipalName.Text = user["userPrincipalName"].ToString();
// just in case
btnSignInSignOut.Text = "Sign out";
});
}
else
{
await DisplayAlert("Something went wrong with the API call", responseString, "Dismiss");
}
}
}

while deny the camera permission in android it wont ask again

first time application asking permission for the camera, if we deny the permission it won't ask again if we allow its working fine ??
var scanPage = new ZXingScannerPage();
var cameraStatus = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);
if (cameraStatus != PermissionStatus.Granted)
{
var results = await CrossPermissions.Current.RequestPermissionsAsync(new[] { Permission.Camera });
cameraStatus = results[Permission.Camera];
if (cameraStatus == PermissionStatus.Granted)
{
// Navigate to our scanner page
await Navigation.PushAsync(scanPage);
scanPage.OnScanResult += (result) =>
{
Device.BeginInvokeOnMainThread(async () =>
{
await Navigation.PopAsync();
txtbarcode.Text = result.Text;
});
};
}
else if (cameraStatus == PermissionStatus.Unknown)
{
await Navigation.PushAsync(scanPage);
scanPage.OnScanResult += (result) =>
{
Device.BeginInvokeOnMainThread(async () =>
{
await Navigation.PopAsync();
txtbarcode.Text = result.Text;
});
};
}
If we deny the camera permission, again its asks while opening camera until we allow the permission.
I wrote a demo about this.
https://github.com/851265601/CheckPermissionDemo
This a GIF of this demo.
Did you check the permission every time when you use the camera function? In this demo, when i click the button ,it will check the permission, then give the result to users, if not give the permission, it will still ask the persmission like the following code.
async void ButtonPermission_OnClicked(object sender, EventArgs e)
{
if (busy)
return;
busy = true;
((Button)sender).IsEnabled = false;
var status = await CrossPermissions.Current.CheckPermissionStatusAsync(Permission.Camera);
await DisplayAlert("Pre - Results", status.ToString(), "OK");
if (status != PermissionStatus.Granted)
{
status = await Utils.CheckPermissions(Permission.Camera);
await DisplayAlert("Results", status.ToString(), "OK");
}
busy = false;
((Button)sender).IsEnabled = true;
}
}
When DisplayAlert was appear, it are used MainApplication for different life cycle
namespace CheckPermissionDemo.Droid
{
//You can specify additional application information in this attribute
[Application]
public class MainApplication : Application, Application.IActivityLifecycleCallbacks
{
public MainApplication(IntPtr handle, JniHandleOwnership transer)
: base(handle, transer)
{
}
public override void OnCreate()
{
base.OnCreate();
RegisterActivityLifecycleCallbacks(this);
//A great place to initialize Xamarin.Insights and Dependency Services!
}
public override void OnTerminate()
{
base.OnTerminate();
UnregisterActivityLifecycleCallbacks(this);
}
public void OnActivityCreated(Activity activity, Bundle savedInstanceState)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityDestroyed(Activity activity)
{
}
public void OnActivityPaused(Activity activity)
{
}
public void OnActivityResumed(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivitySaveInstanceState(Activity activity, Bundle outState)
{
}
public void OnActivityStarted(Activity activity)
{
CrossCurrentActivity.Current.Activity = activity;
}
public void OnActivityStopped(Activity activity)
{
}
}
}

ZXing is not scanning on Android (Xamarin app)

I am using below code to scan a QR code in my Xamarin. I am currently testing it on Samsung Galaxy (Android) and I am able to view the camera streaming but it is not scanning any QR code.
How can I fix this please to get the result of the QR scanned?
public void Scan()
{
try
{
scanner.Options = new MobileBarcodeScanningOptions()
{
UseFrontCameraIfAvailable = false, //update later to come from settings
PossibleFormats = new List(),
TryHarder = true,
AutoRotate = false,
TryInverted = true,
DelayBetweenContinuousScans = 2000,
};
scanner.VerticalOptions = LayoutOptions.FillAndExpand;
scanner.HorizontalOptions = LayoutOptions.FillAndExpand;
// scanner.IsVisible = false;
scanner.Options.PossibleFormats.Add(BarcodeFormat.QR_CODE);
// scanner.Options.PossibleFormats.Add(BarcodeFormat.DATA_MATRIX);
// scanner.Options.PossibleFormats.Add(BarcodeFormat.EAN_13);
scanner.OnScanResult += (result) => {
// Stop scanning
scanner.IsAnalyzing = false;
scanner.IsScanning = false;
if (scanner.IsScanning)
{
scanner.AutoFocus();
}
// Pop the page and show the result
Device.BeginInvokeOnMainThread(async () => {
if (result != null)
{
await DisplayAlert("Scan Value", result.Text, "OK");
}
});
};
mainGrid.Children.Add(scanner, 0, 1);
}
catch (Exception ex)
{
DisplayAlert("Scan Value", ex.ToString(), "Error");
}
}
Maybe you are using the wrong event handler, or missing an event, also the camera never focuses:
the condition is never true, due to this fragment of code:
scanner.IsScanning = false;
if (scanner.IsScanning)
{
scanner.AutoFocus();
}

Resources