Loading...

Does Xamarin forms need to run CrossGeoLocator as a service if it will be run in the background?


Currently I have an application that is using Xamarin Forms. In my shared code I register for events and each time a PositionChanged event fires, I store the most recent location values. I then have a Task running at a specified interval which grabs the latest location values and calls a webservice to load them.

For the app to remain stable in the background, should this code be executed in the Android project as a service?

Things seem to be fairly stable on iOS but very unstable on Android. The app will run fine for a while. But then I get in this mode where each time I show the app, the screen gets a little darker until it finally goes completely black. Eventually it crashes. I am wondering if I am running into the issue mentioned in this article (https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/). When I plug in the phone and connect ADB, I see a major increase in GREFs with tons of garbage collection. enter image description here The stability seems to increase greatly on Android if I leave the device plugged in from the start, but I'm thinking that may be just because the amount of location updates decreases when the phone is sitting still.

I should add, I am pretty confident this area of the code is causing the issue because when I disable the call to the start tracking function the app is stable.

       private async Task StartTracking()
        {
            ListenerSettings ls = new ListenerSettings
            {
                //     Gets or sets whether background location updates should be allowed (>= iOS 9).
                //     Default: false
                AllowBackgroundUpdates = true,

                //     Gets or sets whether location updates should be paused automatically when the
                //     location is unlikely to change (>= iOS 6). Default: true
                PauseLocationUpdatesAutomatically = false,

                //     Gets or sets the activity type that should be used to determine when to automatically
                //     pause location updates (>= iOS 6). Default: ActivityType.Other
                ActivityType = ActivityType.Fitness,

                //     Gets or sets whether the location manager should only listen for significant
                //     changes in location, rather than continuous listening (>= iOS 4). Default: false
                ListenForSignificantChanges = false,

                //     Gets or sets whether the location manager should defer location updates until
                //     an energy efficient time arrives, or distance and time criteria are met (>= iOS
                //     6). Default: false
                DeferLocationUpdates = false,

                //     If deferring location updates, the minimum distance to travel before updates
                //     are delivered (>= iOS 6). Set to null for indefinite wait. Default: 500
                DeferralDistanceMeters = 0,

                //     If deferring location updates, the minimum time that should elapse before updates
                //     are delivered (>= iOS 6). Set to null for indefinite wait. Default: 5 minutes
                DeferralTime = TimeSpan.FromMilliseconds(1)
            };
            CrossDeviceMotion.Current.SensorValueChanged += SensorValueChanged;
            CrossDeviceMotion.Current.Start(MotionSensorType.Compass, MotionSensorDelay.Fastest);
            CrossDeviceMotion.Current.Start(MotionSensorType.Gyroscope, MotionSensorDelay.Fastest);
            CrossDeviceMotion.Current.Start(MotionSensorType.Accelerometer, MotionSensorDelay.Fastest);
            CrossGeolocator.Current.DesiredAccuracy = 100;
            CrossGeolocator.Current.PositionChanged += PositionChanged;
            CrossGeolocator.Current.PositionError += PositionError;
            try
            {
                await CrossGeolocator.Current.StartListeningAsync(Cfg.TimeBetweenSamples, 1, true, ls).CodeBelowThisLineRunsInBackground();
            }
            catch (InvalidOperationException ioe)
            {
                "The CrossGeolocator.Current throws an InvalidOperationException if we try to start it and it has already been started.  In those rare cases we simply call stop then start again to retry(as done here).  If it fails a second time during the retry it will crash the app and we will get a crash log and be able to investigate.  The immeadiately next log entry is the handled exception, and is logged for informational purposes.  If you see a similar exception logged shortly hereafter that is the log entry just before the app crashes.".LogEvenIfNotInDebugMode();
                ioe.LogException();
                await CrossGeolocator.Current.StopListeningAsync();
                await CrossGeolocator.Current.StartListeningAsync(Cfg.TimeBetweenSamples, 1, true, ls);
            }
            _vectorLoopCanceller = Repeater.Repeat(StashGuardVector, Cfg.TimeBetweenSamples, skipFirstFewIntervals: 2);
        }
- - Source
comments powered by Disqus