I. Mon application est un Service▲
Un service, c’est un démon, une thread qui tourne sans IHM, bref un service. Un service est un singleton ou presque. En effet, si plusieurs processus accèdent au service, il n’y aura qu’un service. Mais si le service n’a plus d’utilisateur alors le singleton est détruit et le prochain utilisateur recrée un autre singleton. Cela paraît anodin, mais si votre service lance une thread puis est détruit et recréé alors il lancera une nouvelle thread, oubliant la précédente…
L’exemple typique d’un service est votre lecteur de musique. Quand le lecteur n’est plus au premier plan, la musique continue à être jouée, c’est un service. Si ce n’était qu’une activité, dés que l’activité aurait quitté le premier plan, la musique se serait arrêtée.
Un service se lance soit manuellement par l’utilisateur, soit par un appel d’un autre processus. Puis, il reste en vie jusqu'à ce qu’il ne soit plus nécessaire. De ce fait, il doit être très peu gourmant en CPU (au risque de vider la batterie trop vite) et en mémoire (au risque de saturer l’appareil trop vite).
Enfin, soit votre service est interne à votre application et n’a pas de vocation à être ouvert sur le reste du système, soit il a pour vocation d’être ouvert au système. Ces deux cas de figure sont profondément différents et dans l’implémentation et dans l’utilisation du service. Nous n’exposerons ici que le cas d’un service ouvert au reste du monde.
I-A. Utilisation d'un service▲
Il faut implémenter sept choses dans votre Activity pour pouvoir utiliser un service:
- Un objet Service qui n’est autre qu’un pointeur vers le service que vous souhaitez utiliser.
- Un objet ServiceConnection dont le but est de gérer la connexion et la déconnexion au service.
- Un objet BroadCastReceiver pour pouvoir écouter les modifications envoyées par le service
- Un appel à la méthode bindService(service, serviceConnection, flags) dans votre méthode onCreate
- Un appel à la méthode unbindService(serviceConnection) dans votre méthode onDestroy
- Un appel à la méthode registerReceiver(broadcastReceiver, filter) dans votre méthode onResume pour pouvoir écouter les intentions envoyées par le service. Ce mécanisme permet au service d’informer l’activité d’un changement.
- Un appel à la méthode unregisterReceiver(broadcastReceiver) dans votre méthode onPause pour stopper l’écoute des modifications envoyées par le service.
Ce qui donne l’exemple élémentaire suivant :
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
public
class
MyServiceUser extends
Activity {
/**
*
The
service
that
can
be
used
as
a
normal
object
You
can
call
its
public
methods
*/
private
MyService appService =
null
;
/**
*
The
broadcast
receiver
that
aims
to
listen
to
change
broadcast
by
the
service
*/
private
BroadcastReceiver receiver =
new
BroadcastReceiver
(
) {
public
void
onReceive
(
Context context, Intent intent) {
//
Do
something,
call
a
method,
you
already
know
your
service
//
you
can
use
its
methods
directly
in
your
code
}
}
;
/**
*
The
service
connection
,
that
aims
to
connect
to
the
service
*/
private
ServiceConnection onService =
new
ServiceConnection
(
) {
/*
(non-Javadoc)
*
@see
android.content.ServiceConnection#onServiceConnected(android.content.ComponentName,*
android.os.Ibinder)
*/
public
void
onServiceConnected
(
ComponentName className, IBinder rawBinder) {
appService =
(
(
MyService.LocalBinder) rawBinder).getService
(
);
}
/*
(non-Javadoc)
*
@see
*
android.content.ServiceConnection#onServiceDisconnected(android.content.ComponentName)
*/
public
void
onServiceDisconnected
(
ComponentName className) {
appService =
null
;
}
}
;
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
...
//
Bind
your
service
to
your
activity.
//
The
parameters
are:
The
intent
to
talk
to
the
service,
the
service
connection
//
to
use
and
a
flag
to
indicates
if
the
service
has
to
automaticly
start
or
not
//
You
should
use
BIND_AUTO_CREATE
bindService
(
new
Intent
(
this
, MyService.class
),onService, Context.BIND_AUTO_CREATE);
}
@
Override
public
void
onResume
(
) {
super
.onResume
(
);
//
Register
your
activity
to
listen
for
change
send
by
the
service
//
You
can
here
see
that
the
service
has
declared
a
Static
public
String
BROADCAST_ACTION
//that
is
used
to
identify
the
Intent
with
unicity
registerReceiver
(
receiver, new
IntentFilter
(
MyService.BROADCAST_ACTION));
}
@
Override
public
void
onPause
(
) {
super
.onPause
(
);
//
Unregister
your
activity
to
listen
for
change
send
by
the
service
unregisterReceiver
(
receiver);
}
@
Override
public
void
onDestroy
(
) {
super
.onDestroy
(
);
//
Unbind
your
service
(else
your
activity
will
be
destroyed
but
your
service
//
will
still
think
that
somebody
use
it
unbindService
(
onService);
}
}
I-B. Création d’un service▲
Lors de la création d’un service, gardez en tête que celui-ci s’exécute par défaut dans la thread principale de votre application. C’est à vous de faire en sorte de créer une thread pour que votre service l’utilise et ne court-circuite pas votre activité principale.
Pour créer un service, vous devez implémenter :
- la méthode onCreate() qui a à charge l’initialisation
- la méthode onDestroy qui a à charge la destruction de votre service une classe privée qui étend Binder
- la méthode onBind qui renvoie votre classe privée qui étend Binder
- un attribut public static final qui n’est autre que votre identifiant d’intention
- la classe de traitement dans une thread parallèle pour effectuer les actions de votre service. Cette classe étend AsyncTask.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
/**
*
@author
mathias1
*
@goals
This
class
aims
to
show
a
service
'
s
skeleton
*/
public
class
MyService extends
Service {
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
Managing
initialisation
and
death
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
/
*
*
(
non
-
Javadoc
)
*
*
@see
android
.
app
.
Service
#
onCreate
(
)
*/
@
Override
public
void
onCreate
(
) {
super
.onCreate
(
);
//
initialize
your
service
here
}
/*
*
(non-Javadoc)
*
*
@see
android.app.Service#onDestroy()
*/
@
Override
public
void
onDestroy
(
) {
super
.onDestroy
(
);
//
destroy
your
service
here
}
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
Managing
the
binder
to
this
service
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
The
binder
that
glue
to
my
service
*/
private
final
Binder binder=
new
LocalBinder
(
);
/**
*
@author
mSeguy
*
@goals
This
class
aims
to
define
the
binder
to
use
for
my
service
*/
public
class
LocalBinder extends
Binder {
/**
*
@return
the
service
you
want
to
bind
to
:
i
.
e
.
this
*/
MyService getService
(
) {
return
(
MyService.this
);
}
}
/*
(non-Javadoc)
*
@see
android.app.Service#onBind(android.content.Intent)
*/
@
Override
public
IBinder onBind
(
Intent intent) {
return
binder;
}
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
Managing
the
Communication
between
the
service
and
its
listeners
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
/**
*
The
key
of
the
Intent
to
communicate
with
the
service
'
s
users
*/
public
static
final
String MY_SERVICE_INTENT =
"
stinfoservices.net.android.MyUniqueItentServiceKey
"
;
/**
*
The
intent
itself
*/
private
Intent broadcast =
new
Intent
(
MY_SERVICE_INTENT);
/**
*
@author
mSeguy
*
@goals
*
This
class
aims
to
make
a
task
in
a
separeted
thread
*/
class
MyTaskInAnOtherThread extends
AsyncTask<
Location, Void, Void>
{
@
Override
protected
Void doInBackground
(
Location... locs) {
//
Do
something
to
update
your
data
//
here
is
the
place
where
your
treatment
is
done
in
another
thread
than
in
the
GUI
//
thread
//
Prevent
your
listener
that
something
happens
sendBroadcast
(
broadcast);
return
(
null
);
}
@
Override
protected
void
onProgressUpdate
(
Void... unused) {
//
not
needed
here
}
@
Override
protected
void
onPostExecute
(
Void unused) {
//
not
needed
here
}
}
}
II. Le fichier manifest.xml▲
Le fichier manifest.xml est décrit de manière complète à la page :
http://developer.android.com/guide/topics/manifest/manifest-intro.html
Ce fichier est le centre névralgique de votre application et ce pour plusieurs raisons :
- D’une part il décrit les besoins de votre application, en termes de SDK, de compatibilité matérielle, d’API utilisées et d’utilisation de services du système,
- D’autre part, il décrit ce qu’offre votre application au système (Activity, ContentProvider, Service…),
- Enfin, il décrit les éléments auxquels votre application réagit au moyen des IntentFilters et d’URI ainsi que les permissions nécessaire pour les utiliser.
Ce fichier est analysé par les markets pour cibler les appareils qui sont éligibles pour le téléchargement de votre application. Il faut donc être très attentif à sa mise en place.
Pour décrire ces éléments, ce fichier possède la structure globale suivante :
<
manifest
>
<
uses-permission
/
>
<
permission
/
>
<
permission-tree
/
>
<
permission-group
/
>
<
instrumentation
/
>
<
uses-sdk
/
>
<
uses-configuration
/
>
<
uses-feature
/
>
<
supports-screens
/
>
<
compatible-screens
/
>
<
supports-gl-texture
/
>
<
application
>
<
activity
>
<
intent-filter
>
<
action
/
>
<
category
/
>
<
data
/
>
<
/
intent-filter
>
<
meta-data
/
>
<
/
activity
>
<
activity-alias
>
<
intent-filter
>
. . . <
/
intent-filter
>
<
meta-data
/
>
<
/
activity-alias
>
<
service
>
<
intent-filter
>
. . . <
/
intent-filter
>
<
meta-data
/
>
<
/
service
>
<
receiver
>
<
intent-filter
>
. . . <
/
intent-filter
>
<
meta-data
/
>
<
/
receiver
>
<
provider
>
<
grant-uri-permission
/
>
<
meta-data
/
>
<
/
provider
>
<
uses-library
/
>
<
/
application
>
<
/
manifest
>
N’hésitez pas à assouvir votre curiosité en allant sur la page précédemment citée pour connaître chacune de ces balises.