I. Filtres d'intentions▲
I-A. Objectif des intentions et bonne pratique▲
Les applications Android doivent se décomposer en activités distinctes les unes des autres. Au sein de ces applications, les activités doivent pouvoir s'enchaîner, s'appeler, retourner à leur activité principale. Pour mettre en place cette communication entre activités, Android utilise le système des intentions. Celles-ci permettent d'envoyer des messages d'une activité vers une autre avec des données pour les activer.
Dans ce contexte, il faut se demander si l'activité mère, quand elle lance une autre activité, est dans une relation maître-esclave ou dans une relation de pair à pair.
Dans le premier cas, l'activité mère attend que l'activité fille finisse et est informée de cette fin. Dans l'autre cas, l'activité fille est lancée, l'activité mère n'a plus de contact avec elle.
I-B. Définition▲
Une intention peut se traduire par « je veux, toi système, que tu fasses … ». Et cela dépend de l'action demandée et du contexte. Il faut les considérer comme de la colle entre activités permettant de les lier les unes aux autres.
Une intention est ainsi une action associée à des données. Les actions sont des constantes : ACTION_VIEW, ACTION_EDIT, ACTION_PICK, les données sont des URI.
Les intentions peuvent se spécifier ; on peut leur rajouter des informations :
· Une catégorie : LAUNCHER (pour les activités présentes dans le lanceur Android), DEFAULT ou ALTERNATIVE.
· Un type MIME : indique le type de la ressource (comme pour les mails).
· Un composant : indique la classe d'activité censée recevoir l'intention. Cette méthode n'est pas la plus heureuse, car elle fige l'activité associée. Soit vous l'avez codée vous-même, dans ce cas, c'est naturel, sinon, l'utilisation des autres paramètres est préconisée.
· Des « extras » : un bundle d'informations permettant de transférer des données à l'activité cible.
I-C. Routage des intentions▲
Il est préférable d'utiliser les URI et le type MIME, plutôt que Composant si vous souhaitez dialoguer avec une application qui n'est pas la vôtre. En d'autres termes, laissez Android se charger de trouver l'activité cible.
Pour qu'une activité soit éligible au routage d'une intention, il faut qu'elle supporte :
· l'action indiquée ;
· le type MIME indiqué ;
· ainsi que la catégorie.
Il faut donc spécifier suffisamment pour permettre à Android de trouver votre activité cible.
I-C-1. Déclarer des intentions▲
Les déclarations se déclarent dans le fichier manifest.xml de l'application.
Pour être éligible, une activité doit ainsi déclarer les intentions auxquelles elle souhaite répondre, typiquement, pour une activité qui se lance par l'IHM principale d'Android, on rajoute :
<
intent-filter
>
<
action
android
:
name
=
"
android.intent.action.MAIN
"
/
>
<
category
android
:
name
=
"
android.intent.category.LAUNCHER
"
/
>
<
/
intent-filter
>
Un autre exemple plus utile est la déclaration d'une intention qui n'est pas main launcher :
<
intent-filter
>
<
action
android
:
name
=
"
android.intent.action.VIEW
"
/
>
<
action
android
:
name
=
"
android.intent.action.EDIT
"
/
>
<
action
android
:
name
=
"
android.intent.action.PICK
"
/
>
<
category
android
:
name
=
"
android.intent.category.DEFAULT
"
/
>
<
data
mimeType
:
name
=
"
vnd.android.cursor.dir/vnd.google.note
"
/
>
<
/
intent-filter
>
Cette intention déclare pouvoir répondre aux actions de visualisation et d'édition associées à un objet de type vnd.android.cursor.dir/vnd.google.note (c'est l'URI de la définition de l'objet). De même, le PICK permet de récupérer l'un de ces objets et de retourner dans l'application appelante. (Cf. http://developer.android.com/reference/android/content/Intent.html pour l'exemple complet).
Les intentions peuvent ainsi, en interne de l'application, faire des appels entre ces sous-modules. Ou en termes Android, les intentions permettent d'appeler différentes activités au sein de votre application de manière transparente.
I-C-2. Récepteur d'intention▲
Typiquement, au lieu de recevoir une intention avec une activité, il peut être utile d'implémenter au sein de l'application une classe spécifique qui s'occupe de la récupération des intentions (comme un service) et de leur traitement qui peut être, du coup, contextuel (appel à un service, à plusieurs activités…).
Pour cela, il suffit de faire étendre votre classe réceptrice de la classe BroadCastReceiver et la déclarer dans le manifest.xml par :
<
receiver
android
:
name
=
"
maClasseReceptionniste
"
/
>
Cette classe doit étendre la méthode onReceive. De plus, elle ne vit que lors de la réception d'une intention, elle est créée à la réception et détruite dès que la méthode onReceive est terminée. Ainsi, la classe BroadcastReceiver ne peut être liée à un service, une fenêtre de dialogue ou quoi que ce soit d'autre n'appartenant pas à son thread.
La seule exception à cette règle est quand votre classe qui hérite de BroadCastReceiver est implémentée par un composant d'une durée de vie longue (un service, une activité), dans ce cas, elle sera détruite quand l'hôte (bref le service, l'activité) est détruite.
Dans ce cas, le receveur ne se déclare pas dans le manifest.xml, il faut appeler la méthode registerReceiver dans le code de votre activité (service) au sein de la méthode onResume() et unregisterReceiver dans la méthode onPause().
Seuls les récepteurs actifs peuvent recevoir des intentions…
I-D. Lancer des activités▲
I-D-1. Instanciation▲
Pour instancier une activité interne à son programme :
final
Intent intent =
new
Intent
(
).setClass
(
this
, MyDaughterActivity.class
);
Cette instruction déclare une intention associée à l'activité MyDaughterActivity qui est une classe de votre programme et this qui est l'activité courante.
Pour instancier une activité externe à votre programme, il vaut mieux spécifier une URI et une action, par exemple :
//
Retrieve
latitude
and
longitude
String latitude =
"
43.565715431592736
"
;
String longitude =
"
1.398482322692871
"
;
//
Format
the
associated
uri
Uri uriGeo =
Uri.parse
(
"
geo:
"
+
latitude +
"
,
"
+
longitude);
//
Declare
the
associated
Intent
final
Intent intentGeo =
new
Intent
(
Intent.ACTION_VIEW, uriGeo);
Cette intention demande au système d'afficher une URI de type géo, à lui de se débrouiller pour trouver quelle activité répondra à cette intention.
I-D-2. Appel▲
Pour lancer une activité, deux cas s'offrent à vous, le cas de la relation pair-à-pair ou le cas maître-esclave entre vos deux activités.
Dans le cas pair-à-pair (c.-à-d. l'activité mère lance l'activité fille et n'attend rien) :
startActivity
(
intentGeo);
Dans le cas maître-esclave :
startActivityForResult
(
intentContactForResult, INTENT_CALL_ID);
Il faut alors implémenter dans l'activité mère la méthode onActivityResult qui est appelée lorsque l'activité fille prend fin. L'activité fille, elle, doit implémenter la méthode setResult() qui généralement renvoie RESULT_OK ou RESULT_CANCELLED.
On peut récupérer aussi dans onActivityResult un String contenant des informations (une URL par exemple) ou un objet Bundle.
I-D-2-a. Exemple▲
Dans cet exemple, nous montrons comment lancer :
· une activité qui appartient à votre programme ;
· une activité qui permet de se géolocaliser avec une latitude/longitude grâce à la carte ;
· une activité qui récupère un contact et affiche les informations associées.
Ce projet est donc séparé en deux classes :
· l'activité principale qui lance les autres activités et qui implémente onActivityResult pour traiter les activités lancées avec la méthode startActivityForResults ;
· l'activité otherActivity qui ne fait qu'afficher un champ texte.
Le code Java de la classe principale :
public
class
IntentionSimpleTuto extends
Activity {
/**
*
The
unique
identifier
for
the
call
using
Intent
of
contact
*/
private
final
int
INTENT_CALL_ID =
10012220
;
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.main);
//
To
launch
your
own
activity
//
First
declare
an
intent
final
Intent intent =
new
Intent
(
).setClass
(
this
, OtherActivity.class
);
//
Then
add
the
action
to
the
button:
Button btnOtherActivity =
(
Button) findViewById
(
R.id.launchOther);
btnOtherActivity.setOnClickListener
(
new
View.OnClickListener
(
) {
public
void
onClick
(
View v) {
//
Launch
the
activity
startActivity
(
intent);
}
}
);
//
Do
the
same
for
Geo*
//
Retrieve
latitude
and
longitude
String latitude =
"
43.565715431592736
"
;
String longitude =
"
1.398482322692871
"
;
//
Format
the
associated
uri
Uri uriGeo =
Uri.parse
(
"
geo:
"
+
latitude +
"
,
"
+
longitude);
//
Declare
the
associated
Intent
final
Intent intentGeo =
new
Intent
(
Intent.ACTION_VIEW, uriGeo);
//
instanciate
the
button
Button btnGeoActivity =
(
Button) findViewById
(
R.id.launchGeo);
btnGeoActivity.setOnClickListener
(
new
View.OnClickListener
(
) {
public
void
onClick
(
View v) {
//
Launch
the
activity
startActivity
(
intentGeo);
}
}
);
//
Do
the
same
for
Contact
waiting
for
result
//
Format
the
associated
uri
Uri uriContact =
Uri.parse
(
"
content://contacts/people
"
);//
"content://contacts/people"
//
Declare
the
intent:
final
Intent intentContactForResult =
new
Intent
(
Intent.ACTION_PICK, uriContact);
//
instanciate
the
button
Button btnContactActivityForResults =
(
Button) findViewById
(
R.id.launchContactForResult);
btnContactActivityForResults.setOnClickListener
(
new
View.OnClickListener
(
) {
public
void
onClick
(
View v) {
//
Launch
the
activity
startActivityForResult
(
intentContactForResult, INTENT_CALL_ID);
}
}
);
}
/*
*
(non-Javadoc)
*
*
@see
android.app.Activity#onActivityResult(int,
int,
android.content.Intent)
*/
@
Override
protected
void
onActivityResult
(
int
requestCode, int
resultCode, Intent data) {
super
.onActivityResult
(
requestCode, resultCode, data);
if
(
requestCode =
=
INTENT_CALL_ID) {
if
(
resultCode =
=
Activity.RESULT_OK) {
Uri contactData =
data.getData
(
);
Toast.makeText
(
IntentionSimpleTuto.this
,
"
Result
ok
(uri:
"
+
contactData +
"
)
data
"
+
contactData.toString
(
), Toast.LENGTH_LONG).show
(
);
Cursor c =
managedQuery
(
contactData, null
, null
, null
, null
);
StringBuffer columnName =
new
StringBuffer
(
"
Result
:
"
);
String value;
String name=
"
...
"
;
if
(
c.moveToFirst
(
)) {
for
(
int
i =
0
; i <
c.getColumnCount
(
); i+
+
) {
value =
c.getString
(
c.getColumnIndexOrThrow
(
c.getColumnName
(
i)));
columnName.append
(
"
,\r\n
"
+
c.getColumnName
(
i) +
"
:
"
+
value);
}
Toast.makeText
(
IntentionSimpleTuto.this
, columnName,
Toast.LENGTH_LONG).show
(
);
name =
c.getString
(
c.getColumnIndexOrThrow
(
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
Toast.makeText
(
IntentionSimpleTuto.this
, "
Et
le
nom
:
"
+
name,
Toast.LENGTH_LONG).show
(
);
}
}
else
if
(
resultCode =
=
Activity.RESULT_CANCELED) {
Toast.makeText
(
IntentionSimpleTuto.this
, "
Result
ko
no
contact
picked
"
,
Toast.LENGTH_LONG).show
(
);
}
}
}
}
Le code Java de la seconde activité :
public
class
OtherActivity extends
Activity {
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.other_activity);
}
}
Le mainLayout.xml de l'activité principale qui déclare trois boutons et un champ texte :
<?
xml version="1.0" encoding="utf-8"?
>
<
LinearLayout
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
android
:
orientation
=
"
vertical
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
>
<
TextView
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
wrap_content
"
android
:
text
=
"
@string/hello
"
/
>
<
Button
android
:
text
=
"
@string/launchOther
"
android
:
id
=
"
@+id/launchOther
"
android
:
layout_width
=
"
wrap_content
"
android
:
layout_height
=
"
wrap_content
"
>
<
/
Button
>
<
Button
android
:
text
=
"
@string/launchGeo
"
android
:
id
=
"
@+id/launchGeo
"
android
:
layout_width
=
"
wrap_content
"
android
:
layout_height
=
"
wrap_content
"
>
<
/
Button
>
<
Button
android
:
text
=
"
@string/launchContactForResult
"
android
:
id
=
"
@+id/launchContactForResult
"
android
:
layout_width
=
"
wrap_content
"
android
:
layout_height
=
"
wrap_content
"
>
<
/
Button
>
<
/
LinearLayout
>
Le layout de other_activity.xml :
<?
xml version="1.0" encoding="utf-8"?
>
<
LinearLayout
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
android
:
orientation
=
"
vertical
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
>
<
TextView
android
:
id
=
"
@+id/otherTextView
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
wrap_content
"
android
:
text
=
"
@string/otheractivity
"
/
>
<
/
LinearLayout
>
Le fichier des chaînes de caractères (string.xml) :
<?
xml version="1.0" encoding="utf-8"?
>
<
resources
>
<
string
name
=
"
hello
"
>
Hello World, IntentionSimpleTuto!<
/
string
>
<
string
name
=
"
app_name
"
>
IntentionSimpleTuto<
/
string
>
<
string
name
=
"
launchOther
"
>
Launch the activity other<
/
string
>
<
string
name
=
"
launchGeo
"
>
Launch the activity Geo<
/
string
>
<
string
name
=
"
launchContactForResult
"
>
Launch the activity Contact for results<
/
string
>
<
string
name
=
"
otheractivity
"
>
And an other activity appears in front of your amazed eyes !<
/
string
>
<
/
resources
>
Et le fichier manifest.xml :
<?
xml version="1.0" encoding="utf-8"?
>
<
manifest
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
package
=
"
net.stinfoservices.android.tuto.core
"
android
:
versionCode
=
"
1
"
android
:
versionName
=
"
1.0
"
>
<
application
android
:
icon
=
"
@drawable/icon
"
android
:
label
=
"
@string/app_name
"
>
<
activity
android
:
name
=
"
.IntentionSimpleTuto
"
android
:
label
=
"
@string/app_name
"
>
<
intent-filter
>
<
action
android
:
name
=
"
android.intent.action.MAIN
"
/
>
<
category
android
:
name
=
"
android.intent.category.LAUNCHER
"
/
>
<
/
intent-filter
>
<
/
activity
>
<
activity
android
:
name
=
"
OtherActivity
"
>
<
/
activity
>
<
/
application
>
<
uses-sdk
android
:
minSdkVersion
=
"
8
"
/
>
<
uses-permission
android
:
name
=
"
android.permission.READ_CONTACTS
"
>
<
/
uses-permission
>
<
/
manifest
>
I-E. Cas particulier : la navigation par onglets▲
Pour des raisons de sécurité, une activité ne peut héberger les activités d'autres applications au sein de ses onglets. Ainsi, pour obtenir une navigation par onglet, il faut tout d'abord créer l'activité contenante qui est une TabActivity et lui rajouter des onglets que l'on peuple avec des intentions. Pour cela, on récupère le TabHost de la classe TabActivity et pour chacun des onglets on effectue les opérations suivantes :
· définition de l'Intent qui représente l'activité contenue par l'onglet ;
· récupération puis définition du TabSpec (son tag, son label, son contenu via l'Intent) ;
· ajout du TabSpec au TabHost.
Le code Java de la classe principale :
public
class
MultiTabBrowserTuto extends
TabActivity {
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
//
Define
the
Tab
structure
setContentView
(
R.layout.main);
//
Retrieve
the
ressource
to
access
to
the
icon
Resources resources =
getResources
(
); //
Resource
object
to
get
Drawables
//
Set
the
tabHost
(set
it
has
final
to
use
it
in
the
OnTabChangeListener)
final
TabHost tabHost =
getTabHost
(
);
//
Define
the
tabSpec
that
can
be
thought
has
the
content
of
the
TabPanel
TabHost.TabSpec tabSpec;
//
Define
the
intent
that
is
used
to
populate
the
tabSpec
Intent intent;
//
Create
an
Intent
to
launch
an
Activity
for
the
tab
intent =
new
Intent
(
).setClass
(
this
, SiteWebSTI.class
);
//
Initialize
a
TabSpec
for
each
tab
and
add
it
to
the
TabHost
//
Get
a
new
TabHost.TabSpec
associated
with
this
tab
host.
tabSpec =
tabHost.newTabSpec
(
"
SiteWebSti
"
);
//
Define
its
indicator
the
label
displayed
(it
should
be
//
ressources.getString(R.string.stringId)
tabSpec.setIndicator
(
"
SiteSti
"
, resources.getDrawable
(
R.drawable.ic_tab));
//
Define
the
content
of
the
Spec
(the
TabPanel)
tabSpec.setContent
(
intent);
//
Add
it
to
the
tab
container
tabHost.addTab
(
tabSpec);
//
Do
the
same
with
the
tab
that
displays
a
simple
TextView:
//
Define
the
intent
that
will
be
displayed
intent =
new
Intent
(
).setClass
(
this
, TextViewActivity.class
);
//
Get
a
new
TabHost.TabSpec
associated
with
this
tab
host.
tabSpec =
tabHost.newTabSpec
(
"
textView
"
);
//
Define
its
indicator
the
label
displayed
(it
should
be
//
ressources.getString(R.string.stringId)
tabSpec.setIndicator
(
"
TextView
"
, resources.getDrawable
(
R.drawable.ic_tab));
//
Define
the
content
of
the
Spec
(the
TabPanel)
tabSpec.setContent
(
intent);
//
Add
it
to
the
tab
container
tabHost.addTab
(
tabSpec);
//
Do
the
same
with
the
tab
that
displays
a
simple
Clock
(analogic
and
digital):
//
Define
the
intent
that
will
be
displayed
intent =
new
Intent
(
).setClass
(
this
, ClockAD.class
);
//
Get
a
new
TabHost.TabSpec
associated
with
this
tab
host.
tabSpec =
tabHost.newTabSpec
(
"
clock
"
);
//
Define
its
indicator
the
label
displayed
tabSpec.setIndicator
(
"
Clock
"
, resources.getDrawable
(
R.drawable.ic_tab));
//
Define
the
content
of
the
Spec
(the
TabPanel)
tabSpec.setContent
(
intent);
//
Add
it
to
the
tab
container
tabHost.addTab
(
tabSpec);
//
Define
the
current
tab
displayed
(here
the
clock)
tabHost.setCurrentTab
(
2
);
//
Add
a
listener
that
just
displays
a
Toast
with
the
tag
of
the
new
selected
tab
tabHost.setOnTabChangedListener
(
new
OnTabChangeListener
(
) {
@
Override
public
void
onTabChanged
(
String tabId) {
Toast.makeText
(
getApplicationContext
(
), "
New
tab
selection
:
"
+
tabHost.getCurrentTabTag
(
),
Toast.LENGTH_SHORT).show
(
);
}
}
);
}
}
Les codes Java des classes des activités sont des codes d'activités normales. Les classes ne savent pas qu'elles vont être utilisées au sein d'onglets.
Le code Java de la classe SiteWebSti qui ne fait que déclarer un WebKit qui pointe vers un site :
public
class
SiteWebSTI extends
Activity {
WebView browser;
@
Override
public
void
onCreate
(
Bundle icicle) {
super
.onCreate
(
icicle);
browser=
new
WebView
(
this
);
setContentView
(
browser);
browser.loadUrl
(
"
http://www.stinfoservices.net/
"
);
}
}
Le code Java de la classe TextView qui ne fait que déclarer un TextView avec un texte simple :
public
class
TextViewActivity extends
Activity {
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
TextView textview =
new
TextView
(
this
);
textview.setText
(
"
Hello
Guy
this
a
TabPanel
also
called
TabSpec
"
);
setContentView
(
textview);
}
}
Le code Java de la classe ClockAD qui ne fait que charger son fichier de layout.xml nommé clock.xml :
public
class
ClockAD extends
Activity {
/**
Called
when
the
activity
is
first
created
.
*/
@
Override
public
void
onCreate
(
Bundle savedInstanceState) {
super
.onCreate
(
savedInstanceState);
setContentView
(
R.layout.clock);
}
}
Le fichier de layout associé à la classe ClockAD qui se nomme clock. Il déclare deux éléments, une horloge digitale et une analogique :
<?
xml version="1.0" encoding="utf-8"?
>
<
RelativeLayout
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
android
:
orientation
=
"
vertical
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
>
<
AnalogClock
android
:
id
=
"
@+id/analog
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
wrap_content
"
android
:
layout_centerHorizontal
=
"
true
"
android
:
layout_alignParentTop
=
"
true
"
/
>
<
DigitalClock
android
:
id
=
"
@+id/digital
"
android
:
layout_width
=
"
wrap_content
"
android
:
layout_height
=
"
wrap_content
"
android
:
layout_centerHorizontal
=
"
true
"
android
:
layout_below
=
"
@id/analog
"
/
>
<
/
RelativeLayout
>
Puis les fichiers principaux de l'application :
Le fichier Layout principal de la classe MultiTabBrowserTuto qui déclare la structure usuelle d'une application à onglets :
<?
xml version="1.0" encoding="utf-8"?
>
<
TabHost
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
android
:
id
=
"
@android:id/tabhost
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
>
<
LinearLayout
android
:
orientation
=
"
vertical
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
android
:
padding
=
"
5dp
"
>
<
TabWidget
android
:
id
=
"
@android:id/tabs
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
wrap_content
"
/
>
<
FrameLayout
android
:
id
=
"
@android:id/tabcontent
"
android
:
layout_width
=
"
fill_parent
"
android
:
layout_height
=
"
fill_parent
"
android
:
padding
=
"
5dp
"
/
>
<
/
LinearLayout
>
<
/
TabHost
>
Le fichier de ressource pour les icônes qui re-route automatiquement vers une ressource en fonction de son état « de sélection » :
<?
xml version="1.0" encoding="UTF-8"?
>
<
selector
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
>
<!--
When
selected,
use
grey
-->
<
item
android
:
drawable
=
"
@drawable/ic_tab_grey
"
android
:
state_selected
=
"
true
"
/
>
<!--
When
not
selected,
use
white
-->
<
item
android
:
drawable
=
"
@drawable/ic_tab_white
"
/
>
<
/
selector
>
Il est à noter que le dossier drawable contient deux icônes, ic_tab_grey.png et ic_tab_white.png qui sont dans les en-têtes des onglets et qui sont pointés par le fichier ci-dessus.
Et enfin le fichier manifest.xml de l'application. Trois choses sont importantes dans ce manifest.xml :
· Chaque activité est déclarée (il ne faut pas l'oublier).
· L'attribut noTitleBar est spécifié pour l'activité principale, ce qui permet de gagner un peu de place en hauteur.
· L'accès à Internet est demandé (nécessaire à l'activité WebKit)
<?
xml version="1.0" encoding="utf-8"?
>
<
manifest
xmlns
:
android
=
"
http://schemas.android.com/apk/res/android
"
package
=
"
net.stinfoservices.android.tuto.gui
"
android
:
versionCode
=
"
1
"
android
:
versionName
=
"
1.0
"
>
<
application
android
:
icon
=
"
@drawable/icon
"
android
:
label
=
"
@string/app_name
"
>
<
activity
android
:
name
=
"
.MultiTabBrowserTuto
"
android
:
label
=
"
@string/app_name
"
android
:
theme
=
"
@android:style/Theme.NoTitleBar
"
>
<
intent-filter
>
<
action
android
:
name
=
"
android.intent.action.MAIN
"
/
>
<
category
android
:
name
=
"
android.intent.category.LAUNCHER
"
/
>
<
/
intent-filter
>
<
/
activity
>
<
activity
android
:
name
=
"
SiteWebSTI
"
>
<
/
activity
>
<
activity
android
:
name
=
"
TextViewActivity
"
>
<
/
activity
>
<
activity
android
:
name
=
"
ClockAD
"
>
<
/
activity
>
<
/
application
>
<
uses-sdk
android
:
minSdkVersion
=
"
8
"
/
>
<
uses-permission
android
:
name
=
"
android.permission.INTERNET
"
>
<
/
uses-permission
>
<
/
manifest
>
Voilà, une activité affichant un navigateur avec des onglets qui marchent avec les intentions. Ce qui correspond à l'état de l'art pour un programme Android qui se doit d'être un ensemble d'activités liées les unes aux autres au moyen d'intents.
I-F. Filtres d'intention standard▲
Vous trouverez dans http://developer.android.com/reference/android/content/Intent.html une très bonne description de ces intentions.
Les points suivants listent les paramètres les plus utilisés pour la déclaration d'intentions.
I-F-1. Action standard des activités▲
Actions courantes et standard que les Intents définissent pour lancer les activités (usuellement au moyen de startActivity(Intent)). Les plus importantes et les plus utilisées sont de loin ACTION_MAIN et ACTION_EDIT.
I-F-2. Actions standard d'un Broadcast▲
Actions courantes et standard que les Intents définissent pour recevoir les BroadCast (usuellement au moyen de registerReceiver(BroadcastReceiver, IntentFilter) ou au moyen du tag <receiver> dans le fichier manifest.xml).
- ACTION_TIME_TICK
- ACTION_TIME_CHANGED
- ACTION_TIMEZONE_CHANGED
- ACTION_BOOT_COMPLETED
- ACTION_PACKAGE_ADDED
- ACTION_PACKAGE_CHANGED
- ACTION_PACKAGE_REMOVED
- ACTION_PACKAGE_RESTARTED
- ACTION_PACKAGE_DATA_CLEARED
- ACTION_UID_REMOVED
- ACTION_BATTERY_CHANGED
- ACTION_POWER_CONNECTED
- ACTION_POWER_DISCONNECTED
- ACTION_SHUTDOWN
I-F-3. Catégories standard▲
Catégories courantes et standard qui peuvent être utilisées pour classifier les Intents au moyen de la méthode addCategory(String).
I-F-4. Extra Data standard▲
Champs courants et standard qui peuvent être utilisés comme données supplémentaires au moyen de la méthode putExtra(String, Bundle).
- EXTRA_ALARM_COUNT
- EXTRA_BCC
- EXTRA_CC
- EXTRA_CHANGED_COMPONENT_NAME
- EXTRA_DATA_REMOVED
- EXTRA_DOCK_STATE
- EXTRA_DOCK_STATE_CAR
- EXTRA_DOCK_STATE_DESK
- EXTRA_DOCK_STATE_UNDOCKED
- EXTRA_DONT_KILL_APP
- EXTRA_EMAIL
- EXTRA_INITIAL_INTENTS
- EXTRA_INTENT
- EXTRA_KEY_EVENT
- EXTRA_PHONE_NUMBER
- EXTRA_REMOTE_INTENT_TOKEN
- EXTRA_REPLACING
- EXTRA_SHORTCUT_ICON
- EXTRA_SHORTCUT_ICON_RESOURCE
- EXTRA_SHORTCUT_INTENT
- EXTRA_STREAM
- EXTRA_SHORTCUT_NAME
- EXTRA_SUBJECT
- EXTRA_TEMPLATE
- EXTRA_TEXT
- EXTRA_TITLE
- EXTRA_UID
II. La rotation▲
Lors de la rotation de l'écran, votre activité est détruite puis reconstruite.
Vous pouvez vous référer à la partie 5.2 : Gestion des événements du cycle de vie d'une activité.
Pour désactiver la rotation, il suffit de rajouter dans son fichier manifest.xml le type d'orientation (landscape, portrait ou sensor) de votre activité :
<
activity
android
:
name
=
"
.LaunchDemo
"
android
:
label
=
"
LaunchDemo
"
>
<
intent-filter
>
<
action
android
:
name
=
"
android.intent.action.MAIN
"
android
:
screenOrientation
=
"
landscape
"
/
>
<
category
android
:
name
=
"
android.intent.category.LAUNCHER
"
/
>
<
/
intent-filter
>
<
/
activity
>
Si vous mettez le paramètre sensor, cela demande à Android de faire pivoter l'activité en fonction de l'accéléromètre qui détecte quand l'écran est en mode portrait ou pas.
IV. Android2EE: La Formation et l'Expertise Android à votre service▲
Android2EE
|
|
|
V. Récupération des tutoriels et lecture des autres chapitres du livre▲
Vous pouvez lire l'ensemble de l'ouvrage sur Android2EE, à cet adresse Livre en consultation. Les 28 chapitres sont disponibles. Un tutorial sera bientôt disponible sur le site Android2EE.
VI. Le site Android2ee, une référence pour le développement Android.▲
Le site Android2EE vous propose des tutoriels, des articles, des vidéos, des conférences, des eBooks en libre consultation pour monter en compétence sur la technologie Android.
Vous trouverez tout cela dans la partie « Open Resources ».
N'hésitez plus visitez-le ! Android2EE