Firebase Job Dispatcher

In diesem Leitfaden wird erläutert, wie Sie Hintergrundarbeiten mithilfe der Firebase Job Dispatcher-Bibliothek von Google planen.

Übersicht

Eine der besten Möglichkeiten, um eine Android-Anwendung auf den Benutzer reagieren zu lassen, besteht darin, sicherzustellen, dass komplexe oder lang andauernde Arbeiten im Hintergrund ausgeführt werden. Es ist jedoch wichtig, dass sich Hintergrundarbeit nicht negativ auf die Benutzerfreundlichkeit mit dem Gerät auswirkt.

Beispielsweise kann ein Hintergrundauftrag alle drei oder vier Minuten eine Website abfragen, um Änderungen an einem bestimmten Dataset abzufragen. Dies scheint gut zu sein, hätte jedoch eine katastrophale Auswirkung auf die Akkulaufzeit. Die Anwendung wird das Gerät wiederholt reaktivieren, die CPU in einen höheren Leistungszustand versetzen, die Funkgeräte einschalten, netzwerkanforderungen stellen und dann die Ergebnisse verarbeiten. Es wird schlimmer, da das Gerät nicht sofort heruntergefahren wird und in den Leerlaufzustand mit geringer Leistung zurückkehrt. Schlecht geplante Hintergrundarbeit kann das Gerät versehentlich in einem Zustand mit unnötigen und übermäßigen Stromanforderungen halten. Diese scheinbar unschuldige Aktivität (Das Abrufen einer Website) wird das Gerät in relativ kurzer Zeit unbrauchbar machen.

Android stellt die folgenden APIs bereit, um die Ausführung von Arbeiten im Hintergrund zu unterstützen, aber sie allein reichen für eine intelligente Auftragsplanung nicht aus.

  • Absichtsdienste : Absichtsdienste eignen sich hervorragend für die Ausführung der Arbeit, bieten jedoch keine Möglichkeit, Die Arbeit zu planen.
  • AlarmManager : Diese APIs ermöglichen nur die Planung der Arbeit, bieten jedoch keine Möglichkeit, die Arbeit tatsächlich auszuführen. Außerdem lässt der AlarmManager nur zeitbasierte Einschränkungen zu, was bedeutet, dass ein Alarm zu einem bestimmten Zeitpunkt oder nach Ablauf eines bestimmten Zeitraums ausgelöst wird.
  • JobScheduler : JobSchedule ist eine großartige API, die mit dem Betriebssystem zum Planen von Aufträgen arbeitet. Es ist jedoch nur für Android-Apps verfügbar, die auf API-Ebene 21 oder höher abzielen.
  • Broadcast Receivers : Eine Android-App kann Rundfunkempfänger einrichten, um Arbeiten als Reaktion auf systemweite Ereignisse oder Absichten auszuführen. Sendeempfänger bieten jedoch keine Kontrolle darüber, wann der Auftrag ausgeführt werden soll. Änderungen am Android-Betriebssystem schränken außerdem ein, wann Rundfunkempfänger funktionieren oder auf welche Arten von Aufgaben sie reagieren können.

Es gibt zwei wichtige Features für die effiziente Ausführung von Hintergrundarbeiten (manchmal auch als Hintergrundauftrag oder Auftrag bezeichnet):

  1. Intelligente Planung der Arbeit – Es ist wichtig, dass eine Anwendung, die im Hintergrund arbeitet, dies als guter Bürger tut. Im Idealfall sollte die Anwendung nicht verlangen, dass ein Auftrag ausgeführt wird. Stattdessen sollte die Anwendung Bedingungen angeben, die erfüllt werden müssen, wenn der Auftrag ausgeführt werden kann, und dann die Ausführung der Arbeit planen, wenn die Bedingungen erfüllt sind. Dies ermöglicht Android eine intelligente Ausführung von Arbeiten. Netzwerkanforderungen können beispielsweise im Batch ausgeführt werden, um alle gleichzeitig auszuführen, um den mit dem Netzwerk verbundenen Mehraufwand maximal zu nutzen.
  2. Kapselung der Arbeit : Der Code zum Ausführen der Hintergrundarbeiten sollte in eine diskrete Komponente gekapselt werden, die unabhängig von der Benutzeroberfläche ausgeführt werden kann und relativ einfach neu geplant werden kann, wenn die Arbeit aus irgendeinem Grund nicht abgeschlossen werden kann.

Der Firebase-Auftragsverteiler ist eine Bibliothek von Google, die eine fluent-API bietet, um die Planung von Hintergrundarbeiten zu vereinfachen. Es ist als Ersatz für Google Cloud Manager vorgesehen. Der Firebase-Auftragsverteiler besteht aus den folgenden APIs:

  • A Firebase.JobDispatcher.JobService ist eine abstrakte Klasse, die mit der Logik erweitert werden muss, die im Hintergrundauftrag ausgeführt wird.
  • Ein Firebase.JobDispatcher.JobTrigger gibt an, wann der Auftrag gestartet werden soll. Dies wird in der Regel als Zeitfenster ausgedrückt, z. B. warten Sie mindestens 30 Sekunden, bevor Sie den Auftrag starten, aber den Auftrag innerhalb von 5 Minuten ausführen.
  • Ein Firebase.JobDispatcher.RetryStrategy enthält Informationen dazu, was ausgeführt werden sollte, wenn ein Auftrag nicht ordnungsgemäß ausgeführt werden kann. Die Wiederholungsstrategie gibt an, wie lange gewartet werden soll, bevor versucht wird, den Auftrag erneut auszuführen.
  • A Firebase.JobDispatcher.Constraint ist ein optionaler Wert, der eine Bedingung beschreibt, die erfüllt sein muss, bevor der Auftrag ausgeführt werden kann, z. B. dass sich das Gerät in einem nicht gemessenen Netzwerk befindet oder aufgeladen wird.
  • Ist Firebase.JobDispatcher.Job eine API, die die vorherigen APIs in einer Arbeitseinheit vereint, die von JobDispatchergeplant werden kann. Die Job.Builder -Klasse wird verwendet, um ein Jobzu instanziieren.
  • A Firebase.JobDispatcher.JobDispatcher verwendet die vorherigen drei APIs, um die Arbeit mit dem Betriebssystem zu planen und bei Bedarf Aufträge abzubrechen.

Um die Arbeit mit dem Firebase-Auftragsverteiler zu planen, muss eine Xamarin.Android-Anwendung den Code in einen Typ kapseln, der die JobService Klasse erweitert. JobService verfügt über drei Lebenszyklusmethoden, die während der Lebensdauer des Auftrags aufgerufen werden können:

  • bool OnStartJob(IJobParameters parameters) – Diese Methode ist der Ort, an dem die Arbeit stattfindet und immer implementiert werden sollte. Sie wird im Standard-Thread ausgeführt. Diese Methode gibt zurück true , wenn noch Arbeit vorhanden ist oder false wenn die Arbeit erledigt ist.
  • bool OnStopJob(IJobParameters parameters) – Dies wird aufgerufen, wenn der Auftrag aus irgendeinem Grund beendet wird. Es sollte zurückgegeben true werden, wenn der Auftrag für einen späteren Zeitpunkt neu geplant werden soll.
  • JobFinished(IJobParameters parameters, bool needsReschedule) – Diese Methode wird aufgerufen, wenn die JobService asynchrone Arbeit abgeschlossen hat.

Um einen Auftrag zu planen, instanziieren sie ein JobDispatcher Objekt. Anschließend wird ein Job.Builder verwendet, um ein Job -Objekt zu erstellen, das für das JobDispatcher bereitgestellt wird, das versucht, die Ausführung des Auftrags zu planen.

In diesem Leitfaden wird erläutert, wie Sie den Firebase-Auftragsverteiler zu einer Xamarin.Android-Anwendung hinzufügen und zum Planen von Hintergrundarbeiten verwenden.

Anforderungen

Für den Firebase-Auftragsverteiler ist die Android-API-Ebene 9 oder höher erforderlich. Die Firebase Job Dispatcher-Bibliothek basiert auf einigen Komponenten, die von Google Play Services bereitgestellt werden. Auf dem Gerät muss Google Play Services installiert sein.

Verwenden der Firebase-Auftragsverteilerbibliothek in Xamarin.Android

Fügen Sie zunächst das NuGet-Paket Xamarin.Firebase.JobDispatcher zum Xamarin.Android-Projekt hinzu, um mit dem Firebase-Auftragsverteiler zu beginnen. Suchen Sie im NuGet-Paket-Manager nach dem Paket Xamarin.Firebase.JobDispatcher (das sich noch in der Vorabversion befindet).

Nachdem Sie die Firebase Job Dispatcher-Bibliothek hinzugefügt haben, erstellen Sie eine JobService Klasse, und planen Sie die Ausführung mit einer instance von FirebaseJobDispatcher.

Erstellen eines JobService

Alle von der Firebase Job Dispatcher-Bibliothek ausgeführten Arbeiten müssen in einem Typ ausgeführt werden, der die Firebase.JobDispatcher.JobService abstrakte Klasse erweitert. Das Erstellen eines JobService ähnelt dem Erstellen eines Service mit dem Android-Framework:

  1. Erweitern der JobService Klasse
  2. Dekorieren Sie die Unterklasse mit .ServiceAttribute Obwohl nicht unbedingt erforderlich, wird empfohlen, den Parameter explizit festzulegen, um beim Name Debuggen von JobServicezu helfen.
  3. Fügen Sie einen IntentFilter hinzu, um den JobService im AndroidManifest.xmlzu deklarieren. Dies hilft der Firebase Job Dispatcher-Bibliothek auch beim Suchen und Aufrufen von JobService.

Der folgende Code ist ein Beispiel für die einfachsten JobService für eine Anwendung, die die TPL zum asynchronen Ausführen von Aufgaben verwendet:

[Service(Name = "com.xamarin.fjdtestapp.DemoJob")]
[IntentFilter(new[] {FirebaseJobServiceIntent.Action})]
public class DemoJob : JobService
{
    static readonly string TAG = "X:DemoService";

    public override bool OnStartJob(IJobParameters jobParameters)
    {
        Task.Run(() =>
        {
            // Work is happening asynchronously (code omitted)
                       
        });

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

    public override bool OnStopJob(IJobParameters jobParameters)
    {
        Log.Debug(TAG, "DemoJob::OnStartJob");
        // nothing to do.
        return false;
    }
}

Erstellen eines FirebaseJobDispatchers

Bevor eine Arbeit geplant werden kann, muss ein Firebase.JobDispatcher.FirebaseJobDispatcher Objekt erstellt werden. Der FirebaseJobDispatcher ist für das Planen von verantwortlich JobService. Der folgende Codeausschnitt ist eine Möglichkeit, eine instance des FirebaseJobDispatcherzu erstellen:

// This is the "Java" way to create a FirebaseJobDispatcher object
IDriver driver = new GooglePlayDriver(context);
FirebaseJobDispatcher dispatcher = new FirebaseJobDispatcher(driver);

Im vorherigen Codeausschnitt ist die GooglePlayDriver Is-Klasse, die die FirebaseJobDispatcher Interaktion mit einigen der Planungs-APIs in Google Play Services auf dem Gerät unterstützt. Der Parameter context ist ein beliebiger Android-Parameter Context, z. B. eine Aktivität. Derzeit ist dies GooglePlayDriver die einzige IDriver Implementierung in der Firebase Job Dispatcher-Bibliothek.

Die Xamarin.Android-Bindung für den Firebase-Auftragsverteiler stellt eine Erweiterungsmethode bereit, um eine FirebaseJobDispatcher aus dem Contextzu erstellen:

FirebaseJobDispatcher dispatcher = context.CreateJobDispatcher();

Nachdem die FirebaseJobDispatcher instanziiert wurde, ist es möglich, einen Job zu erstellen und den Code in der JobService -Klasse auszuführen. Wird Job von einem Job.Builder -Objekt erstellt und wird im nächsten Abschnitt erläutert.

Erstellen eines Firebase.JobDispatcher.Job mit dem Job.Builder

Die Firebase.JobDispatcher.Job -Klasse ist für die Kapselung der Metadaten verantwortlich, die zum Ausführen eines JobServiceerforderlich sind. EinJob enthält Informationen wie alle Einschränkungen, die erfüllt werden müssen, bevor der Auftrag ausgeführt werden kann, wenn der Job wiederholt wird, oder alle Trigger, die dazu führen, dass der Auftrag ausgeführt wird. Als absolutes Minimum muss ein Job-Tag (eine eindeutige Zeichenfolge, die den Auftrag mit dem FirebaseJobDispatcheridentifiziert) und den Typ des verfügen, der JobService ausgeführt werden soll. Der Firebase-Auftragsverteiler instanziiert den JobService , wenn der Auftrag ausgeführt werden soll. Ein Job wird mithilfe eines instance der Firebase.JobDispatcher.Job.JobBuilder -Klasse erstellt.

Der folgende Codeausschnitt ist das einfachste Beispiel für das Erstellen eines Job mithilfe der Xamarin.Android-Bindung:

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .Build();

Die Job.Builder führt einige grundlegende Überprüfungen der Eingabewerte für den Auftrag durch. Eine Ausnahme wird ausgelöst, wenn es nicht möglich Job.Builder ist, einen Jobzu erstellen. Erstellt Job.Builder ein Job mit den folgenden Standardwerten:

  • Die JobLebensdauer eines Geräts (wie lange die Ausführung geplant ist) dauert nur, bis das Gerät neu gestartet wird – sobald das Gerät neu gestartet wird, geht der Job verloren.
  • A Job wiederholt sich nicht – es wird nur einmal ausgeführt.
  • A Job wird so bald wie möglich ausgeführt.
  • Die Standardmäßige Wiederholungsstrategie für eine Job besteht darin, einen exponentiellen Backoff zu verwenden (ausführlichere Informationen finden Sie weiter unten im Abschnitt Festlegen einer Wiederholungsstrategie).

Planen eines Auftrags

Nach dem Erstellen von muss es Jobmit dem FirebaseJobDispatcher geplant werden, bevor es ausgeführt wird. Es gibt zwei Methoden zum Planen eines Job:

// This will throw an exception if there was a problem scheduling the job
dispatcher.MustSchedule(myJob);

// This method will not throw an exception; an integer result value is returned
int scheduleResult = dispatcher.Schedule(myJob);

Der von FirebaseJobDispatcher.Schedule zurückgegebene Wert ist einer der folgenden ganzzahligen Werte:

  • FirebaseJobDispatcher.ScheduleResultSuccess – Die Job wurde erfolgreich geplant.
  • FirebaseJobDispatcher.ScheduleResultUnknownError – Es ist ein unbekanntes Problem aufgetreten, das verhinderte, dass das Job geplant wurde.
  • FirebaseJobDispatcher.ScheduleResultNoDriverAvailable – Ein ungültiges IDriver wurde verwendet oder war IDriver irgendwie nicht verfügbar.
  • FirebaseJobDispatcher.ScheduleResultUnsupportedTrigger – Die Trigger wurde nicht unterstützt.
  • FirebaseJobDispatcher.ScheduleResultBadService – Der Dienst ist nicht ordnungsgemäß konfiguriert oder nicht verfügbar.

Konfigurieren eines Auftrags

Es ist möglich, einen Auftrag anzupassen. Beispiele für die Anpassung eines Auftrags sind die folgenden:

Jedes dieser Themen wird in den folgenden Abschnitten näher erläutert.

Übergeben von Parametern an einen Auftrag

Parameter werden an einen Auftrag übergeben, indem ein Bundle erstellt wird, der zusammen mit der Job.Builder.SetExtras -Methode übergeben wird:

Bundle jobParameters = new Bundle();
jobParameters.PutInt(FibonacciCalculatorJob.FibonacciPositionKey, 25);

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetExtras(jobParameters)
                      .Build();

Der Bundle Zugriff erfolgt über die IJobParameters.Extras -Eigenschaft der OnStartJob -Methode:

public override bool OnStartJob(IJobParameters jobParameters)
{
    int position = jobParameters.Extras.GetInt(FibonacciPositionKey, DEFAULT_VALUE);
    
    // rest of code omitted
} 

Festlegen von Einschränkungen

Einschränkungen können dazu beitragen, die Kosten oder den Akkuverbrauch des Geräts zu reduzieren. Die Firebase.JobDispatcher.Constraint -Klasse definiert diese Einschränkungen als ganzzahlige Werte:

  • Constraint.OnUnmeteredNetwork – Führen Sie den Auftrag nur aus, wenn das Gerät mit einem nicht gemessenen Netzwerk verbunden ist. Dies ist nützlich, um zu verhindern, dass dem Benutzer Datengebühren anfallen.
  • Constraint.OnAnyNetwork – Führen Sie den Auftrag in jedem Netzwerk aus, mit dem das Gerät verbunden ist. Wenn dieser Wert zusammen mit Constraint.OnUnmeteredNetworkangegeben wird, hat dieser Wert Priorität.
  • Constraint.DeviceCharging – Führen Sie den Auftrag nur aus, wenn das Gerät aufgeladen wird.

Einschränkungen werden mit der Job.Builder.SetConstraint -Methode festgelegt:

Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetConstraint(Constraint.DeviceCharging)
                      .Build();

Stellt JobTrigger dem Betriebssystem Anleitungen darüber bereit, wann der Auftrag gestartet werden soll. Ein JobTrigger verfügt über ein ausführungsfähiges Fenster , das einen geplanten Zeitpunkt für die Ausführung von Job definiert. Das Ausführungsfenster verfügt über einen Startfensterwert und einen Endfensterwert . Das Startfenster ist die Anzahl der Sekunden, die das Gerät warten soll, bevor der Auftrag ausgeführt wird, und der Wert für das Endfenster ist die maximale Anzahl von Sekunden, die vor dem Ausführen von Jobgewartet werden soll.

Ein JobTrigger kann mit der Firebase.Jobdispatcher.Trigger.ExecutionWindow -Methode erstellt werden. Beispielsweise Trigger.ExecutionWindow(15,60) bedeutet, dass der Auftrag zwischen 15 und 60 Sekunden nach der Planung ausgeführt werden soll. Die Job.Builder.SetTrigger -Methode wird verwendet, um

JobTrigger myTrigger = Trigger.ExecutionWindow(15,60);
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetTrigger(myTrigger)
                      .Build();

Der Standardwert JobTrigger für einen Auftrag wird durch den -Wert Trigger.Nowdargestellt, der angibt, dass ein Auftrag so bald wie möglich nach dem Geplanten ausgeführt wird.

Festlegen einer RetryStrategy

Wird Firebase.JobDispatcher.RetryStrategy verwendet, um anzugeben, wie viel Verzögerung ein Gerät verwenden soll, bevor versucht wird, einen fehlgeschlagenen Auftrag erneut auszuführen. Eine RetryStrategy verfügt über eine Richtlinie, die definiert, welcher Zeitbasisalgorithmus verwendet wird, um den fehlgeschlagenen Auftrag neu zu planen, und ein Ausführungsfenster, das ein Fenster angibt, in dem der Auftrag geplant werden soll. Dieses Neuplanungsfenster wird durch zwei Werte definiert. Der erste Wert ist die Anzahl der Sekunden, die gewartet werden müssen, bevor der Auftrag neu geplant wird (der anfängliche Backoffwert ), und die zweite Zahl ist die maximale Anzahl von Sekunden, bevor der Auftrag ausgeführt werden muss (der maximale Backoffwert ).

Die beiden Typen von Wiederholungsrichtlinien werden durch die folgenden int-Werte identifiziert:

  • RetryStrategy.RetryPolicyExponential – Eine exponentielle Backoffrichtlinie erhöht den anfänglichen Backoffwert nach jedem Fehler exponentiell. Wenn ein Auftrag zum ersten Mal fehlschlägt, wartet die Bibliothek das angegebene _initial Intervall, bevor der Auftrag neu geplant wird (Beispiel: 30 Sekunden). Wenn der Auftrag zum zweiten Mal fehlschlägt, wartet die Bibliothek mindestens 60 Sekunden, bevor sie versucht, den Auftrag auszuführen. Nach dem dritten fehlgeschlagenen Versuch wartet die Bibliothek 120 Sekunden usw. Die Standardeinstellung RetryStrategy für die Firebase Job Dispatcher-Bibliothek wird durch das RetryStrategy.DefaultExponential -Objekt dargestellt. Es hat ein anfängliches Backoff von 30 Sekunden und einen maximalen Backoff von 3600 Sekunden.
  • RetryStrategy.RetryPolicyLinear – Bei dieser Strategie handelt es sich um ein lineares Backoff , bei dem der Auftrag so neu geplant werden sollte, dass er in festgelegten Intervallen ausgeführt wird (bis er erfolgreich ist). Linearer Backoff eignet sich am besten für Arbeiten, die so schnell wie möglich abgeschlossen werden müssen, oder für Probleme, die sich schnell von selbst lösen. Die Firebase Job Dispatcher-Bibliothek definiert eine RetryStrategy.DefaultLinear , die über ein Neuplanungsfenster von mindestens 30 Sekunden und bis zu 3600 Sekunden verfügt.

Es ist möglich, eine benutzerdefinierte RetryStrategy mit der FirebaseJobDispatcher.NewRetryStrategy -Methode zu definieren. Es werden drei Parameter benötigt:

  1. int policy – Die Richtlinie ist einer der vorherigen RetryStrategy Werte, RetryStrategy.RetryPolicyLinearoder RetryStrategy.RetryPolicyExponential.
  2. int initialBackoffSeconds – Das anfängliche Backoff ist eine Verzögerung in Sekunden, die erforderlich ist, bevor versucht wird, den Auftrag erneut auszuführen. Der Standardwert hierfür ist 30 Sekunden.
  3. int maximumBackoffSeconds – Der maximale Backoffwert deklariert die maximale Anzahl von Sekunden, die verzögert werden soll, bevor versucht wird, den Auftrag erneut auszuführen. Der Standardwert ist 3600 Sekunden.
RetryStrategy retry = dispatcher.NewRetryStrategy(RetryStrategy.RetryPolicyLinear, initialBackoffSeconds, maximumBackoffSet);

// Create a Job and set the RetryStrategy via the Job.Builder
Job myJob = dispatcher.NewJobBuilder()
                      .SetService<DemoJob>("demo-job-tag")
                      .SetRetryStrategy(retry)
                      .Build();

Abbrechen eines Auftrags

Es ist möglich, alle geplanten Aufträge oder nur einen einzelnen Auftrag mit der FirebaseJobDispatcher.CancelAll() -Methode oder der FirebaseJobDispatcher.Cancel(string) -Methode abzubrechen:

int cancelResult = dispatcher.CancelAll(); 

// to cancel a single job:

int cancelResult = dispatcher.Cancel("unique-tag-for-job");

Beide Methoden geben einen ganzzahligen Wert zurück:

  • FirebaseJobDispatcher.CancelResultSuccess – Der Auftrag wurde erfolgreich abgebrochen.
  • FirebaseJobDispatcher.CancelResultUnknownError – Ein Fehler verhinderte, dass der Auftrag abgebrochen wurde.
  • FirebaseJobDispatcher.CancelResult.NoDriverAvailable – Der FirebaseJobDispatcher kann den Auftrag nicht abbrechen, da kein gültiger IDriver Verfügbar ist.

Zusammenfassung

In diesem Leitfaden wurde erläutert, wie Sie den Firebase-Auftragsverteiler verwenden, um Aufgaben im Hintergrund intelligent auszuführen. Es wurde erläutert, wie die auszuführende Arbeit als JobService gekapselt wird, und wie sie verwendet FirebaseJobDispatcher wird, um diese Arbeit zu planen, wobei die Kriterien mit einer JobTrigger angegeben werden und wie Fehler mit einem RetryStrategybehandelt werden sollen.