Android Job Scheduler-按周期性计划调用作业,直到被取消?

问题描述 投票:2回答:1

随着Oreo / Android 8.0的发布,我想用计划的作业替换我的GPS前台服务。

我看过Xamarin Example for Job Scheduler,,说实话,我感到很困惑。

这就是我要做的:

  1. 用户点击按钮
  2. 已创建并计划了作业。
  3. 立即调用该作业,此后每30秒调用一次,直到用户再次点击该按钮为止>>
  4. 该工作将代替我的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示例,说实话,我觉得很不错...

android xamarin xamarin.android android-service android-jobscheduler
1个回答
0
投票

对于仍在努力实现这一目标的人,有很多有关连续跟踪的问题。您应该阅读的一篇与此相关的文章是https://developer.android.com/training/location/background

© www.soinside.com 2019 - 2024. All rights reserved.