AIDL - UPJVExemple Complet 1ière Etape : Implementation des Parcelables (si nécessaire) Fichier...
Transcript of AIDL - UPJVExemple Complet 1ière Etape : Implementation des Parcelables (si nécessaire) Fichier...
InterfaceDe
Service ServiteurClient
AIDLAndroid Interface Definition Language
ServiteurClient
Process Process
IPC Inter Process Communication ….….. mais sur une même machine …. pas entre plusieurs machines
Service
IPC
Spécification AIDL (.aidl)
package com.example.aidl2kristof.api;
interface InterfaceDeService {
int premierService();int secondService();
}
<<interface>>InterfaceDeService
int premierService();int secondService();
<<package>>com.example.aidl2kristof.api
<<interface>>IInterface
<<package>>android.os
<<class>>Parcel
<<class>>Binder
<<interface>>IBinder
<<class>>Stub
int premierService();int secondService();
<<class>>Proxy
Type Interne
<<package>>android.content
<<interface>>ServiceConnection
<<class>>Stub
int premierService();int secondService();<<interface>>
InterfaceDeServiceint premierService();int secondService();
<<class>>Proxy
Android MiddlewareAndroid IPC
<<class>>Stub
int premierService();int secondService();<<interface>>
InterfaceDeServiceint premierService();int secondService();
<<class>>Proxy
Android MiddlewareAndroid IPC
ServiteurClient
Process Process
<<class>>Stub
int premierService();int secondService();
<<interface>>InterfaceDeService
int premierService();int secondService();
<<class>>Proxy
Android MiddlewareAndroid IPC
Exemple Complet1ière Etape : Spécification de l'interface IDL
package com.kristofaidldemo.api;
import com.kristofaidldemo.api.MonParcelable;
interface InterfaceDeService {int unService();
MonParcelable mode1(in MonParcelable inParam);
MonParcelable mode2(out MonParcelable outParam);
MonParcelable mode3(inout MonParcelable inoutParam);
}
Il faut packager
On peut importer
Exemple simple
3 modes de passage de paramètres ( Parcelable ! ):
- in
Client → Serveur
- out
Client ← Serveur
- inout
Client ↔ Serveur
//Un Paramètre = ModeParam + TypeParam + NomParam
FichierInterfaceDeService.aidl
Exemple Complet1ière Etape : Spécification des Parcelables
(si nécessaire)
package com.kristofaidldemo.api;
parcelable MonParcelable;
Il faut packager
FichierMonParcelable.aidl
Ce parcelable a un intérêt seulement dans le cas d'utilisation de paramètres en mode in, out et inout.
Les paramètres de type primitifs ne peuvent être passé qu'en mode in (par défaut).
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
package com.kristofaidldemo.api;
import android.os.Parcel;import android.os.Parcelable;
public class MonParcelable implements Parcelable {
//// Données "utiles" du Parcelable ...//private int d1;private String d2;
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
//… MonParcelable ….suite //// Il faut fournir un constructeur par defaut !// Utilisé par l'infrastructure sous-jascente //
public MonParcelable() {this.d1 = 0;this.d2 = "";
}
//// Constructeur Facultatif//
public MonParcelable(int d1, String d2) {this.d1 = d1;this.d2 = d2;
}
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
//… MonParcelable ….suite //// Getter/Setter en fonction de vos besoins... // ...mais c'est mieux !//
public int getD1() { return d1; }
public void setD1(int d1) { this.d1 = d1; }
public String getD2() { return d2; }
public void setD2(String d2) { this.d2 = d2;}
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
//… MonParcelable ….suite //// describeContents() … il la faut, c'est comme ca !// cf JavaDoc:// Describe the kinds of special objects contained in// this Parcelable's marshalled representation.//// Returns : a bitmask indicating the set of special// object types marshalled by the Parcelable. //// ??? Il la faut !//
@Overridepublic int describeContents() {
// TODO Auto-generated method stubreturn 0;
}
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
//… MonParcelable ….suite /** Factory .... * * ... le nom " CREATOR " ....doit être ainsi ... */public static final Parcelable.Creator<MonParcelable> CREATOR = new Parcelable.Creator<MonParcelable>() {
public MonParcelable createFromParcel(Parcel in) {int v1 = in.readInt();String v2 = in.readString();return new MonParcelable(v1, v2);
}
public MonParcelable[] newArray(int size) {return new MonParcelable[size];
}};
Exemple Complet1ière Etape : Implementation des Parcelables
(si nécessaire)
FichierMonParcelable.java
//… MonParcelable ….suite
public void writeToParcel(Parcel outParcel, int arg1) { // Pour les paramètre en mode out et inout
outParcel.writeInt(d1); outParcel.writeString(d2);}
public void readFromParcel(Parcel in) {// Pour les paramètre en mode in
d1 = in.readInt(); d2 = in.readString();}
public String toString() {return
"MonParcelable [d1=" + d1 + ", d2=" + d2 + "]";}
}
Exemple Complet
Le compilateur AIDL …. va traduire ces AIDL en java ….
Exemple Complet2nde Etape : Le coté Serveur ...
package com.kristofaidldemo.coteserveur.lib;
import ...
//// Implémentation du "Serviteur" ... Objet qui rend // effectivement les services ...//
////Premiere Etape : //// On "fabrique" une classe d’implémentation qui dérive de la // classe android.app.Service//// En conséquence de cette dérivation, cela implique // l’implémentation de la méthode : public abstract Ibinder// onBind (Intent intent)//public class InterfaceDeServiceImpl extends Service {
Exemple Complet2nde Etape : Le coté Serveur ...
private static final String
TAG=com.kristofaidldemo.coteserveur.lib.InterfaceDeServiceImpl.class.getName();
//// Variable compteur.... pour illustrer le code métier..//private int compteur=0;
Exemple Complet2nde Etape : Le coté Serveur ...
//// Seconde Etape : // ----------------//// En conséquence de la dérivation de la classe Service par // la classe InterfaceDeServiceImpl, on implémenté la // méthode onBind (Intent intent)//// Comme on illustre ici l'offre d'un service AIDL, cette // méthode onBind // doit retourner un Binder de type InterfaceDeService.Stub // (nommé ici monBinder... cf ensuite) et implémentant // les services apparaissant dans l'interface// InterfaceDeService(.aidl).////public IBinder onBind(Intent intent) {
return monBinder;}
Exemple Complet2nde Etape : Le coté Serveur ...
private InterfaceDeService.Stub monBinder = new InterfaceDeService.Stub() {
//// Notez ici l’implémentation des services apparaissant// dans l'interface InterfaceDeService(.aidl). // ... c'est ici qu’apparaît le " code métier " du// fournisseur de service ...//public int unService() throws RemoteException {
//Log.d(TAG, "Execution de 'unService'.");
compteur++;return compteur;
}
Exemple Complet2nde Etape : Le coté Serveur ...
@Overridepublic MonParcelable mode1( // Illustation du mode in
MonParcelable inParam)throws RemoteException {
int v1=inParam.getD1();String v2=inParam.getD2();Log.d(TAG, " inParam (avant modif)= "+inParam);
inParam.setD1(compteur);inParam.setD2("From mode1="+v2);Log.d(TAG, " inParam (apres modif)= "+inParam);
MonParcelable res = new MonParcelable(666, "in parameter");
Log.d(TAG, " resultat = "+res);
return res;}
Exemple Complet2nde Etape : Le coté Serveur ...
@Overridepublic MonParcelable mode2( // Illustation du mode out
MonParcelable outParam)throws RemoteException {
int v1=outParam.getD1();String v2=outParam.getD2();outParam.setD1(compteur);outParam.setD2("From mode2="+v2);Log.d(TAG, " outParam (apres modif)= "+outParam);
MonParcelable res = new MonParcelable(667, "out parameter");
Log.d(TAG, " resultat = "+res);
return res;}
Exemple Complet2nde Etape : Le coté Serveur ...
@Overridepublic MonParcelable mode3(// Illustation du mode outin
MonParcelable inoutParam) throws RemoteException {
int v1=inoutParam.getD1();String v2=inoutParam.getD2();
inoutParam.setD1(compteur);inoutParam.setD2("From mode3="+v2);
MonParcelable res = new MonParcelable(668, "inout parameter");
return res;}
// fin de private InterfaceDeService.Stub monBinder = ...
Exemple Complet2nde Etape : Le coté Serveur ...
public void onCreate() {// Création du servicesuper.onCreate();
Log.d(TAG, "unService...");Utils.listRunningService(getApplicationContext());
Utils.showShortToast(this, "onCreate()... Création du service...");
new MonThread().start();}
Exemple Complet2nde Etape : Le coté Serveur ...
public void onDestroy() {super.onDestroy();// Destruction du service
Log.d(TAG, "unService...");Utils.listRunningService(getApplicationContext());
Utils.showShortToast(this, "onDestroy()... Destruction du service...");
}
Exemple Complet2nde Etape : Le coté Serveur ...
public int onStartCommand(Intent intent, int flags, int startId)
{
Log.d(TAG, "unService...");Utils.listRunningService(getApplicationContext());
Utils.showShortToast(this, "onStartCommand()...");
return super.onStartCommand(intent, flags, startId);}
Exemple Complet2nde Etape : Le coté Serveur … pour être complet :
package com.kristofaidldemo.coteserveur.lib;
import android.util.Log;
public class MonThread extends Thread {
private static final String TAG=...
private int pause=1000;
private int compteur=0 ;
Exemple Complet2nde Etape : Le coté Serveur … pour être complet :
@Overridepublic void run() {
while(compteur<200){
compteur++;
Log.d(TAG, "MonThread["+compteur+"]");try {
Thread.sleep(pause);} catch (InterruptedException e) {}
}}
}
Exemple Complet2nde Etape : Le coté Serveur … Concernant l'AndroidManifest
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.kristofaidldemo.coteserveur.lib" android:versionCode="1" android:versionName="1.0" >
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16" />
<application android:icon="@drawable/ic_launcher" android:label="@string/app_name"
<service android:name="InterfaceDeServiceImpl" android:enabled="true" android:exported="true"
> <intent-filter>
<action android:name="com.kristofaidldemo.intent.service.ZeServiteur" /> </intent-filter> </service>
</application></manifest>
Exemple Complet2nde Etape : Le coté Serveur … Concernant l'AndroidManifest
<service android:name=The name of the Service subclass that implements the
service. This should be a fully qualified class name (such as, "com.example.project.RoomService"). However, as a shorthand, if the first character of the name is a period (for example, ".RoomService"), it is appended to the package name specified in the <manifest> element.
android:enabled=Whether or not the service can be instantiated by the system — "true" if it can be, and "false" if not. The default value is "true".
android:exported=Whether or not components of other applications can invoke the service or interact with it — "true" if they can, and "false" if not. When the value is "false", only components of the same application or applications with the same user ID can start the service or bind to it.
>
Exemple Complet2nde Etape : Le coté Serveur … Concernant l'AndroidManifest
<intent-filter><action android:name="com.kristofaidldemo.intent.service.ZeServiteur" />
</intent-filter>
Le nom de l'Intent dont devra disposer tout composant souhaitant se conencter au Serveur
Exemple Complet3nde Étape : Le coté Client
Le Client doit disposer d'une référence sur le Serveur :
private InterfaceDeService monServiteur;
Exemple Complet3nde Étape : Le coté Client
Le Client doit disposer d'une « connexion » sur le Serveur :
// L'interface ServiceConnection appartient à l'API
private ServiceConnection maConnection = new ServiceConnection()
{public
void onServiceConnected(ComponentName arg0, IBinder arg1) {…}
public void onServiceDisconnected
(ComponentName arg0) {…}
}
Exemple Complet3nde Étape : Le coté Client
Le Client doit disposer d'une « connexion » sur le Serveur avec :
//// La Méthode onServiceConnected (...) de l'interface // android.content.ServiceConnection//// Called when a connection to the Service has been established,// with the IBinder of the communication channel to the Service.//// cf API Docs//public void onServiceConnected
(ComponentName arg0, IBinder arg1) {
monServiteur = InterfaceDeService.Stub.asInterface(arg1);
}
Exemple Complet3nde Étape : Le coté Client
Le Client doit disposer d'une « connexion » sur le Serveur avec :
//// La Methode onServiceDisconnected (...) de l'interface// android.content.ServiceConnection//// Called when a connection to the Service has been lost. This// typically happens when the process hosting the service has crashed// or been killed.//// cf API Docs//public void onServiceDisconnected
(ComponentName arg0) {
monServiteur = null;}
Exemple Complet3nde Étape : Le coté Client
Une fois que le Client se sera lié au Serveur :
String intentString = "com.kristofaidldemo.intent.service.ZeServiteur";
// Nom de l'intent-filter du service apparaissant// dans l'AndroidManifest.xml coté serveur
Intent intent = new Intent(intentString) ;
boolean res = BindService(intent,
maConnection, Context.BIND_AUTO_CREATE);
Il n'aura plus qu'à « naturellement » interagir avec :
int res = monServiteur.unService();
Exemple Complet3nde Étape : Le coté Client
Le Client doit disposer d'une « connexion » sur le Serveur avec :
//// La Methode onServiceDisconnected (...) de l'interface// android.content.ServiceConnection//// Called when a connection to the Service has been lost. This// typically happens when the process hosting the service has crashed// or been killed.//// cf API Docs//public void onServiceDisconnected
(ComponentName arg0) {
monServiteur = null;}