I am working on Xamarin form app with andorid, UWP and Windows 8 project. I am using Geolocation plugin created by Jamesmontemagno to get the current device location. It is working fine in windows 8 and UWP but whenever I am trying to run it against the android device I keep getting task cancelled exception. I have checked all the permissions that are required as per suggestion but still no luck. My code to access location is below
protected override void OnAppearing()
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 100; //100 is new default
if (locator.IsGeolocationAvailable && locator.IsGeolocationEnabled)
{
try
{
var position = locator.GetPositionAsync(timeoutMilliseconds: 60000).Result;
//var pp = helper.Setting.Location;
var Latitude = position.Latitude;
var Longitude = position.Longitude;
}
catch(Exception ex)
{
var exc = ex;
}
}
}
Below is an image for my settings for android manifest
For anyone else who gets a timeout even with the await, only on Android, and even though the device's Google Maps app works fine, you are probably running into this bug which only happens on certain Android devices, but quite a few of them at that.
The issue is an old one that Google has never fixed. The solution, and one possible reason the Google Maps app works fine, is to use Google Play Services' fused location provider.
Currently the Geolocator Plugin just uses the regular Android Location Provider, but James has mentioned that he would like to use the Fused provider at some point. I have yet to try the fused provider myself though.
Try using the await keyword like it is used in the original code:
try
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 50;
var position = await locator.GetPositionAsync (timeoutMilliseconds: 10000);
Console.WriteLine ("Position Status: {0}", position.Timestamp);
Console.WriteLine ("Position Latitude: {0}", position.Latitude);
Console.WriteLine ("Position Longitude: {0}", position.Longitude);
}
catch(Exception ex)
{
Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
}
This should take care that there are no race condition and therefore TaskCancellationException.
Thanks to #Radinator below is the working solution.
protected async override void OnAppearing()
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 100; //100 is new default
if (locator.IsGeolocationAvailable && locator.IsGeolocationEnabled)
{
try
{
await SetLocation();
}
catch (Exception ex)
{
var exc = ex;
}
}
}
private async Task SetLocation()
{
var locator = CrossGeolocator.Current;
locator.DesiredAccuracy = 100; //100 is new default
if (locator.IsGeolocationAvailable && locator.IsGeolocationEnabled)
{
try
{
var position = await locator.GetPositionAsync(timeoutMilliseconds: 60000);
var Latitude = position.Latitude;
var Longitude = position.Longitude;
}
catch (Exception ex)
{
//log ex;
throw ex;
}
}
}
Faced 'Task killed' issue with v3.0.4. The following worked for me:
Uninstall the app
Update Geolocator to prerelease 4.0
Related
I am using the CrossGeolocator.Current.StartListeningAsync method in my xamarin app to be able to listen to location updates in background for iOS.
I am using essentials to request permissions.
On first run we get location permission (in app only) and location using essentials and then we use StartListeningAsync for ios to be able to track location if the app is in background or foreground.
When the callback is hit we get a popup saying this app uses background location and gives you the option to use it or change back to use in app only option. On selection of any option the callback never completes and subsequent code isnt run.
Here is the popup I get after I have permission for when in use and then start listening:
Popup on ios
On subsequent runs once permissions are set manually the callback works.
Xamarin Forms Version: 5.0.0.1931
Xamarin Essential Version: 1.6.1
Geolocator Plugin Version: 4.6.2-beta
Code example:
private async Task StartListening()
{
if (CrossGeolocator.Current.IsListening)
return;
try
{
var settings = new ListenerSettings
{
ActivityType = ActivityType.Other,
DeferLocationUpdates = true,
DeferralDistanceMeters = 15,
DeferralTime = TimeSpan.FromSeconds(10),
ListenForSignificantChanges = false,
PauseLocationUpdatesAutomatically = false,
AllowBackgroundUpdates = true,
};
await CrossGeolocator.Current.StartListeningAsync(TimeSpan.FromSeconds(15), 5, true, settings);
CrossGeolocator.Current.PositionChanged += PositionChanged;
CrossGeolocator.Current.PositionError += PositionError;
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
You need to make sure the permission is ok before starting to listen to location updates. Have a try with following code:
public async Task GetLocationAsync()
{
var status = await CheckAndRequestPermissionAsync(new Permissions.LocationAlways());
if (status != PermissionStatus.Granted)
{
// Notify user permission was denied
return;
}else{
await StartListening();
}
}
public async Task<PermissionStatus> CheckAndRequestPermissionAsync<T>(T permission)
where T : BasePermission
{
var status = await permission.CheckStatusAsync();
if (status != PermissionStatus.Granted)
{
status = await permission.RequestAsync();
}
return status;
}
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
Issue
I'm trying to trigger a BackgroundTask when a Geofence Event (Enter / Exit) occurs in WP8.1 (WinRT). I've written a sample application to try to get it working, but can't seem to be able to do so.
So far, these are the steps I've taken to try to get Geofences working in the background:
Check for Location Capabilities
Create + Register a Geofence
Create + Register a BackgroundTask that listens for LocationTrigger(LocationTriggerType.Geofence);
In my background task, trigger a simple popup notification
Things I have done to Troubleshoot
I have enabled in my app.manifest:
Toast Capable => Yes
Capabilities: Location, Internet(Client &
Server)
Declarations: BackgroundTasks (Location). EntryPoint = BackgroundTask.GeofenceBackgroundTask
My background task is located in a separate project, titled BackgroundTask. It is a WindowsRT Component and contains one class GeofenceBackgroundTask.
Sample Project
The code for the project can be found at this [link](https://github.com/kiangtengl/GeofenceSample):
How To Test
Run the code in the emulator
Set Location to to: Latitude = 01.3369, Longitude = 103.7364
Click the Register Geofence + BackgroundTasks button
Exit the app (press the home button)
Change the current location to anywhere 100m away from the location you set previously. A notification should pop out.
Project Code:
Check for Location Capabilities
public static async Task GetLocationCapabilities()
{
try
{
var geolocator = new Geolocator();
await geolocator.GetGeopositionAsync();
var backgroundAccessStatus = await BackgroundExecutionManager.RequestAccessAsync();
Debug.WriteLine("background access status" + backgroundAccessStatus);
}
catch (UnauthorizedAccessException e)
{
Debug.WriteLine(e);
}
catch (TaskCanceledException e)
{
Debug.WriteLine(e);
}
}
Create Geofence
public static void CreateGeofence(BasicGeoposition position, double radius, string id = "default")
{
// The Geofence is a circular area centered at (latitude, longitude) point, with the
// radius in meter.
var geocircle = new Geocircle(position, radius);
// Sets the events that we want to handle: in this case, the entrace and the exit
// from an area of intereset.
var mask = MonitoredGeofenceStates.Entered | MonitoredGeofenceStates.Exited;
// Specifies for how much time the user must have entered/exited the area before
// receiving the notification.
var dwellTime = TimeSpan.FromSeconds(1);
// Creates the Geofence and adds it to the GeofenceMonitor.
var geofence = new Geofence(id, geocircle, mask, false, dwellTime);
try
{
GeofenceMonitor.Current.Geofences.Add(geofence);
}
catch (Exception e)
{
Debug.WriteLine(e);
// geofence already added to system
}
}
Register Background Task
public static async Task RegisterBackgroundTask()
{
try
{
// Create a new background task builder
var geofenceTaskBuilder = new BackgroundTaskBuilder()
{
Name = GeofenceBackgroundTaskName,
TaskEntryPoint = "BackgroundTask.GeofenceBackgroundTask"
};
// Create a new location trigger
var trigger = new LocationTrigger(LocationTriggerType.Geofence);
// Associate the location trigger with the background task builder
geofenceTaskBuilder.SetTrigger(trigger);
var geofenceTask = geofenceTaskBuilder.Register();
// Associate an event handler with the new background task
geofenceTask.Completed += (sender, e) =>
{
try
{
e.CheckResult();
}
catch(Exception error)
{
Debug.WriteLine(error);
}
};
}
catch(Exception e)
{
// Background task probably exists
Debug.WriteLine(e);
}
}
BackgroundTask Code to Trigger Toast
namespace BackgroundTask
{
public sealed class GeofenceBackgroundTask : IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
var toastTemplate = ToastTemplateType.ToastText02;
var toastXML = ToastNotificationManager.GetTemplateContent(toastTemplate);
var textElements = toastXML.GetElementsByTagName("text");
textElements[0].AppendChild(toastXML.CreateTextNode("You have left!"));
var toast = new ToastNotification(toastXML);
ToastNotificationManager.CreateToastNotifier().Show(toast);
}
}
}
I've discovered that the above code sample, as well as the above code works. The problem that I was facing was that Windows Phone 8.1 does not automatically trigger a Geofence event. You have to wait a certain amount of time <5 mins before the BackgroundTask is triggered.
This applies to Geofencing in the foreground as well.
I'm busy with the same stuff, and I also noticed this behaviour, but for me its 2 mins.
Unfortunately it always triggers after 2 min, even, if there was no change in location and still inside the fence..
I'm working on WP7/8 application with barcode scanning. And have a problem with disposing camera. Camera initialize too long, and when camera is still initializing and I press back button, I've got a fatal error:
A first chance exception of type 'System.ObjectDisposedException'
occurred in Microsoft.Devices.Camera.ni.dll WinRT information: Fatal
error. Disposing capture device.
Could anybody helps me how to avoid this error?
my code:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
InitializeAndGo();
base.OnNavigatedTo(e);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
disposeCamera();
}
private void PhotoCameraOnInitialized(object sender, CameraOperationCompletedEventArgs cameraOperationCompletedEventArgs)
{
_width = Convert.ToInt32(_photoCamera.PreviewResolution.Width);
_height = Convert.ToInt32(_photoCamera.PreviewResolution.Height);
_luminance = new PhotoCameraLuminanceSource(_width, _height);
if (_photoCamera.IsFlashModeSupported(FlashMode.Auto))
{
_photoCamera.FlashMode = FlashMode.Off;
}
cameraInitialized = true;
Dispatcher.BeginInvoke(() =>
{
FlashCheckbox.IsEnabled = true;
if (_photoCamera.IsFlashModeSupported(FlashMode.Auto))
{
_photoCamera.FlashMode = FlashMode.Off;
}
});
_photoCamera.Focus();
}
private void InitializeAndGo()
{
stopScan = false;
_photoCamera = new PhotoCamera();
_photoCamera.Initialized += PhotoCameraOnInitialized;
_photoCamera.AutoFocusCompleted += PhotoCameraOnAutoFocusCompleted;
viewfinderBrush.SetSource(_photoCamera);
_previewTransform.Rotation = _photoCamera.Orientation;
_results = new ObservableCollection<Result>();
_barcodeReader = new BarcodeReader();
_barcodeReader.TryHarder = true;
_barcodeReader.AutoRotate = true;
_service = new MyMoviesDataService(ErrorDataService);
}
private void disposeCamera()
{
try
{
cameraInitialized = false;
StopScan();
_photoCamera.Initialized -= PhotoCameraOnInitialized;
_photoCamera.AutoFocusCompleted -= PhotoCameraOnAutoFocusCompleted;
_photoCamera.Dispose();
_photoCamera = null;
}
catch (Exception ex)
{
App.ShowErrorToast(ex.Message);
}
}
Don't use the camera until it's been successfully initialized (You can check this in the camera's Initialized event).
Also, wrap any usages of the camera in a
try
{
// camera code here
}
catch (ObjectDisposedException)
{
// re-initialize the camera?
}
to handle situations like suspension, which will dispose of the camera automatically.
As for the
An exception of type 'System.ObjectDisposedException' occurred in
Microsoft.Devices.Camera.ni.dll and wasn't handled before a
managed/native boundary WinRT information: Fatal error. Disposing
capture device.
This is something Microsoft needs to fix; I mean, how are you supposed to handle a native code exception if it isn't allowed to propagate to managed code?
Where is the exception coming from (which code line / block)?
I would for starter put a try...catch around InitializeAndGo() in the OnNavigatedTo event handler. And on the whole PhotoCameraOnInitialized event handler also.
Cheers,
I have written a windows service that is supposed to run a chrome instance.
how ever on attaching the service to the process I am able to hit the breakpoint to Process.Start but it does not opens the chrome.
also I do not get any error.
can anyone help me here.
protected override void OnStart(string[] args)
{
var timer = new Timer(5000);
timer.Elapsed += TimerElapsed;
timer.Start();
}
void TimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
var processes = Process.GetProcessesByName("Chrome");
var found = false;
foreach (var process in processes)
{
if (process.MainWindowTitle.StartsWith("title"))
{
found = true;
}
}
if (!found)
{
var process = Process.Start("Chrome", "http://localhost");
}
}
catch (Exception ex)
{
}
}
If I create a windows application for the same then it works fine.
due to session 0 isolation I guess this is not a good idea to proceed upon..
Click here to know more