Erstellen von Android Services

In diesem Leitfaden werden Xamarin.Android-Dienste erläutert, bei denen es sich um Android-Komponenten handelt, die die Arbeit ohne aktive Benutzeroberfläche ermöglichen. Dienste werden sehr häufig für Aufgaben verwendet, die im Hintergrund ausgeführt werden, z. B. zeitaufwendige Berechnungen, Herunterladen von Dateien, Wiedergeben von Musik usw. Darin werden die verschiedenen Szenarien erläutert, für die Dienste geeignet sind, und es wird gezeigt, wie sie sowohl für die Ausführung von lang andauernden Hintergrundaufgaben als auch für die Bereitstellung einer Schnittstelle für Remoteprozeduraufrufe implementiert werden können.

Übersicht über Android Services

Mobile Apps sind nicht wie Desktop-Apps. Desktops verfügen über eine große Menge an Ressourcen wie Bildschirmimmobilien, Arbeitsspeicher, Speicherplatz und eine verbundene Stromversorgung, mobile Geräte nicht. Diese Einschränkungen zwingen mobile Apps dazu, sich anders zu verhalten. Beispielsweise bedeutet der kleine Bildschirm auf einem mobilen Gerät in der Regel, dass nur eine App (d. h. Aktivität) gleichzeitig sichtbar ist. Andere Aktivitäten werden in den Hintergrund verschoben und in einen angehaltenen Zustand verschoben, in dem sie keine Arbeit ausführen können. Nur weil sich eine Android-Anwendung im Hintergrund befindet, bedeutet dies jedoch nicht, dass es unmöglich ist, dass die App weiterhin funktioniert.

Android-Anwendungen bestehen aus mindestens einer der folgenden vier Hauptkomponenten: Aktivitäten, Rundfunkempfänger, Inhaltsanbieter und Dienste. Aktivitäten sind der Eckpfeiler vieler großartiger Android-Anwendungen, da sie die Benutzeroberfläche bereitstellen, die es einem Benutzer ermöglicht, mit der Anwendung zu interagieren. Wenn es jedoch um die Ausführung gleichzeitiger oder Hintergrundarbeit geht, sind Aktivitäten nicht immer die beste Wahl.

Der primäre Mechanismus für Hintergrundarbeit in Android ist der Dienst. Ein Android-Dienst ist eine Komponente, die für einige Aufgaben ohne Benutzeroberfläche konzipiert ist. Ein Dienst kann eine Datei herunterladen, Musik wiedergeben oder einen Filter auf ein Bild anwenden. Dienste können auch für die Interprocess Communication (IPC) zwischen Android-Anwendungen verwendet werden. Beispielsweise kann eine Android-App den Musikplayerdienst verwenden, der von einer anderen App stammt, oder eine App kann Daten (z. B. die Kontaktinformationen einer Person) über einen Dienst für andere Apps verfügbar machen.

Dienste und ihre Fähigkeit, Hintergrundarbeiten auszuführen, sind von entscheidender Bedeutung für eine reibungslose und flüssige Benutzeroberfläche. Alle Android-Anwendungen verfügen über einen Standard Thread (auch als UI-Thread bezeichnet), auf dem die Aktivitäten ausgeführt werden. Damit das Gerät reaktionsfähig bleibt, muss Android die Benutzeroberfläche mit einer Geschwindigkeit von 60 Frames pro Sekunde aktualisieren können. Wenn eine Android-App zu viel Arbeit für den Standard Threads ausführt, löscht Android Frames, was wiederum dazu führt, dass die Benutzeroberfläche ruckartig erscheint (manchmal auch als Janky bezeichnet). Dies bedeutet, dass alle am UI-Thread ausgeführten Arbeiten in der Zeitspanne zwischen zwei Frames( ca. 16 Millisekunden) (1 Sekunde alle 60 Frames) abgeschlossen werden sollten.

Um dieses Problem zu beheben, kann ein Entwickler Threads in einer Aktivität verwenden, um einige Arbeiten auszuführen, die die Benutzeroberfläche blockieren würden. Dies kann jedoch zu Problemen führen. Es ist sehr möglich, dass Android die mehreren Instanzen der Aktivität zerstört und neu erstellt. Android zerstört die Threads jedoch nicht automatisch, was zu Speicherverlusten führen kann. Ein hervorragendes Beispiel hierfür ist, wenn das Gerät gedreht wird: Android versucht, die instance der Aktivität zu zerstören und dann eine neue neu zu erstellen:

Wenn sich das Gerät dreht, wird instance 1 zerstört und instance 2 erstellt.

Dies ist ein potenzieller Speicherverlust. Der Thread, der vom ersten instance der Aktivität erstellt wurde, wird weiterhin ausgeführt. Wenn der Thread einen Verweis auf den ersten instance der Aktivität enthält, verhindert dies, dass Android das Objekt mit Müll sammelt. Der zweite instance der Aktivität wird jedoch weiterhin erstellt (wodurch wiederum ein neuer Thread erstellt werden kann). Wenn Das Gerät mehrmals in schneller Folge rotiert wird, kann der gesamte RAM erschöpft sein und Android zwingen, die gesamte Anwendung zu beenden, um Arbeitsspeicher zurückzugeben.

Als Faustregel gilt: Wenn die auszuführende Arbeit eine Aktivität überdauern soll, sollte ein Dienst erstellt werden, um diese Arbeit auszuführen. Wenn die Arbeit jedoch nur im Kontext einer Aktivität anwendbar ist, ist das Erstellen eines Threads zum Ausführen der Arbeit möglicherweise geeigneter. Beispielsweise sollte das Erstellen einer Miniaturansicht für ein Foto, das gerade einer Fotogalerie-App hinzugefügt wurde, wahrscheinlich in einem Dienst erfolgen. Ein Thread ist jedoch möglicherweise besser geeignet, um Musik abzuspielen, die nur gehört werden sollte, wenn sich eine Aktivität im Vordergrund befindet.

Hintergrundarbeiten können in zwei allgemeine Klassifizierungen unterteilt werden:

  1. Task mit langer Ausführungsdauer : Dies ist eine Arbeit, die bis zum expliziten Beenden fortgesetzt wird. Ein Beispiel für eine Aufgabe mit langer Ausführungsdauer ist eine App, die Musik streamt oder daten überwachen muss, die von einem Sensor gesammelt wurden. Diese Aufgaben müssen ausgeführt werden, obwohl die Anwendung über keine sichtbare Benutzeroberfläche verfügt.
  2. Periodische Aufgaben – (manchmal auch als Auftrag bezeichnet) Eine periodische Aufgabe ist eine Aufgabe, die relativ kurz (mehrere Sekunden) ist und nach einem Zeitplan ausgeführt wird (d. h. einmal täglich für eine Woche oder vielleicht nur einmal in den nächsten 60 Sekunden). Ein Beispiel hierfür ist das Herunterladen einer Datei aus dem Internet oder das Generieren einer Miniaturansicht für ein Bild.

Es gibt vier verschiedene Arten von Android-Diensten:

  • Gebundener Dienst : Ein gebundener Dienst ist ein Dienst, an den eine andere Komponente (in der Regel eine Aktivität) gebunden ist. Ein gebundener Dienst stellt eine Schnittstelle bereit, die es der gebundenen Komponente und dem Dienst ermöglicht, miteinander zu interagieren. Sobald keine weiteren Clients an den Dienst gebunden sind, wird der Dienst von Android heruntergefahren.

  • IntentService – Ein IntentService ist eine spezialisierte Unterklasse der -Klasse, die Service die Erstellung und Nutzung von Diensten vereinfacht. Ein IntentService soll einzelne autonome Aufrufe verarbeiten. Im Gegensatz zu einem Dienst, der mehrere Aufrufe gleichzeitig verarbeiten kann, ähnelt ein IntentService eher einem Arbeitswarteschlangenprozessor : Die Arbeit wird in die Warteschlange eingereiht und verarbeitet IntentService jeden Auftrag einzeln in einem einzelnen Workerthread. In der Regel ist einIntentService nicht an eine Aktivität oder ein Fragment gebunden.

  • Gestarteter Dienst : Ein gestarteter Dienst ist ein Dienst, der von einer anderen Android-Komponente (z. B. einer Aktivität) gestartet wurde und kontinuierlich im Hintergrund ausgeführt wird, bis der Dienst explizit zum Beenden aufgefordert wird. Im Gegensatz zu einem gebundenen Dienst sind bei einem gestarteten Dienst keine Clients direkt an ihn gebunden. Aus diesem Grund ist es wichtig, gestartete Dienste so zu entwerfen, dass sie bei Bedarf ordnungsgemäß neu gestartet werden können.

  • Hybriddienst : Ein Hybriddienst ist ein Dienst, der die Merkmale eines gestarteten Diensts und eines gebundenen Diensts aufweist. Ein Hybriddienst kann gestartet werden, wenn eine Komponente an ihn gebunden oder von einem Ereignis gestartet wird. Eine Clientkomponente kann an den Hybriddienst gebunden sein oder nicht. Ein Hybriddienst wird so lange ausgeführt, bis er explizit zum Beenden aufgefordert wird oder bis keine weiteren Clients mehr an ihn gebunden sind.

Welcher Diensttyp verwendet werden soll, hängt stark von den Anwendungsanforderungen ab. Als Faustregel gilt, dass ein IntentService oder ein gebundener Dienst für die meisten Aufgaben ausreicht, die eine Android-Anwendung ausführen muss. Daher sollte einer dieser beiden Arten von Diensten vorrangt werden. Ein IntentService ist eine gute Wahl für "One-Shot"-Aufgaben, z. B. das Herunterladen einer Datei, während ein gebundener Dienst geeignet wäre, wenn häufige Interaktionen mit einer Aktivität/einem Fragment erforderlich sind.

Während die meisten Dienste im Hintergrund ausgeführt werden, gibt es eine spezielle Unterkategorie, die als Vordergrunddienst bezeichnet wird. Dies ist ein Dienst, dem (im Vergleich zu einem normalen Dienst) eine höhere Priorität eingeräumt wird, um einige Aufgaben für den Benutzer auszuführen (z. B. musikwiedergabe).

Es ist auch möglich, einen Dienst in einem eigenen Prozess auf demselben Gerät auszuführen. Dies wird manchmal als Remotedienst oder als Out-of-Process-Dienst bezeichnet. Dies erfordert mehr Aufwand bei der Erstellung, kann aber nützlich sein, wenn eine Anwendung Funktionen für andere Anwendungen freigeben muss, und kann in einigen Fällen die Benutzerfreundlichkeit einer Anwendung verbessern.

Einschränkungen für die Hintergrundausführung in Android 8.0

Ab Android 8.0 (API-Ebene 26) kann eine Android-Anwendung nicht mehr frei im Hintergrund ausgeführt werden. Im Vordergrund kann eine App Dienste ohne Einschränkung starten und ausführen. Wenn eine Anwendung in den Hintergrund wechselt, gewährt Android der App eine bestimmte Zeit zum Starten und Verwenden von Diensten. Sobald diese Zeit verstrichen ist, kann die App keine Dienste mehr starten, und alle gestarteten Dienste werden beendet. Zu diesem Zeitpunkt ist es für die App nicht möglich, irgendwelche Arbeiten auszuführen. Android betrachtet eine Anwendung als im Vordergrund, wenn eine der folgenden Bedingungen erfüllt ist:

  • Es gibt eine sichtbare Aktivität (entweder gestartet oder angehalten).
  • Die App hat einen Vordergrunddienst gestartet.
  • Eine andere App befindet sich im Vordergrund und verwendet Komponenten aus einer App, die sich andernfalls im Hintergrund befinden würden. Ein Beispiel hierfür ist, wenn Anwendung A, die sich im Vordergrund befindet, an einen Dienst gebunden ist, der von Anwendung B bereitgestellt wird. Anwendung B wird dann auch im Vordergrund betrachtet und nicht von Android beendet, weil sie sich im Hintergrund befindet.

Es gibt einige Situationen, in denen Android, obwohl sich eine App im Hintergrund befindet, die App aktiviert und diese Einschränkungen einige Minuten lang lockert, sodass die App einige Aufgaben ausführen kann:

  • Die App empfängt eine Firebase Cloud-Nachricht mit hoher Priorität.
  • Die App empfängt eine Übertragung.
  • Die Anwendung empfängt und führt eine PendingIntent als Reaktion auf eine Benachrichtigung aus.

Vorhandene Xamarin.Android-Anwendungen müssen möglicherweise die Ausführung von Hintergrundarbeiten ändern, um Probleme zu vermeiden, die unter Android 8.0 auftreten können. Hier sind einige praktische Alternativen zu einem Android-Dienst:

  • Planen der Ausführung von Arbeiten im Hintergrund mithilfe des Android-Auftragsplaners oder des Firebase-Auftragsverteilers : Diese beiden Bibliotheken bieten ein Framework für Anwendungen, um Hintergrundarbeit in Aufträge zu trennen, eine separate Arbeitseinheit. Apps können dann den Auftrag mit dem Betriebssystem zusammen mit einigen Kriterien planen, wann der Auftrag ausgeführt werden kann.
  • Starten Sie den Dienst im Vordergrund – ein Vordergrunddienst ist nützlich, wenn die App eine Aufgabe im Hintergrund ausführen muss und der Benutzer möglicherweise regelmäßig mit dieser Aufgabe interagieren muss. Der Vordergrunddienst zeigt eine permanente Benachrichtigung an, sodass der Benutzer weiß, dass die App eine Hintergrundaufgabe ausführt und auch eine Möglichkeit zum Überwachen oder Interagieren mit der Aufgabe bietet. Ein Beispiel hierfür wäre eine Podcast-App, die einen Podcast für den Benutzer wiedergibt oder vielleicht eine Podcast-Episode herunterladen, damit er später genossen werden kann.
  • Verwenden einer Firebase Cloud Message (FCM) mit hoher Priorität : Wenn Android eine FCM mit hoher Priorität für eine App erhält, kann diese App Dienste für einen kurzen Zeitraum im Hintergrund ausführen. Dies wäre eine gute Alternative zu einem Hintergrunddienst, der eine App im Hintergrund abruft.
  • Zurückstellen von Arbeiten für, wenn die App in den Vordergrund tritt : Wenn keine der vorherigen Lösungen praktikabel ist, müssen Apps ihre eigene Methode entwickeln, um die Arbeit anzuhalten und fortzusetzen, wenn die App in den Vordergrund kommt.