Harmonogram zadań dla systemu Android
W tym przewodniku omówiono sposób planowania pracy w tle przy użyciu interfejsu API harmonogramu zadań systemu Android, który jest dostępny na urządzeniach z systemem Android 5.0 (poziom 21 interfejsu API) i nowszym.
Omówienie
Jednym z najlepszych sposobów reagowania aplikacji systemu Android na użytkownika jest zapewnienie, że złożone lub długotrwałe prace są wykonywane w tle. Jednak ważne jest, aby praca w tle nie wpływała negatywnie na środowisko użytkownika z urządzeniem.
Na przykład zadanie w tle może sondować witrynę internetową co trzy lub cztery minuty, aby wykonać zapytanie o zmiany w określonym zestawie danych. Wydaje się to łagodne, jednak miałoby to katastrofalny wpływ na żywotność baterii. Aplikacja będzie wielokrotnie wznawiać urządzenie, podnieść poziom procesora CPU do wyższego stanu zasilania, włączyć urządzenia radiowe, wysyłać żądania sieciowe, a następnie przetwarzać wyniki. Pogarsza się, ponieważ urządzenie nie będzie natychmiast zasilać i wracać do stanu bezczynności o niskiej mocy. Nieprawidłowo zaplanowane prace w tle mogą przypadkowo zachować urządzenie w stanie z niepotrzebnymi i nadmiernymi wymaganiami dotyczącymi zasilania. Ta pozornie niewinna aktywność (sondowanie witryny internetowej) sprawi, że urządzenie będzie bezużyteczne w stosunkowo krótkim czasie.
System Android udostępnia następujące interfejsy API, które ułatwiają wykonywanie pracy w tle, ale same w sobie nie są wystarczające do inteligentnego planowania zadań.
- Intent Services — usługi Intent Services doskonale nadają się do wykonywania pracy, ale nie zapewniają możliwości planowania pracy.
- AlarmManager — te interfejsy API zezwalają tylko na zaplanowanie pracy, ale nie zapewniają możliwości rzeczywistego wykonania pracy. Ponadto menedżer alarmów zezwala tylko na ograniczenia oparte na czasie, co oznacza zgłaszanie alarmu w określonym czasie lub po upływie określonego czasu.
- Odbiorniki rozgłaszań — aplikacja systemu Android może skonfigurować odbiorniki emisji w celu wykonywania pracy w odpowiedzi na zdarzenia lub intencje dla całego systemu. Jednak odbiorniki emisji nie zapewniają żadnej kontroli nad tym, kiedy zadanie powinno zostać uruchomione. Zmiany w systemie operacyjnym Android będą również ograniczać, gdy odbiorniki emisji będą działać lub rodzaje pracy, na które mogą reagować.
Istnieją dwie kluczowe funkcje wydajnego wykonywania pracy w tle (czasami określane jako zadanie w tle lub zadanie):
- Inteligentne planowanie pracy — ważne jest, aby aplikacja wykonywała pracę w tle, co robi jako dobry obywatel. Najlepiej, aby aplikacja nie wymagała uruchomienia zadania. Zamiast tego aplikacja powinna określić warunki, które muszą zostać spełnione, gdy zadanie może zostać uruchomione, a następnie zaplanować to zadanie z systemem operacyjnym, który wykona pracę po spełnieniu warunków. Dzięki temu system Android może uruchomić zadanie w celu zapewnienia maksymalnej wydajności na urządzeniu. Na przykład żądania sieciowe mogą być wsadowe do uruchamiania wszystkich w tym samym czasie, aby maksymalnie wykorzystać obciążenie związane z siecią.
- Hermetyzowanie pracy — kod do wykonania pracy w tle powinien być hermetyzowany w dyskretnym składniku, który można uruchomić niezależnie od interfejsu użytkownika i będzie stosunkowo łatwy do ponownego przygotowania, jeśli praca nie zostanie ukończona z jakiegoś powodu.
Harmonogram zadań systemu Android to struktura wbudowana w system operacyjny Android, który zapewnia płynny interfejs API umożliwiający uproszczenie planowania pracy w tle. Harmonogram zadań systemu Android składa się z następujących typów:
- Jest
Android.App.Job.JobScheduler
to usługa systemowa używana do planowania, wykonywania i w razie potrzeby anulowania zadań w imieniu aplikacji systemu Android. - Jest
Android.App.Job.JobService
to abstrakcyjna klasa, która musi zostać rozszerzona o logikę, która będzie uruchamiać zadanie w głównym wątku aplikacji. Oznacza to, żeJobService
element jest odpowiedzialny za sposób asynchronicznego wykonywania pracy. - Obiekt
Android.App.Job.JobInfo
zawiera kryteria, które należy kierować systemem Android, gdy zadanie powinno zostać uruchomione.
Aby zaplanować pracę z harmonogramem zadań systemu Android, aplikacja platformy Xamarin.Android musi hermetyzować kod w klasie, która rozszerza klasę JobService
. JobService
ma trzy metody cyklu życia, które mogą być wywoływane w okresie istnienia zadania:
bool OnStartJob(Parametry JobParameters) — ta metoda jest wywoływana przez
JobScheduler
metodę do wykonania pracy i uruchamiana w głównym wątku aplikacji. Jest to odpowiedzialnośćJobService
za asynchroniczne wykonywanie pracy i powróttrue
, jeśli istnieje praca pozostała, lubfalse
jeśli praca jest wykonywana.Gdy
JobScheduler
wywoła tę metodę, będzie żądać i zachować wakelock z systemu Android na czas trwania zadania. Po zakończeniu zadania należyJobService
poinformowaćJobScheduler
o tym fakt przez wywołanieJobFinished
metody (opisanej dalej).JobFinished(Parametry JobParameters, bool needsReschedule) — ta metoda musi być wywoływana przez parametr ,
JobService
aby poinformowaćJobScheduler
, że praca jest wykonywana. JeśliJobFinished
nie zostanie wywołana,JobScheduler
nie spowoduje to usunięcia blokady, co powoduje niepotrzebne opróżnienie baterii.bool OnStopJob(Parametry JobParameters) — jest to wywoływane, gdy zadanie jest przedwcześnie zatrzymane przez system Android. Powinna zostać zwrócona
true
, jeśli zadanie powinno zostać ponownie ułożone na podstawie kryteriów ponawiania (omówione poniżej bardziej szczegółowo).
Istnieje możliwość określenia ograniczeń lub wyzwalaczy , które będą kontrolować, kiedy zadanie może lub powinno zostać uruchomione. Na przykład można ograniczyć zadanie tak, aby było uruchamiane tylko wtedy, gdy urządzenie jest ładowane, lub uruchamiać zadanie po zrobieniu zdjęcia.
W tym przewodniku szczegółowo omówiono sposób implementowania JobService
klasy i planowania jej za pomocą klasy JobScheduler
.
Wymagania
Harmonogram zadań systemu Android wymaga interfejsu API systemu Android na poziomie 21 (Android 5.0) lub nowszego.
Korzystanie z harmonogramu zadań systemu Android
Istnieją trzy kroki dotyczące korzystania z interfejsu API jobScheduler systemu Android:
- Zaimplementuj typ usługi JobService, aby hermetyzować pracę.
JobInfo.Builder
Użyj obiektu , aby utworzyćJobInfo
obiekt, który będzie przechowywać kryteria uruchamianiaJobScheduler
zadania.- Zaplanuj zadanie przy użyciu polecenia
JobScheduler.Schedule
.
Implementowanie usługi jobService
Wszystkie prace wykonywane przez bibliotekę harmonogramu zadań systemu Android muszą być wykonywane w typie rozszerzającym klasę abstrakcyjną Android.App.Job.JobService
. Tworzenie elementu JobService
jest bardzo podobne do tworzenia za Service
pomocą platformy systemu Android:
- Rozszerz klasę
JobService
. - Dekoruj podklasę za pomocą parametru
ServiceAttribute
i ustawName
parametr na ciąg składający się z nazwy pakietu i nazwy klasy (zobacz poniższy przykład). Permission
Ustaw właściwość w obiekcie naServiceAttribute
ciągandroid.permission.BIND_JOB_SERVICE
.- Zastąpij metodę
OnStartJob
, dodając kod, aby wykonać pracę. System Android wywoła tę metodę w głównym wątku aplikacji w celu uruchomienia zadania. Praca, która potrwa dłużej niż kilka milisekund, powinna zostać wykonana w wątku, aby uniknąć blokowania aplikacji. - Po zakończeniu
JobService
pracy metoda musi wywołać metodęJobFinished
. Ta metoda informujeJobService
o wykonaniuJobScheduler
tej pracy. Brak wywołaniaJobFinished
spowodujeJobService
wprowadzenie niepotrzebnych wymagań na urządzeniu, skracając żywotność baterii. - Dobrym pomysłem jest również zastąpienie
OnStopJob
metody . Ta metoda jest wywoływana przez system Android, gdy zadanie jest zamykane przed jego zakończeniem i zapewniaJobService
możliwość prawidłowego usuwania wszystkich zasobów. Ta metoda powinna zwrócićtrue
, jeśli konieczne jest ponowne zaplanowanie zadania lubfalse
jeśli nie jest pożądane ponowne uruchomienie zadania.
Poniższy kod jest przykładem najprostszego JobService
dla aplikacji, używając języka TPL do asynchronicznego wykonywania pewnych zadań:
[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;
}
}
Tworzenie informacji o zadaniu w celu zaplanowana zadania
Aplikacje platformy Xamarin.Android nie tworzą wystąpienia JobService
bezpośrednio, zamiast tego przekażą JobInfo
obiekt do JobScheduler
obiektu . Spowoduje JobScheduler
to utworzenie wystąpienia żądanego JobService
obiektu, zaplanowanie i uruchomienie JobService
zgodnie z metadanymi w obiekcie JobInfo
. Obiekt JobInfo
musi zawierać następujące informacje:
- JobId — jest
int
to wartość używana do identyfikowania zadania w obiekcieJobScheduler
. Ponowne przy użyciu tej wartości spowoduje zaktualizowanie wszystkich istniejących zadań. Wartość musi być unikatowa dla aplikacji. - JobService — ten parametr to
ComponentName
parametr, który jawnie identyfikuje typ, któregoJobScheduler
należy użyć do uruchomienia zadania.
Ta metoda rozszerzenia pokazuje, jak utworzyć element JobInfo.Builder
z systemem Android Context
, na przykład Działanie:
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.
Zaawansowaną funkcją harmonogramu zadań systemu Android jest możliwość kontrolowania, kiedy zadanie jest uruchamiane lub w jakich warunkach może zostać uruchomione zadanie. W poniższej tabeli opisano niektóre metody, które JobInfo.Builder
umożliwiają aplikacji wywieranie wpływu na uruchomienie zadania:
Metoda | opis |
---|---|
SetMinimumLatency |
Określa, że opóźnienie (w milisekundach), które należy zaobserwować przed uruchomieniem zadania. |
SetOverridingDeadline |
Deklaruje, że zadanie musi zostać uruchomione przed upływem tego czasu (w milisekundach). |
SetRequiredNetworkType |
Określa wymagania dotyczące sieci dla zadania. |
SetRequiresBatteryNotLow |
Zadanie może być uruchamiane tylko wtedy, gdy urządzenie nie wyświetla użytkownikowi ostrzeżenia o "niskiej baterii". |
SetRequiresCharging |
Zadanie może działać tylko wtedy, gdy bateria jest ładowana. |
SetDeviceIdle |
Zadanie zostanie uruchomione, gdy urządzenie jest zajęte. |
SetPeriodic |
Określa, że zadanie powinno być regularnie uruchamiane. |
SetPersisted |
Zadanie powinno być perisistą w przypadku ponownych uruchomień urządzeń. |
Zawiera SetBackoffCriteria
kilka wskazówek dotyczących JobScheduler
czasu oczekiwania przed ponownym uruchomieniem zadania. Istnieją dwie części kryteriów wycofywania: opóźnienie w milisekundach (wartość domyślna 30 sekund) i typ wycofywania, który powinien być używany (czasami określany jako zasady wycofywania lub zasady ponawiania). Te dwie zasady są hermetyzowane w wyliczeniem Android.App.Job.BackoffPolicy
:
BackoffPolicy.Exponential
— Zasady wycofywania wykładniczego zwiększą początkową wartość wycofywania wykładniczo po każdym niepowodzeniu. Podczas pierwszego niepowodzenia zadania biblioteka będzie czekać początkowy interwał określony przed ponownym zaplanowaniem zadania — na przykład 30 sekund. Po raz drugi zadanie zakończy się niepowodzeniem, biblioteka będzie czekać co najmniej 60 sekund przed próbą uruchomienia zadania. Po trzeciej nieudanej próbie biblioteka będzie czekać 120 sekund itd. Jest to wartość domyślna.BackoffPolicy.Linear
— Ta strategia jest liniowym wycofywaniem, które powinno zostać ponownie zaplanowane, aby zadanie było uruchamiane w ustalonych odstępach czasu (dopóki nie powiedzie się). Wycofywanie liniowe najlepiej nadaje się do pracy, która musi zostać ukończona tak szybko, jak to możliwe lub w przypadku problemów, które szybko się rozwiążą.
Aby uzyskać więcej informacji na temat tworzenia obiektu, przeczytaj dokumentację JobInfo
firmy Google dotyczącą JobInfo.Builder
klasy.
Przekazywanie parametrów do zadania za pomocą informacji o zadaniu
Parametry są przekazywane do zadania przez utworzenie przekazanego Job.Builder.SetExtras
elementu PersistableBundle
wraz z metodą :
var jobParameters = new PersistableBundle();
jobParameters.PutInt("LoopCount", 11);
var jobBuilder = this.CreateJobBuilderUsingJobId<DownloadJob>(1)
.SetExtras(jobParameters)
.Build();
Dostęp PersistableBundle
do obiektu jest uzyskiwany z Android.App.Job.JobParameters.Extras
właściwości w OnStartJob
metodzie elementu JobService
:
public override bool OnStartJob(JobParameters jobParameters)
{
var loopCount = jobParams.Extras.GetInt("LoopCount", 10);
// rest of code omitted
}
Planowanie zadań
Aby zaplanować zadanie, aplikacja platformy Xamarin.Android uzyska odwołanie do JobScheduler
usługi systemowej i wywoła JobScheduler.Schedule
metodę z JobInfo
obiektem utworzonym w poprzednim kroku. JobScheduler.Schedule
natychmiast zwróci jedną z dwóch wartości całkowitych:
- JobScheduler.ResultSuccess — zadanie zostało pomyślnie zaplanowane.
- JobScheduler.ResultFailure — nie można zaplanować zadania. Jest to zwykle spowodowane przez parametry powodujące konflikt
JobInfo
.
Ten kod jest przykładem planowania zadania i powiadamiania użytkownika o wynikach próby planowania:
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();
}
Anulowanie zadania
Istnieje możliwość anulowania wszystkich zaplanowanych zadań lub tylko jednego zadania przy użyciu JobsScheduler.CancelAll()
metody lub JobScheduler.Cancel(jobId)
metody:
// Cancel all jobs
jobScheduler.CancelAll();
// to cancel a job with jobID = 1
jobScheduler.Cancel(1)
Podsumowanie
W tym przewodniku omówiono sposób użycia harmonogramu zadań systemu Android do inteligentnego wykonywania pracy w tle. Omówiono w nim sposób hermetyzacji pracy, która ma być wykonywana jako element JobService
i jak używać JobScheduler
elementu do planowania tej pracy, określając kryteria za pomocą elementu JobTrigger
oraz sposób obsługi błędów za pomocą elementu RetryStrategy
.