当前,我有一个使用Xamarin Forms的应用程序。在我的共享代码中,我注册了事件,并且每次触发PositionChanged事件时,我都会存储最新的位置值。然后,我将以指定的间隔运行一个Task,该Task会获取最新的位置值并调用Web服务以加载它们。
为使应用在后台保持稳定,该代码是否应作为服务在Android项目中执行?
事情似乎在iOS上相当稳定,但在Android上却非常不稳定。该应用程序将在一段时间内正常运行。但是随后进入这种模式,每次我显示该应用程序时,屏幕都会变暗一些,直到最终完全变黑。最终它崩溃了。我想知道我是否遇到了本文(https://docs.microsoft.com/en-us/xamarin/android/app-fundamentals/services/)中提到的问题。当我插入电话并连接ADB时,我看到大量垃圾收集导致GREF的大幅增加。 如果我从一开始就插入设备,那么在Android上的稳定性似乎会大大提高,但是我认为这可能是因为当手机静止不动时位置更新的数量会减少。
我应该补充一点,我非常有信心代码的这一部分会导致此问题,因为当我禁用对启动跟踪功能的调用时,该应用程序是稳定的。
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);
}