Création de services Android

De RAD Studio
Aller à : navigation, rechercher

Remonter à Création d'une app Android

Un service Android est une application sans interface utilisateur qui exécute des tâches en arrière-plan. Il y a essentiellement deux types de services :

  • Un service de type Démarré : ce service est démarré par une application Android. Le service peut s'exécuter en arrière-plan indéfiniment, même si l'application est fermée. Ce type de service exécute généralement une tâche unique et s'arrête automatiquement dès que cette tâche est terminée.
  • Un service de type Lié : ce service s'exécute uniquement lorsqu'il est lié à une application Android. Il existe une interaction entre l'application et le service, et il reste actif tant que l'application n'a pas rompu la liaison. Plusieurs applications peuvent se lier au même service.

Création d'un service Android

RAD Studio fournit un expert pour créer des projets Service Android, et un autre expert pour ajouter des services Android à une application multi-périphérique.

Pour créer un nouveau projet Service Android, choisissez Fichier > Nouveau > Autre, puis naviguez sur :

  • Projets Delphi > Android Service

Utilisez cet expert pour spécifier le type du service, local ou distant.

  • Un service local est réservé à une application. L'accès au service à partir d'autres applications est bloqué en ajoutant une ligne au fichier manifeste Android :
<service android:exported="false" android:name="com.embarcadero.services.<service_name>"/>
  • Un service distant est public, et d'autres applications peuvent y accéder. L'accès au service est accordé en ajoutant une ligne au fichier manifeste Android :
<service android:exported="true" android:name="com.embarcadero.services.<service_name>"/>

Pour plus d'informations sur les différentes options, voir Service Android.

Pour plus d'informations sur les attributs du manifeste Android, voir Exported Provider Element (EN).

Ajout d'un service Android à une application

Dès sa création, le service apparaît sur le Gestionnaire de projets sous la forme lib<nom_projet>.so :

  1. Ajoutez tous les composants visuels au module de données, et les fonctions et procédures au code.
  2. Enregistrez le projet Service Android.
    Remarque 1 : Enregistrez chaque projet Service Android dans un dossier exclusif.
    Remarque 2 : N'attribuez pas au projet Service Android le nom Service.
  3. Construisez le projet Service Android avant de l'ajouter à l'application afin de générer les fichiers binaires.
  4. Ajoutez dans le Gestionnaire de projets l'application à laquelle vous voulez ajouter le service :
    1. Pour une application existante, cliquez avec le bouton droit sur le groupe de projets et sélectionnez Ajouter un projet existant.
    2. Pour une application multi-périphérique, cliquez avec le bouton droit sur le groupe de projets et sélectionnez Ajouter un nouveau projet, puis naviguez sur :
      • Projets Delphi > Application multi-périphérique.
  5. Sur l'application multi-périphérique, sélectionnez la plate-forme cible Android.
    1. Sur la plate-forme cible Android, cliquez avec le bouton droit et sélectionnez Add Android Service.
    2. L'expert Add New Android Service apparaît.
    3. Cliquez sur ProjectOptionsEllipsis.jpg pour sélectionner le dossier dans lequel votre projet Service Android est enregistré.
    4. Cliquez sur Next.
      1. Si tout est correct, les fichiers sur le point d'être ajoutés à votre application multi-périphérique sont listés.
      2. Si une fenêtre supplémentaire demande des informations sur les chemins du service Android, enregistrez et construisez le service Android, puis réessayez.
  6. Cliquez sur Finish pour ajouter les fichiers à l'application :
    • Le fichier binaire principal, lib<project_name>.so. Le fichier binaire est ajouté au Gestionnaire de déploiement.
      Remarque : Cette remarque n'affecte pas RAD Studio Seattle Subscription Update 1. Le chemin local d'accès au projet lib<project_name>.so est absolu. Si vous changez l'emplacement du service, vous devez ajouter de nouveau le service à l'application.
    • Le fichier libProxyAndroidService.so. Cette bibliothèque est ajoutée au Gestionnaire de déploiement.
      Remarque : Ce fichier est partagé par tous les services ajoutés à l'application.
    • L'archive Java, le fichier <nom_projet>.jar. Le fichier jar est ajouté au noeud Bibliothèques sur le Gestionnaire de projets, sous la plate-forme cible Android.
    • Le fichier module de données, <nom_projet>.pas. Le module de données est ajouté au Gestionnaire de projets.
  7. Compilez l'application multi-périphérique afin de générer le fichier manifeste Android, en ajoutant la ligne qui correspond au type de service sélectionné auparavant (local ou distant). Voir Création d'un service Android.
    Remarque : Chaque service nécessite une déclaration de <service> correspondante dans le fichier AndroidManifest.xml. Celle-ci est ajoutée automatiquement par l'EDI.

Ajout de plusieurs services Android à une application

Vous pouvez ajouter n'importe quel nombre de services à une application Android.

Suivez les étapes spécifiées dans Ajout d'un service Android à une application pour chaque service à ajouter.

Points importants à prendre en compte :

  • Enregistrez chaque projet Service Android dans un dossier exclusif.
  • Nommez différemment chaque projet avant de l'ajouter à l'application principale :
    • Le projet Service Android, lib<nom_service>.so.
    Remarque : N'attribuez pas au projet Service Android le nom Service.

Suppression d'un service Android d'une application

Le processus de suppression d'un service Android, qui est déjà ajouté à une application Android, est manuel :

  1. Retirez l'archive Java : Sur le Gestionnaire de projets, accédez à la plate-forme cible Android, puis :
    1. Allez au noeud Bibliothèques et sélectionnez <nom_service>.jar.
    2. Cliquez avec le bouton droit et sélectionnez Retirer du projet.
    3. Cliquez sur Oui sur le dialogue modal pour confirmer l'opération.
  2. Retirez le module de données : Sur le Gestionnaire de projets :
    1. Allez au noeud Service et sélectionnez <nom_service>.pas.
    2. Cliquez avec le bouton droit et sélectionnez Retirer du projet.
    3. Cliquez sur Oui sur le dialogue modal pour confirmer l'opération.
  3. Retirez les fichiers binaires du Gestionnaire de déploiement :
    • lib<service_name>.so (spécifique à <service_name>).
    • libProxyAndroidService.so (partagé par tous les services).
      Remarque : Ne décochez pas la bibliothèque libProxyAndroidService.so s'il y a des services dans l'application. Ce fichier est partagé par tous les services.

Remarque : Les observations suivantes n'affectent pas RAD Studio Seattle Subscription Update 1.

Les fichiers de type AndroidServiceOutput ne peuvent pas être supprimés du Gestionnaire de déploiement.

Pour désactiver les fichiers qui doivent être déployés sur la machine cible :

  • Sélectionnez lib<nom_service>.so et décochez Chekbox.png.
  • Sélectionnez libProxyAndroidService.so et décochez Chekbox.png.
    Remarque : Ne décochez pas la bibliothèque libProxyAndroidService.so s'il y a des services dans l'application. Ce fichier est partagé par tous les services.

Vous pouvez également utiliser le bouton de commande Revenir aux valeurs par défaut DMgrRevert.png pour annuler toutes les modifications déjà effectuées dans le Gestionnaire de déploiement sur le projet en cours.

Remarque 1 : N'utilisez pas cette option si plusieurs services ont été ajoutés au projet et que vous ne souhaitez pas retirer tous les services, ou si vous ne voulez pas perdre d'autres modifications.
Remarque 2 : N'oubliez pas de cocher l'option Conserver les fichiers ajoutés sur la fenêtre Revenir aux valeurs par défaut pour conserver les fichiers ajoutés manuellement au projet.

Démarrage d'un service

Les services peuvent être démarrés avec ALocalServiceConnection.StartService('<nom_service>') et ALocalServiceConnection.BindService('<nom_service>'), ou ARemoteServiceConnection.StartService('<nom_service>') et ARemoteServiceConnection.BindService('<nom_service>').

Vous initialisez la variable TLocalServiceConnection à un service spécifique lors du démarrage ou de la liaison de ce service. Après cela, il n'est plus nécessaire de faire référence au nom du service pour le reste des méthodes.

Dès que vous ajoutez un service Android à votre application multi-périphérique :

  1. Incluez l'unité suivante dans la clause uses de l'interface :
    Uses
      System.Android.Service; // Unit that contains the methods to work with services.
    
  2. Incluez l'unité <nom_service.pas> dans la clause uses de l'implémentation. Cela vous permet d'utiliser toutes les méthodes définies sur le module de données du service.
    implementation
    
    uses
      MyLocalService; //Key sensitive
    
    {$R *.fmx}
    
  3. Construisez une variable TLocalServiceConnetion pour un service local, ou une variable TRemoteServiceConnection pour un service distant.
    1. Déclarez la variable TLocalServiceConnection/TRemoteServiceConnection :
      type
        TForm1 = class(TForm)
          ...
        private
          { Private declarations }
          FServiceConnection1: TLocalServiceConnection; // For a local service.
          FServiceConnection2: TRemoteServiceConnection; // For a remote service.
        public
          { Public declarations }
        end;
      
    2. Créez la variable TLocalServiceConnection/TRemoteServiceConnection :
      FServiceConnection1 := TLocalServiceConnection.Create; // For a local service.
      FServiceConnection2 := TRemoteServiceConnection.Create; // For a remote service.
      

Service Démarré

Pour un service de type Démarré, appelez StartService('<nom_service>') pour démarrer le service.

Lors de l'utilisation de services de type Démarré, vous devez gérer le processus d'arrêt du service avec JavaService.stopSelf;.

START_STICKY

L'événement OnStartCommand pour le service est défini par défaut sur START_NOT_STICKY.

  • START_STICKY (EN) est utilisé pour les services qui sont démarrés et arrêtés explicitement selon les besoins. Le système essaie de recréer le service qui a été détruit.
  • START_NOT_STICKY (EN) est utilisé pour les services qui doivent seulement rester en cours d'exécution lors du traitement des commandes envoyées à ces services. Si le processus est détruit, le service n'est pas redémarré automatiquement.

Si vous voulez avoir un START_STICKY sur l'événement OnStartCommand, vous devez le spécifier sur le service :

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

Pour plus d'informations, voir Service Lifecycle (EN).

Service Lié

Pour un service de type Lié, appelez BindService('<nom_service>') pour effectuer la liaison au service afin que vous puissiez démarrer l'interaction avec lui, et UnBindService pour se déconnecter du service.

Pour plus d'informations, voir Bound Services (EN).

Méthodes BindService / UnBindService

Lorsque l'application principale appelle BindService('<nom_service>'), la variable de connexion obtient un pointeur sur l'adresse mémoire où le service s'exécute.

Après l'établissement de la connexion à un service spécifique, lorsque vous appelez UnBindService et que l'application est la seule liée au service, le service se libère lui-même. N'oubliez pas que la variable de connexion de l'application principale reste pointée sur la même adresse mémoire. Une nouvelle liaison au même service peut provoquer un blocage de l'application principale car l'adresse mémoire du service peut être non valide.

Il existe deux moyens de gérer cette situation :

Utilisation de l'attribut [Unsafe]

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

Pour de plus amples informations, voir L'attribut Unsafe.

Evénement OnBind

Lorsque vous appelez BindService('<nom_service>') sur votre application, l'événement OnBind se déclenche sur le projet Service Android. La méthode OnBind renvoie un objet IBinder qui est responsable de la gestion de la connexion au service.

La redéfinition de la méthode OnBind a pour conséquence que l'événement ne renvoie pas l'objet IBinder nécessaire à l'application principale pour amener le module de données depuis le service.

Le code suivant est destiné aux utilisateurs expérimentés qui doivent utiliser la méthode OnBind :

  1. Incluez les unités suivantes dans la clause uses de l'interface :
    uses
      Androidapi.Jni, Androidapi.JNIBridge;
    
  2. Créez une fonction pour obtenir l'objet IBinder :
    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. Sur la méthode OnBind, renvoyez l'objet IBinder :
    function TAndroidServiceDM.AndroidServiceBind(const Sender: TObject;
      const AnIntent: JIntent): JIBinder;
    begin
      // .... User's code
      Result := GetBinder(Self);
    end;
    

Résolution des problèmes

Changer la configuration de construction avant le déploiement

Dans RAD Studio, l'un des fichiers qui compose un Service Android est le fichier lib<nom_service>.so. Ce fichier de bibliothèque est généré lorsque vous compilez le Service Android, et il est enregistré dans .\$(Platform)\$(Config) par défaut.

Lorsque vous ajoutez le Service Android à l'application hôte, le fichier de bibliothèque lib<service_nom>.so est ajouté à la configuration de construction dans le Gestionnaire de déploiement, par exemple, Debug. Si vous déployez l'application Android en sélectionnant une configuration de construction différente, par exemple Release, le fichier nécessaire n'est pas déployé car il n'est pas automatiquement ajouté au Gestionnaire de déploiement, ce qui provoque une erreur d'exécution.

Pour ajouter les fichiers nécessaires à la configuration de construction correcte, ajoutez à nouveau le service à l'application principale.

Ajouter le fichier lib<nom_service>.so de la configuration Release

Pour inclure le fichier lib<nom_service>.so de la configuration Release dans l'application hôte, au lieu du fichier lib<nom_service>.so de la configuration Debug :

  1. Nettoyez le projet de Service Android pour retirer les autres fichiers lib<nom_service>.so restants.
  2. Compilez le projet de service Android pour la configuration Release.
  3. Ajoutez le service Android à l'application hôte pour la configuration Release, avant de déployer l'application vers le périphérique Android.
    Remarque : Vérifiez quel fichier a été ajouté dans l'expert Ajouter un service Android.

Problèmes connus

Si vous rencontrez des problèmes avec les templates Java, voir Présentation des services Android et solutions de contournement pour des informations et ressources.

Voir aussi