Chapitre 4. Le modèle de composants : les services



Documents pareils
Tutorial pour une application simple

RMI le langage Java XII-1 JMF

Info0604 Programmation multi-threadée. Cours 5. Programmation multi-threadée en Java

Pour signifier qu'une classe fille hérite d'une classe mère, on utilise le mot clé extends class fille extends mère

RMI. Remote Method Invocation: permet d'invoquer des méthodes d'objets distants.

TP Composants Java ME - Java EE. Le serveur GereCompteBancaireServlet

Création d un service web avec NetBeans 5.5 et SJAS 9

TD Objets distribués n 3 : Windows XP et Visual Studio.NET. Introduction à.net Remoting

INITIATION AU LANGAGE JAVA

Remote Method Invocation (RMI)

Encapsulation. L'encapsulation consiste à rendre les membres d'un objet plus ou moins visibles pour les autres objets.

Les connexions sans fil avec Android. JMF (Tous droits réservés) 1

Chapitre 2. Classes et objets

Android et le Cloud Computing

TP1 : Initiation à Java et Eclipse

Projet Viticulture - TP 3 : bases de données distantes BTS Services informatiques aux organisations

Page 1 sur 5 TP3. Thèmes du TP : l la classe Object. l Vector<T> l tutorial Interfaces. l Stack<T>

NFP 121. Java et les Threads. Présentation : Thierry Escalarasse Mai 2007

DirXML License Auditing Tool version Guide de l'utilisateur

Développement sous Android

Projet de Veille Technologique

Utilisation de GCM (Google Cloud Messaging) pour Android. Partie préliminaire éventuelle : Création d'un AVD lisant GCM

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Java DataBaseConnectivity

Qu'est-ce que c'est Windows NT?

SHERLOCK 7. Version du 01/09/09 JAVASCRIPT 1.5

Outils, langage et approche Android Une introduction. Nicolas Stouls lyon.fr

Héritage presque multiple en Java (1/2)

Un ordonnanceur stupide

TP SIN Programmation sur androïde Support : eclipse

ACTIVITÉ DE PROGRAMMATION

Java Licence Professionnelle Cours 7 : Classes et méthodes abstraites

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Programmer en JAVA. par Tama

Serveur d'application Client HTML/JS. Apache Thrift Bootcamp

INF2015 Développement de logiciels dans un environnement Agile. Examen intra 20 février :30 à 20:30

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Notion de thread (1/2)

Programmation par les Objets en Java

Initiation à JAVA et à la programmation objet.

Java Licence Professionnelle CISII, Cours 2 : Classes et Objets

Auto-évaluation Programmation en Java

TP réseau Android. Bidouilles Tomcat. a) Installer tomcat : il suffit de dézipper l'archive apache-tomcat windowsx64.zip.

Synchro et Threads Java TM

Remote Method Invocation Les classes implémentant Serializable

Projet de programmation (IK3) : TP n 1 Correction

Premiers Pas en Programmation Objet : les Classes et les Objets

Développement mobile MIDP 2.0 Mobile 3D Graphics API (M3G) JSR 184. Frédéric BERTIN

Quelques patterns pour la persistance des objets avec DAO DAO. Principe de base. Utilité des DTOs. Le modèle de conception DTO (Data Transfer Object)

Cours de Génie Logiciel

Compte-rendu de projet de Système de gestion de base de données

IFT287 Exploitation de base de données relationnelles et orientées objet. Laboratoire Mon premier programme Java en Eclipse

Android 4 Les fondamentaux du développement d'applications Java

Lambda! Rémi Forax Univ Paris-Est Marne-la-Vallée

1. Introduction Création d'une macro autonome Exécuter la macro pas à pas Modifier une macro... 5

Diagramme de classes

P r ob lé m a t iq u e d e la g é n é r icit é. Pr in cip e d e la g é n é r icit é e n Ja v a ( 1 /3 )

Threads. Threads. USTL routier 1

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

1.3 Gestion d'une application

LMI 2. Programmation Orientée Objet POO - Cours 9. Said Jabbour. jabbour@cril.univ-artois.fr

TP au menu «UI ANDROID»

Tutoriel: Création d'un Web service en C++ avec WebContentC++Framework

La base de données XML exist. A. Belaïd

Dis papa, c est quoi un bus logiciel réparti?

Application web de gestion de comptes en banques

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Projet gestion d'objets dupliqués

Projet Android (LI260) Cours 2

FORMATION PcVue. Mise en œuvre de WEBVUE. Journées de formation au logiciel de supervision PcVue 8.1. Lieu : Lycée Pablo Neruda Saint Martin d hères

SQL Server 2012 Administrez une base de données : Exercices et corrigés

CA Desktop Migration Manager

I. Introduction aux fonctions : les fonctions standards

Les fondamentaux du développement d applications Java

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Guide d'installation. Release Management pour Visual Studio 2013

JADE : Java Agent DEvelopment framework. Laboratoire IBISC & Départ. GEII Université & IUT d Evry nadia.abchiche@ibisc.univ-evry.

Composants Logiciels. Le modèle de composant de CORBA. Plan

Programmation par composants (1/3) Programmation par composants (2/3)

TUTORIEL: INSTALLATION D'UN SERVEUR LOCAL SOUS WINDOWS 7 POUR APPINVENTOR version du 06/04/2013

Interfaces graphiques avec l API Swing

Tp 1 correction. Structures de données (IF2)

Sauvegarde Android

Corrigé de l'atelier pratique du module 8 : Implémentation de la réplication

Corrigé des exercices sur les références

Introduction : les processus. Introduction : les threads. Plan

Edutab. gestion centralisée de tablettes Android

RAPPELS SUR LES METHODES HERITEES DE LA CLASSE RACINE Object ET LEUR SPECIALISATION (i.e. REDEFINITION)

CONNECTEUR PRESTASHOP VTIGER CRM

Le serveur SLIS - Utilisation de base

J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

Projet Active Object

Android Publish/Subscribe, GCM, Google Cloud Messaging : une introduction

CARPE. Documentation Informatique S E T R A. Version Août CARPE (Documentation Informatique) 1

Tutorial et Guide TeamViewer

Introduction à JDBC. Accès aux bases de données en Java

BTS S.I.O PHP OBJET. Module SLAM4. Nom du fichier : PHPRévisionObjetV2.odt Auteur : Pierre Barais

Polymorphisme, la classe Object, les package et la visibilité en Java... 1

Messages d'erreurs. Redémarrez votre PC en cliquant sur Démarrer, en sélectionnant ensuite Arrêter puis en cochant Redémarrer

Transcription:

Chapitre 4 Le modèle de composants : les services 1

Les services "A Service is an application component that can perform long-running operations in the background and does not provide a user interface." Un service continue son exécution même si l'utilisateur change d'application Il peut être lié à plusieurs applications Il y a deux types de service : "started" (= démarré ou unbounded = non lié), lancés par startservice(). Un tel service, après avoir été lancé, est exécuté indéfiniment tant qu'il n'a pas fini son travail (même si le composant qui l'a lancé est détruit) "bound" (= liés), lancés par bindservice(). Un tel service interagit avec d'autres composants. Il est détruit lorsque tous les composants qui lui sont associés ont annulé leur association avec lui sauf s'il est aussi started donc... Un service peut à la fois être démarré par le composant d'une application est lié à d'autres source : 2 http://developer.android.com/guide/components/services.h tml

Service vs. thread Un service est en arrière plan des actions utilisateur, pas des threads (*). C'est à dire qu'il n'y a pas de création de thread, ni de processus lorsqu'un service est lancé et il s'exécute dans la thread qui lui a donné naissance On doit donc créer une thread pour ne pas être bloquant Et donc à quoi sert un service?! Avoir un service plutôt qu'une thread dans une application augmente la priorité de l'application et a donc ainsi moins de chance d'être détruite par l'environnement. Voir à http://developer.android.com/guide/components/processesand-threads.html On peut lier un service à d'autres composants de l'application, voire à d'autres applications : cf. la suite de cet exposé Il est géré par l'environnement d'exécution et par exemple, en cas d'arrêt de l'application, si le service est demandé, il peut être relancé automatiquement par l'environnement d'exécution (*) http://stackoverflow.com/questions/3520719/thread-orservices 3

Cycle de vie d'un service L'automate d'états-transitions d'un service est linéaire donc simple! Il y a évidemment deux sortes d'automates : un pour les services non liés, l'autre pour les services liés Les méthodes onstartcommand(), onbind(), onunbind() ne sont appelées que dans un des cas Les méthodes oncreate(), ondestroy() sont toujours appelées 4

Création d'un service : précisions Les méthodes startservice() et bindservice() sont des méthodes de la classe (abstraite) Context qu'on trouve donc dans les classes dérivées Service, Activity pas ContentProvider ni BroadcastReceiver startservice(), signé public abstract ComponentName startservice (Intent is) permet de lancer un service "started" et de le créer si ce n'est déjà fait. La méthode onstartcommand() du service est chaque fois exécutée mais la méthode oncreate() du service n'est exécutée qu'une seule fois à la création du service bindservice(), signée public abstract boolean bindservice (Intent is, ServiceConnection conn, int flags) permet de lier l'application au service et de le créer si ce n'est déjà fait Remarque : startservice() a un seul argument (l'intent) alors que bindservice() en a 3 (dont l'intent) 5

Arrêter un service Un service non lié (i.e. lancé par startservice()) peut être arrêté : si le service lui-même lance sa méthode stopself() en lançant la méthode stopservice(intent IDuService) de la classe Context sur ce service. IDuService est un Intent décrivant le service à arrêter. Si ce service est lié à aucun autre composant, il sera arrêté quel que soit le nombre d'appels startservice() qui ont été exécutés le service a fini son travail Un service lié (i.e. lancé par bindservice()) est exécuté tant qu'au moins un composant avec lequel il est lié est vivant (= non détruit). Ce service ne peut être arrêté que lorsque tous les composants liés à lui sont détruits 6

Déclarer un service Un service doit être déclaré dans l'androidmanifest.xml comme fils de la balise application <manifest... >... <application... > <service android:name=".exampleservice" />... </application> </manifest> Remarque : si le service n'est pas déclaré dans le manifest, il n'y a (évidemment) pas d'erreur à la compilation mais il n'y aussi pas d'erreur à l'exécution : rien ne se passe! 7

onstartcommand() d'un service "started" La méthode int onstartcommand(intent intent, int flags, int startid) que lance le service a pour arguments : intent est l'intent qui a été passé à startservice(), flags est un indicateur précisant comment le lancement précédent de ce service s'est terminé, startid est un id précisant cette requête L'entier retourné (qui peut être START_STICKY ou START_NOT_STICKY) est utile pour gérer la création du service s'il a été détruit lors de son exécution précédente alors qu'il n'avait pas fini de s'exécuter Rappel : en général, un service est lancé dans la thread principale de l'application qui l'accueille. Donc il est conseillé de lancer un service dans une thread créée par le programmeur : on peut utiliser Handler ou AsyncTask 8

Démos sur les services locaux Une démo, OK! Demo Ch4ServiceLocalHorlogeProjet 9

Service bloquant, non bloquant Comme indiqué, si la méthode int onstartcommand(intent intent, int flags, int startid) est codée sans création de thread, l'application risque d'être bloquée Demo Ch4ServiceLocalHorlogeProjet, clic sur le bouton "Lance un service bloquant" donne : Il faut donc écrire cette méthode plutôt comme : public int onstartcommand(intent intent, int flags, int startid) { new Thread(new Runnable() { public void run() { while (lecompteur < 100000) { try { lecompteur++; Thread.sleep(1000); } catch (InterruptedException e) { e.printstacktrace(); } } } }).start(); return Service.START_STICKY; } Démo : clic sur "Lance un service de comptage" 10

Récupérer les travaux d'un service "started" L'architecture est généralement : on lance le service started celui ci informe un BroadcastReceiver lorsque le travail est fait Le BroadcastReceiver informe que le travail a été fait Bibliographie : http://www.vogella.com/articles/androidservices/article.html 11

Lancer un service started : le code C'est aussi simple que lancer une activité! Context lecontexte = getapplicationcontext(); Intent i = new Intent(leContexte, ClasseDuService.class); lecontexte.startservice(i); On utilise la méthode startservice() qui a un seul argument, l'intent (comme startactivity()) Remarque : En fait la méthode startservice() utilisée ici est celle de la classe Context alors que la méthode startactivity() utilisée pour lancer les activités est celle de la classe Activity, pas de la classe Context (n'est pas Jean-marc!) 12

Service "lié" local ou distant Définition 1 : Un composant Android peut être lié à un service s'exécutant dans la même application. Un tel service est dit local (local service) Définition 2 : Un composant Android peut être lié à un service s'exécutant dans une autre application (un autre process). Un tel service est dit distant (remote service) Pour être lié à un service local, l'utilisation de Binder suffit Pour être lié à un service distant, il faut utiliser les Messenger ou AIDL Seuls une activité, un service et un content provider peuvent être des composants liés à un service, pas un broadcast receiver Voir à http://developer.android.com/guide/components/boundservices.html 13

Service "lié" local : le Binder Le service auquel on doit être lié, doit retourner ce qui permettra d'être lié à lui : un Binder Ce Binder (spécifié par l'interface IBinder) sera retourné par la méthode public IBinder onbind(intent intent) du service La classe Service (classe mère de tout service) possède cette méthode onbind() abstraite... qu'il faut donc toujours implémenter dans un service! 14

La liaison Binder, ServiceConnection L'association à un service est lancé par bindservice(). C'est un processus asynchrone bindservice() n'est pas bloquant et ne retourne pas un IBinder mais un boolean valant true si l'association a été faite bindservice() avertit le service, qui lance sa méthode onbind() qui retourne alors le Binder ce Binder est passé au gestionnaire de connexion (un ServiceConnection) qui lance sa méthode onserviceconnected() avec ce Binder comme argument En général cette méthode onserviceconnected() initialise des champs de la classe englobante => la classe qui implémente ServiceConnection et interne à la classe qui veut être liée au service 15

Service "lié" local : l'enchaînement des appels La suite des appels lors du bind est donc : On a évidemment une suite d'appels similaire pour le onunbind(intent i) : seules les méthodes changent 16

Conclusion sur l'enchaînement des appels La méthode bindservice() (de la classe Context) est en fait signée public abstract boolean bindservice (Intent intent, ServiceConnection conn, int flags) L'appel bindservice() fait par le client est donc bindservice(intent, leserviceconnection, drapeau); Dans intent il y a le service auquel on veut être lié. L'environnement construit une instance de ce service, puis lance la méthode onbind() sur cette instance qui retourne un objet lebinder L'objet leserviceconnection (2ième argument de bindservice()) lance alors sa méthode onserviceconnected() avec l'objet lebinder ci dessus comme second argument Dans l'objet lebinder, il y a ce qu'il faut pour utiliser le service (c'est le service qui l'a créé!) Et voilà comment le client et le serveur sont liés 17

Le ServiceConnection Donc on doit aussi construire un gestionnaire de service implémentant l'interface android.content.serviceconnection et donc donner un corps aux deux méthodes void onserviceconnected(componentname name, IBinder service) et void onservicedisconnected(componentname name) spécifié dans l'interface Ce ServiceConnection est passé comme argument de bindservice() 18

Démo de service lié local Voir projet ServiceLocalHorlogeProjet, bouton "Lance un service de comptage" Cliquer sur bouton "change d'activité" Dans la nouvelle activité, cliquer le bouton de "liaison au service local" puis le bouton "valeur du service local" 19

Services liés distants On veut désormais atteindre un service d'une application à partir d'une autre application On est sur le même smartphone mais on parle de service... distant! Bon il est vrai que ce sont deux processus distincts (mais deux DVM) Un première solution utilise les messagers (Messager, Message,...) Une seconde solution utilise une technologie générale d'accès aux technologies distantes (cf. CORBA,...) : c'est AIDL 20

Services liés distants : les messagers Dans cette technologie, on utilise les notions de messagers (Messenger), messages (Message), thread gestionnaire d'envoi de message (Handler) Et évidemment de service (Service), d'objet pour la liaison (IBinder), de gestionnaire de connexion (ServiceConnection) 21

AIDL (Android Interface Definition Language) La seconde solution pour interroger un service "distant" est d'utiliser une technologie générale d'accès aux technologies distantes (cf. CORBA,...) Il faut donc d'abord spécifier dans un langage générique ce qui est peut être proposé (par un serveur), c'est à dire ce qu'on peut utilisé (par un client). Ce type de langage est un IDL (Interface Definition Langage) Pour Android ce langage de spécification est AIDL 22

Spécification AIDL On veut construire une application qui lance un compteur puis interroger cette application Les spécifications en AIDL sont : package android.jmf.servicedistantaidlspecification; interface IServiceDeCompteur { long getcompteur(); } C'est le fichier IServiceDeCompteur.aidl à ranger sous src dans le paquetage android.jmf.servicedistantaidlspecification Remarque : les fichier aidl ont un nom de la forme XXX.aidl, sont mis dans un paquetage p.sp et commence par la ligne package p.sp; 23

Spécification AIDL : traduction en Java Automatiquement, l'environnement de dévelopement construit la traduction de ce fichier en Java. Evidemment une interface : package android.jmf.servicedistantaidlspecification; public interface IServiceDeCompteur extends android.os.iinterface { /** Local-side IPC implementation stub class. */ public static abstract class Stub extends android.os.binder implements android.jmf.servicedistantaidlspecification.iservicedecompteur {... Remarque 1 : C'est le fichier IServiceDeCompteur.java rangé sous gen dans le paquetage android.jmf.servicedistantaidlspecification Remarque 2 : En général, c'est le fichier XXX.java rangé sous gen dans dans le paquetage p.sp Remarque 3 : ce fichier est automatiquement généré (cf. première ligne) et il ne faut pas le changer. Même si l'indentation déplait! 24

L'interface générée Remarque 4 : l'interface possède une classe interne (statique abstraite) Stub qui dérive de Binder (et qui contient du code!) : si, c'est possible! Donc le Binder est en grande partie créé. Cela explique l'utilisation de l'architecture AIDL 25

Le service distant (1/2) Il est similaire à un service local : il dérive de android.app.service on doit construire le Binder qui sera retourné par onbind() évidemment la classe IServiceDeCompteur.Stub nous aide. Il suffit de dériver de cette classe et d'implémenter les méthodes utiles pour le client D'où le service distant : public class ServiceDeCompteurAIDL extends Service { private long mlecompteurnonstatic = 0; private final IServiceDeCompteur.Stub mbinder = new IServiceDeCompteur.Stub() { public long getcompteur() { return mlecompteurnonstatic; } }; @Override public IBinder onbind(intent arg0) { // TODO Auto-generated method stub return mbinder; }... // Suite diapositive suivante 26

Le service distant (2/2) Son service de compteur est similaire au service local précédent : @Override public int onstartcommand(intent intent, int flags, int startid) { new Thread(new Runnable() { public void run() { while (mlecompteurnonstatic < 100000) { try { mlecompteurnonstatic++; Thread.sleep(1000); } catch (InterruptedException e) { e.printstacktrace(); } } } }).start(); return Service.START_STICKY; } 27

Déclaration du service distant dans son AndroidManifest.xml Evidemment, il faut déclarer le service dans l'androidmanifest.xml La déclaration doit être : <service android:name=".servicedecompteuraidl" > <intent-filter> <action android:name="android.jmf.servicedistantaidlspecification.iservicedecompteur" /> </intent-filter> </service> Il faut indiquer que ce service pourra être lancé par des Intent (implicites) qui demande l'action android.jmf.servicedistantaidlspecification.iservicedec ompteur. Ce sera le cas d'une application externe (un client) qui ne connaît pas exactement la classe du service (sinon il le dirait et utiliserait un Intent explicite) mais seulement son interface android.jmf.servicedistantaidlspecification.iservicedec ompteur (associé à l'action de même nom) 28

L'application cliente L'application cliente est une autre application qui va demander ce service de comptage Il lui faut les spécifications de ce service c'est à dire le fichier IServiceDeCompteur.aidl à copier dans son paquetage android.jmf.servicedistantaidlspecification L'environnement de développement construit le fichier IServiceDeCompteur.java qu'il va ranger sous gen dans le paquetage android.jmf.servicedistantaidlspecification On a alors : 29

L'application cliente : le code Pour être lié au service distant, il suffit d'écrire (comme d'habitude) : On a besoin d'un ServiceConnection qui est : IServiceDeCompteur étant l'interface android.jmf.servicedistantaidlspecification.iservicedecompte ur Context lecontexte = getapplicationcontext(); Intent i = new Intent(IServiceDeCompteur.class.getName()); lecontexte.bindservice(i, mconnection, Context.BIND_AUTO_CREATE); private IServiceDeCompteur miservicedecompteur; private ServiceConnection mconnection = new ServiceConnection() { public void onserviceconnected(componentname classname, IBinder service) { miservicedecompteur = IServiceDeCompteur.Stub.asInterface(service); } public void onservicedisconnected(componentname classname) { miservicedecompteur = null; } }; 30

Service distant : une démo Ayant repéré le service distant par miservicedecompteur, on peut récupérer les valeurs du compteur par : Démo : miservicedecompteur.getcompteur(); On lance le service distant : projet ServiceDistantAIDLServeurProjet. Au lancement de cette applilcation, le serveur est mis en route (voir les Log) On lance le client : projet ServiceDistantAIDLClientProjet. Faire l'association puis le relevé du compteur 31

Bibliographie sur les services http://developer.android.com/reference/android/ap p/service.html sur AIDL : http://developer.android.com/guide/components/aid l.html http://www.youtube.com/watch?v=fdk2phu0o9c http://saigeethamn.blogspot.fr/2009/09/androiddeveloper-tutorial-part-9.html 32

Fin 33