随着Oreo / Android 8.0的发布,我想用计划的作业替换我的GPS前台服务。
我看过Xamarin Example for Job Scheduler,,说实话,我感到很困惑。
这就是我要做的:
该工作将代替我的GPS服务(实现ILocationListener)。
有人可以帮忙弄清楚我需要做些什么来实现这一目标吗?
我尝试了.SetPeriodic(30000),在运行Oreo的测试设备上似乎无法使用。
该示例使用.SetMinimumLatency()和.SetOverrideDeadline()来设置某种计划范围。是否可以将两者都设置为30000(30秒)以实现所需? 似乎计划的作业也最少要有15分钟的时间。
该示例使用处理程序并传递参数等。作业调度程序是否需要此命令?一个基本的示例项目正在进行很多工作,我对要求感到困惑。
谢谢,希望有人能帮助我解决这个问题。
干杯。
编辑-示例代码
private void StartTracking() { Log.Debug(TAG, "Starting Tracking"); var component = new ComponentName(Context, Java.Lang.Class.FromType(typeof(LocationJobService))); //// This will run a service as normal on pre-Oreo targets, and use the Job Scheduler on Oreo+. //// Unfortunately we can't use it as there is no way to cancel it. //var locationJobIntent = new Intent(Context, typeof(LocationJobIntentService)); //JobIntentService.EnqueueWork(Context, component, LocationJobIntentService.JobId, locationJobIntent); var deadline = 15 * 1000; var retryTime = 60 * 1000; var builder = new JobInfo.Builder(LocationJobService.JobId, component) .SetMinimumLatency(0) .SetOverrideDeadline(deadline) .SetBackoffCriteria(retryTime, BackoffPolicy.Linear) .SetRequiredNetworkType(NetworkType.Any); Log.Debug(TAG, "Scheduling LocationJobService..."); var result = _jobScheduler.Schedule(builder.Build()); if (result != JobScheduler.ResultSuccess) { Log.Warn(TAG, "Job Scheduler failed to schedule job!"); } }
同样,当用户再次点击该按钮以停止位置更新时,也会被点击]
private void StopTracking() { Log.Debug(TAG, "Stopping Tracking"); _jobScheduler.CancelAll(); }
这是我的工作服务
[Service(Name = "my.assembly.name.etc.LocationJobIntentService", Permission = "android.permission.BIND_JOB_SERVICE")] public class LocationJobService : JobService, ILocationListener { public const int JobId = 69; private const long LOCATION_UPDATE_INTERVAL = 5 * 1000; private const string NOTIFICATION_PRIMARY_CHANNEL = "default"; private const int NOTIFICATION_SERVICE_ID = 261088; private static readonly string TAG = typeof(LocationJobService).FullName; private LocationManager _locationManager; private string _locationProvider; #region Base Overrides public override void OnCreate() { base.OnCreate(); Log.Debug(TAG, "OnCreate called."); _locationManager = (LocationManager)GetSystemService(LocationService); //// TODO: Start the Foreground Service, and display the required notification. //var intent = new Intent(this, typeof(LocationJobService)); //if (AndroidTargetHelper.IsOreoOrLater()) //{ // StartForegroundService(intent); //} //else //{ // StartService(intent); //} //CreateForegroundNotification("It started! yay!"); } /// <summary>Called to indicate that the job has begun executing.</summary> /// <remarks>This method executes on the main method. Ensure there is no blocking.</remarks> public override bool OnStartJob(JobParameters jobParameters) { Log.Debug(TAG, "OnStartJob called."); Task.Run(() => { Log.Debug(TAG, "Starting location updates..."); StartLocationUpdates(); Log.Debug(TAG, "Location updates started. Stopping job."); JobFinished(jobParameters, true); }); // TODO: We need a way to cancel the SERVICE (eg. Foreground notifications, etc) if required. This needs to happen on both logging out, and when the user disables tracking. // Perhaps the notifications need to happen on the Fragment, as opposed to here in the job service? // Will this job be doing background work? return true; } /// <summary>This method is called if the system has determined that you must stop execution of your job even before you've had a chance to call JobFinished().</summary> public override bool OnStopJob(JobParameters @params) { // The OS has determined that the job must stop, before JobFinished() has been called. // TODO: Here, we want to restart the Foreground service to continue it's lifespan, but ONLY if the user didn't stop tracking. Log.Debug(TAG, "OnStopJob called."); // Reschedule the job? return false; } public override void OnDestroy() { base.OnDestroy(); // TODO: StopForeground(true); Log.Debug(TAG, "OnDestroy called."); } #endregion #region ILocationListener Members public void OnLocationChanged(Location location) { Log.Debug(TAG, String.Format("Location changed to '{0}, {1}'", location.Latitude, location.Longitude)); StopLocationUpdates(); // TODO: Do we finish the job here? Or right after we ASK for the location updates? (job params would have to be accessible) //JobFinished(_jobParameters, true); // THIS IS WHERE THE LOCATION IS POSTED TO THE API await PostLocationPing(location.Latitude, location.Longitude); } public void OnProviderDisabled(string provider) { Log.Debug(TAG, String.Format("Provider '{0}' disabled by user.", provider)); // TODO: Get new provider via StartLocationupdates()? } public void OnProviderEnabled(string provider) { Log.Debug(TAG, String.Format("Provider '{0}' enabled by user.", provider)); // TODO: Get new provider via StartLocationupdates()? } public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras) { Log.Debug(TAG, String.Format("Provider '{0}' availability has changed to '{1}'.", provider, status.ToString())); // TODO: Get new provider via StartLocationupdates()? } #endregion private async Task<string> PostLocationPing(double latitude, double longitude, bool isFinal = false) { var client = new NetworkClient(); var locationPing = new LocationPingDTO() { TimestampUtc = DateTime.UtcNow, Latitude = latitude, Longitude = longitude, }; return await client.PostLocationAndGetSiteName(locationPing); } #region Helper Methods private void StartLocationUpdates() { // TODO: Specify the criteria - in our case we want accurate enough, without burning through the battery var criteria = new Criteria { Accuracy = Accuracy.Fine, SpeedRequired = false, AltitudeRequired = false, BearingRequired = false, CostAllowed = false, HorizontalAccuracy = Accuracy.High }; // Get provider (GPS, Network, etc) _locationProvider = _locationManager.GetBestProvider(criteria, true); // Start asking for locations, at a specified time interval (eg. 5 seconds to get an accurate reading) // We don't use RequestSingleUpdate because the first location accuracy is pretty shitty. _locationManager.RequestLocationUpdates(_locationProvider, LOCATION_UPDATE_INTERVAL, 0.0f, this); } private void StopLocationUpdates() { Log.Debug(TAG, "StopLocationUpdates called."); _locationManager.RemoveUpdates(this); } #endregion } }
随着Oreo / Android 8.0的发布,我想将我的GPS前台服务替换为计划的工作。我看过Job Scheduler的Xamarin示例,说实话,我觉得很不错...
对于仍在努力实现这一目标的人,有很多有关连续跟踪的问题。您应该阅读的一篇与此相关的文章是https://developer.android.com/training/location/background