Erstellen von Android-Diensten

Aus RAD Studio
Wechseln zu: Navigation, Suche

Nach oben zu Erstellen einer Android-App

Ein Android-Dienst ist eine Anwendung ohne Benutzeroberfläche, die Hintergrundaufgaben ausführt. Im Wesentlichen gibt es zwei Arten von Diensten:

  • Ein gestarteter Dienst: Dieser Dienst wird von einer Android-Anwendung gestartet. Der Dienst kann unendlich im Hintergrund ausgeführt werden, auch wenn die Anwendung geschlossen ist. Diese Art Dienst führt in der Regel eine einzelne Aufgabe aus und wird automatisch nach Beendigung der Aufgabe angehalten.
  • Ein gebundener Dienst: Dieser Dienst wird nur ausgeführt, wenn er an eine Android-Anwendung gebunden ist. Es gibt eine Interaktion zwischen der Anwendung und dem Dienst, und der Dienst bleibt so lange aktiv, bis die Anwendung die Bindung aufhebt. Mehrere Anwendungen können an denselben Dienst gebunden sein.

Erstellen eines Android-Dienstes

RAD Studio stellt einen Experten zum Erstellen von Android-Dienst-Projekten und einen weiteren Experten zum Hinzufügen von Android-Diensten zu geräteübergreifenden Anwendungen bereit.

Um ein neues Android-Dienst-Projekt zu erstellen, wählen Sie Datei > Neu > Weitere und navigieren dann zu:

  • Delphi-Projekte > Android-Dienst

Verwenden Sie diesen Experten, um den Typ des Dienstes, lokal oder remote, festzulegen.

  • Ein lokaler Dienst ist für eine Anwendung privat. Der Zugriff von anderen Anwendungen wird durch Hinzufügen einer Zeile zur Android-Manifestdatei blockiert:
<service android:exported="false" android:name="com.embarcadero.services.<service_name>"/>
  • Ein Remote-Dienst ist öffentlich, und andere Anwendungen können darauf zugreifen. Der Zugriff auf den Dienst wird durch das Hinzufügen einer Zeile zur Android-Manifestdatei erteilt:
<service android:exported="true" android:name="com.embarcadero.services.<service_name>"/>

Weitere Informationen über die verschiedenen Optionen finden Sie unter Android-Dienst.

Weitere Informationen über die Android-Manifestattribute finden Sie unter Exported Provider Element (EN).

Hinzufügen eines Android-Dienstes zu einer Anwendung

Wenn der Dienst erstellt ist, wird er in der Projektverwaltung als lib<Projektname>.so angezeigt:

  1. Fügen Sie dem Datenmodul alle visuellen Komponenten und dem Code die Funktionen und Prozeduren hinzu.
  2. Speichern Sie das Android-Dienstprojekt.
    Hinweis 1: Speichern Sie jedes Android-Dienstprojekt in einem eigenen Ordner.
    Hinweis 2: Nennen Sie das Android-Dienstprojekt nicht Service.
  3. Erzeugen Sie das Android-Dienstprojekt, bevor Sie es der Anwendung hinzufügen, um die Binärdateien zu generieren.
  4. Fügen Sie der Projektverwaltung die Anwendung hinzu, zu der Sie den Dienst hinzufügen möchten:
    1. Klicken Sie bei einer vorhandenen Anwendung mit der rechten Maustaste auf die Projektgruppe, und wählen Sie Existierendes Projekt hinzufügen.
    2. Klicken Sie bei einer neuen geräteübergreifenden Anwendung mit der rechten Maustaste auf die Projektgruppe, wählen Sie Neues Projekt hinzufügen, und navigieren Sie dann zu:
      • Delphi-Projekte > Geräteübergreifende Anwendung.
  5. Wählen Sie für die geräteübergreifende Anwendung die Android-Zielplattform aus.
    1. Klicken Sie mit der rechten Maustaste auf die Android-Zielplattform, und wählen Sie Android-Dienst hinzufügen.
    2. Der Experte Neuen Android-Dienst hinzufügen wird geöffnet.
    3. Klicken Sie auf ProjectOptionsEllipsis.jpg, um den Ordner auszuwählen, in dem das Android-Dienstprojekt gespeichert ist.
    4. Klicken Sie auf Weiter.
      1. Wenn alles korrekt ist, werden die Dateien, die Ihrer geräteübergreifenden Anwendung hinzugefügt werden sollen, aufgeführt.
      2. Wenn ein zusätzliches Fenster mit der Aufforderung, Information über die Android-Dienstpfade anzugeben, angezeigt wird, speichern und erzeugen Sie den Android-Dienst, und versuchen Sie es anschließend erneut.
  6. Klicken Sie auf Fertig stellen, um der Anwendung die Dateien hinzuzufügen:
    • Die Hauptbinärdatei lib<Projektname>.so. Die Binärdatei wird dem Bereitstellungs-Manager hinzugefügt.
      Hinweis: Dieser Hinweis hat keinen Einfluss im RAD Studio Seattle Subscription Update 1. Der lokale Pfad zur Datei lib<Projektname>.so ist absolut. Wenn Sie den Dienst an einen anderen Speicherort verschieben, müssen Sie der Anwendung den Dienst erneut hinzufügen.
    • Die Datei libProxyAndroidService.so. Diese Bibliothek wird dem Bereitstellungs-Manager hinzugefügt.
      Hinweis: Diese Datei wird von allen der Anwendung hinzugefügten Diensten gemeinsam genutzt.
    • Die Java-Archivdatei <Projektname>.jar. Die JAR-Datei wird in der Projektverwaltung dem Knoten Bibliotheken unter der Android-Zielplattform hinzugefügt.
    • Die Datenmoduldatei <Projektname>.pas. Das Datenmodul wird der Projektverwaltung hinzugefügt.
  7. Compilieren Sie die geräteübergreifende Anwendung, um die Android-Manifestdatei zu generieren, wobei die dem zuvor ausgewählten Diensttyp (lokal oder remote) entsprechende Zeile hinzugefügt wird. Siehe Erstellen eines Android-Dienstes.
    Hinweis: Jeder Dienst benötigt eine entsprechende <service>-Deklaration in der Datei AndroidManifest.xml. Diese wird von der IDE automatisch hinzugefügt.

Hinzufügen mehrerer Android-Dienste zu einer Anwendung

Sie können einer Android-Anwendung eine beliebige Anzahl von Diensten hinzufügen.

Befolgen Sie die Schritte unter Hinzufügen eines Android-Dienstes zu einer Anwendung für jeden hinzuzufügenden Dienst.

Berücksichtigen Sie Folgendes:

  • Speichern Sie jedes Android-Dienstprojekt in einem eigenen Ordner.
  • Vergeben Sie für jedes Projekt einen anderen Namen, bevor Sie es der Hauptanwendung hinzufügen:
    • Das Android-Dienstprojekt lib<Dienstname>.so.
    Hinweis: Nennen Sie das Android-Dienstprojekt nicht Service.
    • Die Unit-Datei.
    • Das Datenmodul, indem Sie im Objektinspektor die Eigenschaft Name ändern.

Löschen eines Android-Dienstes aus einer Anwendung

Ein bereits zu einer Anwendung hinzugefügter Android-Dienst muss manuell geändert werden:

  1. Entfernen des Java-Archivs: Wählen Sie in der Projektverwaltung die Android-Zielplattform aus, und:
    1. Wählen Sie im Knoten Bibliotheken <Dienstname>.jar aus.
    2. Klicken Sie mit der rechten Maustaste, und wählen Sie Aus dem Projekt entfernen.
    3. Klicken Sie im modalen Dialogfeld auf Ja, um den Vorgang zu bestätigen.
  2. Entfernen des Datenmoduls: Führen Sie in der Projektverwaltung Folgendes aus:
    1. Wählen Sie im Knoten Dienst <Dienstname>.pas aus.
    2. Klicken Sie mit der rechten Maustaste, und wählen Sie Aus dem Projekt entfernen.
    3. Klicken Sie im modalen Dialogfeld auf Ja, um den Vorgang zu bestätigen.
  3. Entfernen der Binärdateien aus dem Bereitstellungs-Manager:
    • lib<service_name>.so (specific to <service_name>).
    • libProxyAndroidService.so (von allen Diensten gemeinsam genutzt).
      Hinweis: Heben Sie die Markierung der Bibliothek libProxyAndroidService.so nicht auf, wenn sich mehrere Dienste in der Anwendung befinden. Diese Datei wird von allen Diensten gemeinsam genutzt.

Hinweis: Das Folgende hat keinen Einfluss im RAD Studio Seattle Subscription Update 1.

Dateien mit dem Typ AndroidServiceOutput können nicht aus dem Bereitstellungs-Manager gelöscht werden.

So deaktivieren Sie die Dateien, die an das Zielsystem weitergegeben werden sollen:

  • Wählen Sie lib<Dienstname>.so, und entfernen Sie die Markierung von Chekbox.png.
  • Wählen Sie libProxyAndroidService.so, und entfernen Sie die Markierung von Chekbox.png.
    Hinweis: Heben Sie die Markierung der Bibliothek libProxyAndroidService.so nicht auf, wenn sich mehrere Dienste in der Anwendung befinden. Diese Datei wird von allen Diensten gemeinsam genutzt.

Sie können auch mit der Befehlsschaltfläche Auf Standard zurücksetzen DMgrRevert.png alle Änderungen zurücknehmen, die Sie im Bereitstellungs-Manager am aktuellen Projekt vorgenommen haben.

Hinweis 1: Verwenden Sie diese Option nicht, wenn Sie dem Projekt mehrere Dienste hinzugefügt haben und nicht alle entfernen möchten oder wenn Sie andere Änderungen vorgenommen haben, die Sie nicht verlieren möchten.
Hinweis 2: Denken Sie daran, im Fenster Auf Standard zurücksetzen die Option Hinzugefügte Dateien beibehalten zu aktivieren, um die dem Projekt manuell hinzugefügten Dateien beizubehalten.

Starten eines Dienstes

Dienste können mit ALocalServiceConnection.StartService('<Dienstname>') und ALocalServiceConnection.BindService('<Dienstname;') oder ARemoteServiceConnection.StartService('<Dienstname>') und ARemoteServiceConnection.BindService('<Dienstname>') gestartet werden.

Sie initialisieren die Variable TLocalServiceConnection mit einem bestimmten Dienst, wenn Sie den Dienst starten oder ihn einbinden; danach müssen Sie für die restlichen Methoden nicht auf den Dienstnamen verweisen.

Nach dem Hinzufügen eines Android-Dienstes zu einer geräteübergreifenden Anwendung:

  1. Beziehen Sie die folgende Unit in die uses-Klausel des Interface ein:
    Uses
      System.Android.Service; // Unit that contains the methods to work with services.
    
  2. Beziehen Sie die Unit <Dienstname.pas> in die uses-Klausel der Implementierung ein. Auf diese Weise können Sie alle im Dienst-Datenmodul definierten Methoden verwenden.
    implementation
    
    uses
      MyLocalService; //Key sensitive
    
    {$R *.fmx}
    
  3. Erstellen Sie eine TLocalServiceConnetion-Variable für einen lokalen Dienst oder eine TRemoteServiceConnection-Variable für einen Remote-Dienst.
    1. Deklarieren Sie die TLocalServiceConnection/TRemoteServiceConnection-Variable:
      type
        TForm1 = class(TForm)
          ...
        private
          { Private declarations }
          FServiceConnection1: TLocalServiceConnection; // For a local service.
          FServiceConnection2: TRemoteServiceConnection; // For a remote service.
        public
          { Public declarations }
        end;
      
    2. Erstellen Sie die TLocalServiceConnection/TRemoteServiceConnection-Variable:
      FServiceConnection1 := TLocalServiceConnection.Create; // For a local service.
      FServiceConnection2 := TRemoteServiceConnection.Create; // For a remote service.
      

Gestarteter Dienst

Rufen Sie für einen gestarteten Dienst StartService('<Dienstname>') auf, um den Dienst zu starten.

Beim Verwenden von Diensten als gestartet müssen Sie den Dienstprozess, der den Dienst anhält, mit JavaService.stopSelf; verwalten.

"Sticky" Start

Das Ereignis OnStartCommand für den Dienst ist standardmäßig als START_NOT_STICKY definiert.

  • START_STICKY (EN) wird für Dienste verwendet, die bei Bedarf explizit gestartet und angehalten werden. Das System versucht, einen abgebrochenen Dienst neu zu erstellen.
  • START_NOT_STICKY (EN) wird für Dienste verwendet, die nur weiterhin ausgeführt werden sollen, solange an sie gesendete Befehle verarbeitet werden. Wenn der Prozess abgebrochen wurde, wird der Dienst nicht automatisch neu gestartet.

Wenn Sie START_STICKY für das Ereignis OnStartCommand anwenden möchten, müssen Sie das für den Dienst angeben:

function TService1DM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
  Result := TJService.JavaClass.START_STICKY;
end;

Weitere Informationen finden Sie unter Service Lifecycle (EN).

Gebundener Dienst

Rufen Sie für einen gebundenen Dienst BindService('<Dienstname>') auf, um an den Dienst zu binden, damit Sie die Interaktion damit beginnen können, und rufen Sie UnBindService auf, um die Bindung an diesen Dienst aufzuheben.

Weitere Informationen finden Sie unter Bound Services (EN).

Methoden "BindService" und "UnBindService"

Wenn die Hauptanwendung BindService('<Dienstname>') aufruft, erhält die Verbindungsvariable einen Zeiger auf die Speicheradresse, an der der Dienst ausgeführt wird.

Wenn Sie nach dem Herstellen der Verbindung mit einem bestimmten Dienst UnBindService aufrufen und es sich bei der Anwendung um die einzige an den Dienst gebundene Anwendung handelt, gibt der Dienst sich selbst frei. Berücksichtigen Sie, dass die Verbindungsvariable der Hauptanwendung weiterhin auf die gleiche Speicheradresse zeigt. Wenn Sie eine erneute Bindung an denselben Dienst herstellen, kann das einen Absturz der Hauptanwendung verursachen, weil die Speicheradresse des Dienstes ungültig sein könnte.

Es gibt zwei Möglichkeiten, diese Situation zu behandeln:

Das Attribut [Unsafe] verwenden

  private
    { Private declarations }
    [Unsafe] Service1: TAndroidService1DM;

Weitere Informationen finden Sie unter Das Attribut "Unsafe".

Ereignis "OnBind"

Wenn Sie BindService('<Dienstname>') für Ihre Anwendung aufrufen, wird das Ereignis OnBind für das Android-Dienst-Projekt ausgelöst. Die Methode OnBind gibt ein IBinder-Objekt zurück, das für die eigentliche Verwaltung der Verbindung mit dem Dienst zuständig ist.

Das Überschreiben der Methode OnBind verursacht, dass das Ereignis das IBinder-Objekt nicht zurückgibt, das die Hauptanwendung zum Erhalt des Datenmoduls von dem Dienst benötigt.

Der folgende Code ist für fortgeschrittene Benutzer gedacht, die die Methode OnBind verwenden müssen:

  1. Beziehen Sie die folgenden Units in die uses-Klausel des Interface ein:
    uses
      Androidapi.Jni, Androidapi.JNIBridge;
    
  2. Erstellen Sie eine Funktion, um das IBinder-Objekt zu erhalten:
    function GetBinder(const AService: TAndroidBaseService): JIBinder;
    
      function GetmBinder(AJNIService: JNIObject): JIBinder;
      var
        Env: PJNIEnv;
        Clazz: JNIClass;
        FieldID: JNIFieldID;
        LJNIBinder: JNIObject;
      begin
        Result := nil;
        PJavaVM(System.JavaMachine)^.AttachCurrentThread(System.JavaMachine, @Env, nil);
        Clazz := Env^.GetObjectClass(Env, AJNIService);
        FieldID := Env^.GetFieldID(Env, Clazz, 'mBinder', 'Landroid/os/IBinder;');
        if FieldID <> nil then
        begin
          LJNIBinder := Env^.GetObjectField(Env, AJNIService, FieldID);
          if LJNIBinder <> nil then
          begin
            Result := TJIBinder.Wrap(LJNIBinder);
            Env^.DeleteLocalRef(Env, LJNIBinder);
          end;
        end;
        Env^.DeleteLocalRef(Env, Clazz);
      end;
    
    begin
      if AService.JavaService <> nil then
        Result := GetmBinder((AService.JavaService as ILocalObject).GetObjectID)
      else if AService.JavaIntentService <> nil then
        Result := GetmBinder((AService.JavaIntentService as ILocalObject).GetObjectID)
      else
        Result := nil;
    end;
    
  3. Geben Sie in der Methode OnBind das IBinder-Objekt zurück:
    function TAndroidServiceDM.AndroidServiceBind(const Sender: TObject;
      const AnIntent: JIntent): JIBinder;
    begin
      // .... User's code
      Result := GetBinder(Self);
    end;
    

Fehlerbehebung

Ändern der Build-Konfiguration vor der Weitergabe

Eine der Dateien, die einen Android-Dienst in RAD Studio bilden, ist lib<Dienstname>.so. Diese Bibliotheksdatei wird beim Compilieren des Android-Dienstes generiert und standardmäßig in .\$(Platform)\$(Config) gespeichert.

Beim Hinzufügen des Android-Dienstes zur Host-Anwendung wird die Bibliotheksdatei lib<Dienstname>.so im Bereitstellungs-Manager der ausgewählten Build-Konfiguration hinzugefügt, zum Beispiel zu Debug. Wenn Sie bei der Weitergabe der Android-Anwendung eine andere Build-Konfiguration, z. B. Release, auswählen, wird die benötigte Datei nicht weitergegeben, weil sie dem Bereitstellungs-Manager nicht automatisch hinzugefügt wird. Dies verursacht einen Laufzeitfehler.

Um die benötigten Dateien der richtigen Build-Konfiguration hinzuzufügen, fügen Sie den Dienst der Hauptanwendung erneut hinzu.

Hinzufügen von lib<Dienstname>.so für die Release-Konfiguration

So beziehen Sie die Datei lib<Dienstname>.so für die Release-Konfiguration anstatt der Datei lib<Dienstname>.so für die Debug-Konfiguration in die Host-Anwendung ein:

  1. Bereinigen Sie das Android-Dienstprojekt, um andere verbliebene lib<Dienstname>.so-Dateien zu entfernen.
  2. Compilieren Sie das Android-Dienstprojekt für die Release-Konfiguration.
  3. Fügen Sie der Host-Anwendung für die Release-Konfiguration den Android-Dienst vor der Weitergabe der Anwendung an das Android-Gerät hinzu.
    Hinweis: Überprüfen Sie im Experten Android-Dienst hinzufügen die hinzugefügten Dateien.

Bekannte Probleme

Wenn Sie auf Probleme mit Java-Vorlagen stoßen, finden Sie Informationen und Ressourcen unter Darstellungen und Lösungen der Android-Dienste.

Siehe auch