随着Oreo / Android 8.0的发布,我想用预定的工作替换我的GPS前台服务。
我看过Xamarin Example for Job Scheduler,,说实话,我觉得很混乱。
以下是我想要做的所有事情:
该作业将取代我的GPS服务(实现ILocationListener)。
任何人都可以帮助澄清我需要做些什么才能实现这一目标吗?
我尝试过.SetPeriodic(30000),它似乎不适用于运行Oreo的测试设备。
该示例使用.SetMinimumLatency()和.SetOverrideDeadline()来设置某种计划范围。我可以将这两个设置为30000(30秒)以达到我的需要吗? 预定工作的最短时间似乎还有15分钟。
该示例使用处理程序并传递参数等。这是Job Scheduler所必需的吗?基本的示例项目有很多,我只是对这些要求感到困惑。
提前致谢,希望有人可以帮我清理一下。
干杯。
编辑 - 示例代码
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
}
}
答案 0 :(得分:0)
对于那些仍在努力实现这一目标的人来说,关于连续跟踪存在许多问题。您应该阅读与此相关的一篇文章https://developer.android.com/training/location/background