任务在Xamarin Forms上每天运行一次

时间:2016-07-08 12:50:10

标签: xamarin.forms

几个月前我开始使用xamarin,直到现在,我还没有必要做这样的事情。 我正在开发一个应用程序,每天一次,应运行WCF Web服务并验证信息是否为真。如果是,则应在设备上显示通知。 我的问题是我不知道如何执行它,我已经阅读了有关背景和计划任务的内容,但我不明白我该如何执行此操作。我怎么能用Xamarin.Forms来做呢?

谢谢!

2 个答案:

答案 0 :(得分:4)

对于Android,解决方案需要4个组件:

  1. AlarmManager设置每日检查时间表
  2. BroadCastReceiver接收每日触发器并调用IntentService
  3. IntentService执行等待通话
  4. OnBootReceiver以确保在设备重启后再次设置警报
  5. 对于iOS,您很可能需要远程推送通知。

    以下Android组件的示例代码:

    AlarmManager - 设置闹钟

    [assembly: Dependency(typeof(AlarmHelper))] // above the namespace
    ...
    class AlarmHelper: IAlarm
    {
        var now = Calendar.Instance;
        var alarmTime = Calendar.Instance;
        alarmTime.Set(CalendarField.HourOfDay, settings.AlarmHour); // Set Alarm start Hour
        alarmTime.Set(CalendarField.Minute, settings.AlarmMinutes); // Set Alarm Start Minutes
    
        if (alarmTime.Before(now))
        {
            alarmTime.Add(CalendarField.Hour, 24);
        }
    
        var intent = new Intent(Android.App.Application.Context, typeof(ScheduledAlarmHandler));
        var pendingIntent = PendingIntent.GetBroadcast(Android.App.Application.Context, 0, intent, PendingIntentFlags.CancelCurrent);
        var alarmManager = Android.App.Application.Context.GetSystemService(Context.AlarmService) as AlarmManager;
    
        alarmManager.SetRepeating(AlarmType.RtcWakeup, alarmTime.TimeInMillis, AlarmManager.IntervalDay, pendingIntent); 
    }
    

    BroadCastReceiver - 接收警报

    [BroadcastReceiver]
    class ScheduledAlarmHandler : WakefulBroadcastReceiver
    {
        public override void OnReceive(Context context, Intent intent)
        {
            Console.WriteLine("ScheduledAlarmHandler", "Starting service @" + SystemClock.ElapsedRealtime());
            Intent service = new Intent(context, typeof(WakefulAPIService)); 
            StartWakefulService(context, service);
        }
    }
    

    IntentService - 执行等待通话

    [Service]
    [IntentFilter(new String[] { "com.test.testApp.WakefulAPIService" })]
    class WakefulAPIService : IntentService
    {
        protected override void OnHandleIntent(Intent intent)
        {
            // Your API Call code here
    
            Console.WriteLine("WakefulAPIService", "Completed service @ " + SystemClock.ElapsedRealtime());
            Android.Support.V4.Content.WakefulBroadcastReceiver.CompleteWakefulIntent(intent);
        }
    }
    

    OnBootReceiver - 确保在设备重启后再次设置警报

    [BroadcastReceiver(Enabled = true)]
    [IntentFilter(new[] { "android.intent.action.BOOT_COMPLETED", "android.intent.action.QUICKBOOT_POWERON" })]
    class OnBootReceiver : BroadcastReceiver
    {
    
        public override void OnReceive(Context context, Intent intent)
        {
            Console.WriteLine("On Boot Reveiver", "Alarm Set Again after Reboot");
            var alarmHelper = new AlarmHelper();
            alarmHelper.SetAlarm();
        }
    
    }
    

    此工作所需的权限是' RECEIVE_BOOT_COMPLETED'和' WAKE_LOCK'

答案 1 :(得分:1)

在这种情况下,对于 Android ,您可以使用JobScheduler,请参见此类

[Service(Name = "com.xamarin.samples.downloadscheduler.DownloadJob", 
         Permission = "android.permission.BIND_JOB_SERVICE")]
public class DownloadJob : JobService
{
    public override bool OnStartJob(JobParameters jobParams)
    {            
        Task.Run(() =>
        {
            //Your periodic task here
        });

        return true;  
    }

    public override bool OnStopJob(JobParameters jobParams)
    {
        //true so we re-schedule the task
        return true; 
    }
}

然后您可以创建一个工厂来调用此服务。

public static class ReadLocationSchedulerFactory
    {
        public static JobInfo.Builder CreateJobBuilderUsingJobId<T>(this Context context, int jobId) where T : JobService
        {
            var javaClass = Java.Lang.Class.FromType(typeof(T));
            var componentName = new ComponentName(context, javaClass);
            return new JobInfo.Builder(jobId, componentName);
        }

    }

然后在您的主要活动中,必须致电工厂。

protected override void OnCreate(Bundle bundle)
        {                                
            base.OnCreate(bundle);

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App172S.App());

            #region Scheduler

            var jobBuilder = this.CreateJobBuilderUsingJobId<ReadLocationScheduler>(152);
            //This means each 20 mins                
            jobBuilder.SetPeriodic(20 * 60 * 1000); 
            //Persists over phone restarts
            jobBuilder.SetPersisted(true); 
            //If Fails re-try each 2 mins
            jobBuilder.SetBackoffCriteria(120 * 1000, BackoffPolicy.Linear); 
            var jobInfo = jobBuilder.Build();

            var jobScheduler = (JobScheduler)GetSystemService(JobSchedulerService);
            jobScheduler.Cancel(152);
            var scheduleResult = jobScheduler.Schedule(jobInfo);

            if (JobScheduler.ResultSuccess == scheduleResult)
            {
                //If OK maybe show a msg
            }
            else
            {
               //If Failed do something
            }

            #endregion

        }