Android Job Scheduler

Tento průvodce popisuje, jak naplánovat práci na pozadí pomocí rozhraní API plánovače úloh Androidu, které je dostupné na zařízeních s Androidem 5.0 (úroveň rozhraní API 21) a vyšší.

Přehled

Jedním z nejlepších způsobů, jak zajistit, aby aplikace pro Android reagovala na uživatele, je zajistit, aby se složitá nebo dlouhotrvající práce prováděla na pozadí. Je však důležité, aby práce na pozadí nezáporně ovlivnila zkušenosti uživatele se zařízením.

Úloha na pozadí se například může dotazovat na web každých tři nebo čtyři minuty a dotazovat se na změny konkrétní datové sady. Zdá se to neškodné, ale mělo by katastrofální dopad na životnost baterie. Aplikace bude zařízení opakovaně probudit, zvýšit výkon procesoru na vyšší stav napájení, zapnout rádia, nastavovat síťové požadavky a pak zpracovávat výsledky. Je to horší, protože zařízení nebude okamžitě vypnout a vrátit se do stavu nečinnosti s nízkým výkonem. Špatně naplánovaná práce na pozadí může neúmyslně udržovat zařízení ve stavu s zbytečnými a nadměrnými požadavky na napájení. Tato zdánlivě nevinná aktivita (dotazování webu) vykreslí zařízení nepoužitelné v relativně krátkém časovém období.

Android poskytuje následující rozhraní API, která pomáhají s prováděním práce na pozadí, ale samy o sobě nejsou dostatečné pro inteligentní plánování úloh.

  • Služby záměru – Služby záměru jsou skvělé pro provádění práce, ale neposkytují žádný způsob plánování práce.
  • AlarmManager – Tato rozhraní API umožňují plánovat pouze práci, ale neposkytují žádný způsob, jak tuto práci skutečně provést. AlarmManager také umožňuje omezení založená na čase, což znamená vyvolání alarmu v určitém čase nebo po uplynutí určitého časového období.
  • Přijímače všesměrového vysílání – Aplikace pro Android může nastavit přijímače vysílání tak, aby fungovaly v reakci na systémové události nebo záměry. Přijímače všesměrového vysílání ale neposkytují žádnou kontrolu nad tím, kdy se má úloha spustit. Změny v operačním systému Android budou také omezeny, když budou příjemci vysílání fungovat, nebo druhy práce, na které můžou reagovat.

Existují dvě klíčové funkce pro efektivní provádění práce na pozadí (někdy označované jako úloha na pozadí nebo úloha):

  1. Inteligentní plánování práce – Je důležité, aby když aplikace pracuje na pozadí, že to dělá jako dobrý občan. V ideálním případě by aplikace neměla požadovat spuštění úlohy. Místo toho by aplikace měla zadat podmínky, které musí být splněny, když je možné úlohu spustit, a pak naplánovat tuto úlohu s operačním systémem, který bude provádět práci při splnění podmínek. Díky tomu může Android spouštět úlohu, aby se zajistila maximální efektivita na zařízení. Například síťové požadavky se můžou dávkově spouštět najednou, aby se maximálně využily režijní náklady spojené se sítěmi.
  2. Zapouzdření práce – kód pro provedení práce na pozadí by měl být zapouzdřen v samostatné komponentě, která může být spuštěna nezávisle na uživatelském rozhraní a bude relativně snadné přeplánovat, pokud se práce z nějakého důvodu nedokončí.

Plánovač úloh Androidu je architektura integrovaná v operačním systému Android, která poskytuje fluentní rozhraní API pro zjednodušení plánování práce na pozadí. Plánovač úloh Androidu se skládá z následujících typů:

  • Jedná se Android.App.Job.JobScheduler o systémovou službu, která se používá k naplánování, spuštění a v případě potřeby zrušení úloh jménem aplikace pro Android.
  • Je Android.App.Job.JobService abstraktní třída, která se musí rozšířit pomocí logiky, která spustí úlohu v hlavním vlákně aplikace. To znamená, že je zodpovědný za to, JobService jak se má práce provádět asynchronně.
  • Objekt Android.App.Job.JobInfo obsahuje kritéria pro vodítko Androidu, když se má úloha spustit.

Chcete-li naplánovat práci s Plánovačem úloh Androidu, musí aplikace Xamarin.Android zapouzdřit kód ve třídě, která rozšiřuje JobService třídu. JobService má tři metody životního cyklu, které lze volat během životnosti úlohy:

  • bool OnStartJob(Parametry JobParameters) – Tato metoda je volána JobScheduler k provádění práce a spouští se v hlavním vlákně aplikace. Je zodpovědností JobService za asynchronní provádění práce a vrácení true , pokud zbývá práce, nebo false pokud je práce hotová.

    JobScheduler Při volání této metody bude požadovat a zachovat wakelock z Androidu po dobu trvání úlohy. Jakmile je úloha dokončena, je zodpovědností JobService sdělit JobScheduler o této skutečnosti voláním JobFinished metody (popsáno dále).

  • JobFinished(Parametry JobParameters, bool needsReschedule) – Tato metoda musí být volána metodou JobService , která říká JobScheduler , že práce je provedena. Pokud JobFinished není volána, JobScheduler neodebere wakelock, což způsobuje zbytečné vyprázdnění baterie.

  • bool OnStopJob(parametry JobParameters) – Volá se, když je úloha předčasně zastavena Androidem. Měla by se vrátit true , pokud by se úloha měla přeplánovat na základě kritérií opakování (podrobněji popsáno níže).

Je možné určit omezení nebo triggery , které řídí, kdy může nebo má být úloha spuštěna. Úlohu je například možné omezit tak, aby se spustila jenom v případě, že se zařízení účtuje nebo spustí úlohu, když se pořídí obrázek.

Tento průvodce podrobně popisuje, jak implementovat JobService třídu a naplánovat ji pomocí JobScheduler.

Požadavky

Plánovač úloh Androidu vyžaduje rozhraní Android API úrovně 21 (Android 5.0) nebo vyšší.

Použití plánovače úloh Androidu

Pro použití rozhraní API Pro Android JobScheduler existují tři kroky:

  1. Implementujte typ JobService pro zapouzdření práce.
  2. JobInfo.Builder Pomocí objektu JobInfo vytvořte objekt, který bude obsahovat kritéria pro JobScheduler spuštění úlohy.
  3. Naplánujte úlohu pomocí JobScheduler.Schedule.

Implementace služby JobService

Veškerá práce prováděná knihovnou plánovače úloh Androidu musí být provedena v typu, který rozšiřuje Android.App.Job.JobService abstraktní třídu. JobService Vytvoření architektury pro Android je velmi podobné vytvoření Service architektury pro Android:

  1. JobService Rozšiřte třídu.
  2. Ozdobte podtřídu ServiceAttribute pomocí a nastavte Name parametr na řetězec, který se skládá z názvu balíčku a názvu třídy (viz následující příklad).
  3. Permission Nastavte vlastnost ServiceAttribute na řetězec android.permission.BIND_JOB_SERVICE.
  4. Přepište metodu OnStartJob přidáním kódu, který provede práci. Android vyvolá tuto metodu v hlavním vlákně aplikace ke spuštění úlohy. Práce, která bude trvat déle, než by mělo být provedeno několik milisekund ve vlákně, aby se zabránilo blokování aplikace.
  5. Po dokončení JobService práce je nutné volat metodu JobFinished . Tato metoda udává JobServiceJobScheduler , že práce se provádí. Když se volání nepovolí JobFinished , způsobí JobService to, že zařízení zbytečně vyžaduje, což zkracuje životnost baterie.
  6. Je vhodné také přepsat metodu OnStopJob . Tato metoda je volána Androidem, když je úloha vypnuta před dokončením a poskytuje JobService příležitost správně odstranit všechny prostředky. Tato metoda by se měla vrátit true , pokud je nutné přeplánovat úlohu, nebo false pokud není žádoucí znovu spustit úlohu.

Následující kód je příkladem nejjednodušší JobService aplikace pomocí TPL k asynchronnímu provádění některých úloh:

[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(() =>
        {
            // Work is happening asynchronously
                      
            // Have to tell the JobScheduler the work is done. 
            JobFinished(jobParams, false);
        });

        // Return true because of the asynchronous work
        return true;  
    }

    public override bool OnStopJob(JobParameters jobParams)
    {
        // we don't want to reschedule the job if it is stopped or cancelled.
        return false; 
    }
}

Vytvoření informace o úloze pro naplánování úlohy

Aplikace Xamarin.Android nenasadí JobService instanci přímo, místo toho předají JobInfo objekt objektu do objektu JobScheduler. Vytvoří JobScheduler instanci požadovaného JobService objektu, plánování a spuštění JobService podle metadat v objektu JobInfo. Objekt JobInfo musí obsahovat následující informace:

  • JobId – jedná se o int hodnotu, která slouží k identifikaci úlohy v objektu JobScheduler. Opětovné nasazení této hodnoty aktualizuje všechny existující úlohy. Hodnota musí být pro aplikaci jedinečná.
  • JobService – tento parametr je ComponentName explicitně identifikuje typ, který JobScheduler má použít ke spuštění úlohy.

Tato metoda rozšíření ukazuje, jak vytvořit pomocí Androidu JobInfo.BuilderContext, například aktivitu:

public static class JobSchedulerHelpers
{
    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);
    }
}

// Sample usage - creates a JobBuilder for a DownloadJob and sets the Job ID to 1.
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1);

var jobInfo = jobBuilder.Build();  // creates a JobInfo object.

Výkonná funkce Plánovače úloh Androidu je schopnost řídit, kdy se úloha spustí nebo za jakých podmínek může úloha běžet. Následující tabulka popisuje některé metody JobInfo.Builder , které aplikaci umožňují ovlivnit, kdy může úloha běžet:

metoda Popis
SetMinimumLatency Určuje, že zpoždění (v milisekundách), které by se mělo sledovat před spuštěním úlohy.
SetOverridingDeadline Deklaruje, že úloha musí běžet před uplynutím této doby (v milisekundách).
SetRequiredNetworkType Určuje síťové požadavky pro úlohu.
SetRequiresBatteryNotLow Úloha se může spustit jenom v případě, že se uživateli nezobrazuje upozornění na nedostatek baterie.
SetRequiresCharging Úloha může běžet pouze při nabíjení baterie.
SetDeviceIdle Úloha se spustí, když je zařízení zaneprázdněné.
SetPeriodic Určuje, že by se úloha měla pravidelně spouštět.
SetPersisted Úloha by měla přecházet mezi restartováním zařízení.

Toto SetBackoffCriteria téma obsahuje několik pokynů k tomu, jak dlouho JobScheduler má čekat, než se pokusíte znovu spustit úlohu. Kritéria pro zpomalování existují dvě části: zpoždění v milisekundách (výchozí hodnota 30 sekund) a typ zpětného vypnutí, který by se měl použít (někdy se označuje jako zásada zpětného odsud nebo zásada opakování). V výčtu Android.App.Job.BackoffPolicy jsou zapouzdřené dvě zásady:

  • BackoffPolicy.Exponential – Exponenciální zásada zpětného odsunutí zvýší počáteční hodnotu backoff exponenciálně po každé chybě. Při prvním selhání úlohy bude knihovna čekat počáteční interval zadaný před opětovným naplánování úlohy – například 30 sekund. Při druhém selhání úlohy knihovna počká aspoň 60 sekund před pokusem o spuštění úlohy. Po třetím neúspěšném pokusu bude knihovna čekat 120 sekund atd. Tato hodnota je výchozí.
  • BackoffPolicy.Linear – Tato strategie představuje lineární zásadu, že by se úloha měla přeplánovat tak, aby běžela v nastavených intervalech (dokud nebude úspěšná). Lineární backoff je nejvhodnější pro práci, která musí být dokončena co nejdříve nebo pro problémy, které se rychle vyřeší.

Další podrobnosti o vytvoření objektu JobInfo najdete v dokumentaci Společnosti Google pro JobInfo.Builder třídu.

Předání parametrů úloze prostřednictvím JobInfo

Parametry se předávají úloze vytvořením předávaného PersistableBundle společně s metodou Job.Builder.SetExtras :

var jobParameters = new PersistableBundle();
jobParameters.PutInt("LoopCount", 11);

var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)
                     .SetExtras(jobParameters)
                     .Build();

Tato PersistableBundle vlastnost je přístupná z Android.App.Job.JobParameters.Extras vlastnosti v OnStartJob metodě JobService:

public override bool OnStartJob(JobParameters jobParameters)
{
    var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
    
    // rest of code omitted
} 

Plánování úlohy

Pokud chcete naplánovat úlohu, aplikace Xamarin.Android získá odkaz na JobScheduler systémovou službu a zavolá metodu JobScheduler.ScheduleJobInfo s objektem vytvořeným v předchozím kroku. JobScheduler.Schedule vrátí okamžitě jednu ze dvou celočíselnou hodnotu:

  • JobScheduler.ResultSuccess – Úloha byla úspěšně naplánována.
  • JobScheduler.ResultFailure – úlohu nebylo možné naplánovat. Příčinou jsou obvykle konfliktní JobInfo parametry.

Tento kód je příkladem plánování úlohy a upozorňování uživatele na výsledky pokusu o plánování:

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

if (JobScheduler.ResultSuccess == scheduleResult)
{
    var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content), Resource.String.jobscheduled_success, Snackbar.LengthShort);
    snackBar.Show();
}
else
{
    var snackBar = Snackbar.Make(FindViewById(Android.Resource.Id.Content), Resource.String.jobscheduled_failure, Snackbar.LengthShort);
    snackBar.Show();
}

Zrušení úlohy

Pomocí metody nebo JobScheduler.Cancel(jobId) metody je možné zrušit všechny naplánované úlohy nebo jenom jednu úlohuJobsScheduler.CancelAll():

// Cancel all jobs
jobScheduler.CancelAll(); 

// to cancel a job with jobID = 1
jobScheduler.Cancel(1)

Shrnutí

Tato příručka popisuje, jak pomocí plánovače úloh Androidu inteligentně provádět práci na pozadí. Popisuje, jak zapouzdřit práci, která má být provedena jako a JobService jak použít JobScheduler k naplánování této práce, určení kritérií a JobTrigger způsob zpracování selhání pomocí RetryStrategy.