Développement D'application Mobile
Développement D'application Mobile
1
Développement d’application mobile
Il y a deux façons de développement d’applications mobiles
Développement mobile natif:
Android: Java, Android SDK, Android Studio, Google Play
IOS: Objective C, IOS SDK, Xcode, Apple App Store
Windows Phone: C#, Windows Phone SDK, Visual Studio, Microsoft Marketplace
Développement mobile hybride (cross platform)
Partie web: HTML, CSS, JavaScript
Partie native: Apache CORDOVA
Plateformes: Adobe PhoneGap, IBM MobileFirst, IONIC, React Native, Flutter …
2
Développement d’application mobile Android
Introduction
Qu’est-ce qu’Android ?
Android est une surcouche au dessus d’un système Linux. C’est un système
d’exploitation mobile fondé sur Linux et développé par Google
Historique
La première version est lancée en 2007 après le rachat par Google de la start up du
même nom. Depuis il y a eu plusieurs versions, on est actuellement à la version 12
(Octobre 2021) et l’API 31.
Une API (Application Programming Interface) est un ensemble de bibliothèques de
classes pour programmer des applications. Son numéro de version donne un indice
de ses possibilités.
3
Versions d’API
4
Les applications
Les applications android sont actuellement:
Natives: ce qui veut dire qu’elles sont programmées en Java, C++ ou
Kotlin; et sont compilées et fournies avec leurs données sous forme
d’archive Jar (fichier APK)
Web app: applications pour navigateur internet, développées en
HTML5, CSS3, JavaScript …
Hybrides: elles sont développées dans un framework comme Flutter,
Iconic, React Native ... Ces framework font abstraction des particularités
du système d’exploitation, la même application peut tourner de la même
façon sur différentes plateformes (Android, IOS, Windows, Linux)
5
Application native
7
SDK Android et Android Studio
9
Architecture d’Android
10
Composants d’une application Android
Activités (Activities) suivent le modèle architectural MVC (Modèle Vue Composant):
Composants principaux d’une application Android
Contrôleurs de l’application, il affiche les vues (layouts) contenant des données provenant des
modèles
Réagissent aux événements issus des interactions des utilisateurs avec les vues
Services;
Assurent le traitement de fond associé à une application
Récepteurs de diffusion (broadcast receivers):
Gèrent la communication entre le système d’exploitation Android et les applications
La communication entre les composants des applications se fait par envoie de message via
des Intents
Fournisseurs de contenu (content providers):
Permettre l’accès aux données: contacts, agenda, photos, …
11
Composants d’une application Android
Activité:
C’est la brique de base, par défaut une application est une activité
C’est un morceau de code qui s’exécute à la demande de l’utilisateur, de l’OS,
peut être tué par l’utilisateur ou l’OS pour préserver la mémoire du téléphone
Une activité peut interagir
o avec l’utilisateur en lui demandant des données
o avec d’autres activités ou services en émettant des intentions ou
fournissant du contenu
Service:
C’est l’analogue des services ou démons qui s’exécutent sur un OS classique
C’est un morceau de code qui s’exécute habituellement en arrière-plan entre le
moment où il est lancé jusqu’à l’arrêt du mobile.
12
Composants d’une application Android
Intention (intent):
Une intention (intent en anglais) est un message contenant des données émis par
Android (l’OS, une autre application, ou un autre service)
pour prévenir les applications s’exécutant de la survenue d’un événement :
déplacement du GPS, réception d’un SMS. . .
Fournisseur de contenus:
Une application Android répond normalement à un besoin et fournit donc certaines
fonctionnalités: on appelle cela un fournisseur de contenus
Une application doit normalement se déclarer comme fournisseur de tel ou tel
contenu (lorsqu’ils sont identifiés)
ne autre application qui nécessiterait à un moment ce contenu émet une requête
auprès de l’OS pour l’obtenir
L’OS lance alors directement l’application déclarée comme fournisseur
13
Composants d’une application Android
L’interface utilisateur d’une application Android est composée d’écrans. Un « écran
» correspond à une activité, par exemple :
afficher des informations
éditer des informations
Les dialogues et les pop-up ne sont pas des activités, ils se superposent
temporairement à l’écran d’une activité
Android permet de naviguer d’une activité à l’autre, par exemple:
une action de l’utilisateur, bouton, menu ou l’application fait aller sur l’écran
suivant
le bouton back ramène sur l’écran précédent.
14
Structure d’une interface utilisateur
L’interface d’une activité est composée de vues
vues élémentaires : boutons, zones de texte, cases à cocher. . .
vues de groupement qui permettent l’alignement des autres vues : lignes,
tableaux, onglets, panneaux à défilement. . .
Chaque vue d’une interface est gérée par un objet Java, comme en Java classique,
avec AWT, Swing ou JavaFX.
Il y a une hiérarchie de classes dont la racine est View. Elle a une multitude de sous-
classes, dont par exemple TextView, elle-même ayant des sous-classes, par exemple
Button.
Les propriétés des objets sont généralement visibles à l’écran : titre, taille, position,
etc.
15
Structure d’une interface utilisateur
Ces objets d’interface pourraient être créés manuellement, mais :
c’est très complexe, car il y a une multitude de propriétés à définir,
ça ne permet pas de localiser, c’est à dire adapter une application à chaque
pays (sens de lecture de droite à gauche)
Alors, on préfère définir l’interface par l’intermédiaire d’un fichier XML qui décrit
les vues à créer.
Il est lu automatiquement par le système Android lors du lancement de l’activité et transformé
en autant d’objets Java qu’il faut.
Chaque objet Java est retrouvé grâce à un « identifiant de ressource ».
16
A la rencontre de Android studio
Android studio est l’IDE officiel de développement d’applications Android. Il est basé sur
l’IDE IntelliJ de Jetbrains.
Structure d’un projet dans Android studio
17
A la rencontre de Android studio
Interface utilisateur de Android studio: la fenêtre principale de Android studio est constituée
des espaces logiques numérotés suivants, comme le montre la figure suivante:
1. La barre d’outils: permet de faire beaucoup d’actions dont l’exécution de votre application
2.La barre de navigation: permet de naviguer à travers le projet et d’ouvrir les fichiers pour édition
3. La fenêtre d’édition: est l’endroit où on peut créer et modifier du code.
4. La barre de fenêtre d’outils: contient les boutons permettant de d’étendre ou de réduire les fenêtres d’outils
individuelles.
5. Les fenêtres d’outils: donne accès à des taches spécifiques telle que la gestion de projet
6. La barre d’état: affiche l’état du projet et de l’IDE lui-même ainsi que les messages d’avertissement.
18
A la rencontre de Android studio
19
Création de notre première application Android
Nous voulons créer l’application dont l’écran d’acceuil est donné dans la figure suivante:
20
Création de notre première application Android
L’utilisateur est supposé saisir du texte dans la zone de texte et cliquer sur le bouton send;
après cela, le texte saisi doit être récupéré et affiché dans un autre écran. Au final on doit
avoir quelque chose qui ressemble à ceci:
21
Création d’un écran
Chaque écran est géré par une instance d’une sous-classe de Activity que vous programmez.
Il faut au moins surcharger la méthode onCreate selon ce qui doit être affiché sur l’écran :
Exemple:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
C’est l’appel setContentView(...) qui met en place l’interface. Son paramètre est un
identifiant de ressource, c’est à dire d’une disposition de vues d’interface.
22
Ressources
Définition
Les ressources sont tout ce qui n’est pas programme dans une application. Dans Android, ce
sont les textes, messages, icones, images, sons, interfaces, styles, etc.
C’est une bonne séparation, car cela permet d’adapter une application facilement pour
beaucoup de pays, cultures et langues. On n’a pas à bidouiller dans le code source et
recompiler chaque fois. C’est le même code compilé, mais avec des ressources spécifiques.
Le programmeur prévoit simplement des variantes linguistiques des ressources qu’il souhaite
permettre de traduire. Ce sont des sous-dossier, exemple: values-fr, values-en, values-jp, etc
et il n’y a qu’à modifier des fichiers XML.
Identifiant de ressource
Dans Android Studio, il faut faire le lien entre les ressources et les programmes. On le fait à
travers un identifiant.
Par exemple, la méthode setContentView dans l’exemple précédent demande l’identifiant de
l’interface à afficher dans l’écran qui est R.layout.main. 23
Ressources
Un identifiant est un entier qui est généré automatiquement par le SDK Android. Parce que il y
a de très nombreux identifiants dans une application, ils sont tous regroupés dans une classe
spéciale appelée R
chaque vue peut posséder un identifiant
chaque image, icone possède un identifiant
chaque texte, message possède un identifiant
chaque style, theme, etc. etc.
Génération de la classe R
Le SDK Android construit automatiquement cette classe statique appelée R. Elle ne contient
que des constantes entières groupées par catégories : id, layout, menu. . . :
24
Ressources
25
Ressources
Cette classe R est générée automatiquement (dans le dossier generated) par ce que vous
mettez dans le dossier res : interfaces, menus, images, chaînes. . . Certaines de ces ressources
sont des fichiers XML, d’autres sont des images PNG.
Par exemple, le fichier res/values/strings.xml :
27
Ressources
Exemple:
Le système Android ira chercher automatiquement le bon texte en fonction des paramètres
linguistiques configurés par l’utilisateur.
Emploi des ressources texte dans un programme
Dans un programme Java, on peut très facilement placer un texte dans une vue de l’interface :
TextView tv = ...
tv.setText(R.string.bonjour); 28
Ressources
R.string.bonjour désigne le texte de <string name="bonjour">... dans le fichier
res/values*/strings.xml. Cela fonctionne car TextView.setText() a deux versions :
void setText(String text) : on peut fournir une chaîne quelconque
void setText(int idText) : on doit fournir un identifiant de ressource chaîne, donc forcément l’un des textes du
fichier res/values/strings.xml
Par contre, si on veut récupérer l’une des chaînes des ressources pour l’utiliser dans le
programme, on doit procéder comme suit:
String message = getResources().getString(R.string.bonjour);
getResources() est une méthode de la classe Activity (héritée de la classe abstraite Context) qui
retourne une représentation de toutes les ressources du dossier res. Chacune de ces ressources,
selon son type, peut être récupérée avec son identifiant.
Emploi des ressources texte dans une interface
Dans un fichier de ressources décrivant une interface, on peut également employer des
29
ressources texte :
Ressources
<RelativeLayout>
<TextView android:text="@string/bonjour" />
<Button android:text="Commencer" />
</RelativeLayout>
Le titre du TextView sera pris dans le fichier de ressource des chaînes, par contre, le titre du
Button sera une chaîne fixe hard coded, non traduisible, donc Android Studio mettra un
avertissement. De manière générale, @string/nom est une référence à la chaîne du fichier
res/values*/strings.xml ayant ce nom.
Images : R.drawable.nom
De la même façon, les images PNG placées dans res/drawable et res/mipmaps-* peuvent être
référencées :
<ImageView
android:src="@drawable/velo"
android:contentDescription="@string/mon_velo" /> 30
Ressources
La notation @drawable/nom référence l’image portant ce nom dans l’un des dossiers. NB: les
dossiers res/mipmaps-* contiennent la même image à des définitions différentes, pour
correspondre à différents téléphones et tablettes.
Tableau de chaînes : R.array.nom
Voici un exemple de fichier res/values/arrays.xml :
<resources>
<string-array name="planetes">
<item>Mercure</item>
<item>Venus</item>
<item>Terre</item>
<item>Mars</item>
</string-array>
</resources>
Dans le programme Java, il est possible de faire :
Resources res = getResources();
String[] planetes = res.getStringArray(R.array.planetes); 31
Mise en page (layouts)
Structure d’une interface Android
Un écran Android de type formulaire est généralement composé de plusieurs vues. Entre
autres de :
TextView, ImageView : titre, image
EditText : texte à saisir
Button, CheckBox : bouton à cliquer, case à cocher
Ces vues sont alignées à l’aide de groupes sous-classes de ViewGroup, éventuellement
imbriqués :
LinearLayout : positionne ses vues en ligne ou en colonne
RelativeLayout, ConstraintLayout : positionnent leurs vues l’une par rapport à l’autre
TableLayout : positionne ses vues sous forme d’un tableau
Il est préférable de stocker l’interface dans un fichier res/layout/main.xml, qui est référencé
par son identifiant R.layout.nom_du_fichier dans le programme Java. La méthode
setContentView fait afficher le layout indiqué.
32
Mise en page (layouts)
<LinearLayout ...>
<TextView android:text="@string/bonjour" ... />
</LinearLayout>
Identifiants et vues
Lorsque l’application veut manipuler l’une de ses vues, elle doit utiliser R.id.symbole,
exemple :
TextView tv = findViewById(R.id.message);
33
Mise en page (layouts)
avec la définition suivante dans res/layout/main.xml :
<LinearLayout ...>
<TextView
android:id="@+id/message"
android:text="@string/bonjour" />
</LinearLayout>
Une activité qui n’est pas déclarée dans le manifeste ne peut pas être lancée.
Démarrage d’une application
L’une des activités est marquée comme étant démarrable de l’extérieur, grâce à un sous-élément
<intent-filter> :
37
Applications et activités
<activity android:name=".MainActivity" ...>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
Un <intent-filter> déclare les conditions de démarrage d’une activité. Celui-ci indique
l’activité principale, celle qu’il faut lancer quand on clique sur son icône.
Démarrage d’une activité et Intents
Les activités sont démarrées à l’aide d’intents. Un Intent contient une demande destinée à une
activité, par exemple, composer un numéro de téléphone ou lancer l’application.
action : spécifie ce que l’Intent demande. Il y en a de très nombreuses :
– VIEW pour afficher quelque chose, EDIT pour modifier une information, SEARCH. . .
données : selon l’action, ça peut être un numéro de téléphone, l’identifiant d’une information. . . 38
Applications et activités
catégorie : information supplémentaire sur l’action, par exemple, ...LAUNCHER pour lancer une application.
Une application a la possibilité de lancer certaines activités d’une autre application, celles qui
ont un intent-filter.
Lancement d’une activité par programme
Soit une application contenant deux activités : Activ1 et Activ2. La première lance la seconde par :
Intent intent = new Intent(this, Activ2.class);
startActivity(intent);
L’instruction startActivity démarre Activ2. Celle-ci se met au premier plan, tandis que
Activ1 se met en sommeil.
Activ1 reviendra au premier plan quand Activ2 se finira ou quand l’utilisateur appuiera
sur back.
Ce bout de code est employé par exemple lorsqu’un bouton, un menu, etc. est cliqué.
Seule contrainte : que ces deux activités soient déclarées dans AndroidManifest.xml.39
Applications et activités
Lancement d’une activité d’une autre application
Soit une seconde application dans le package eni.git.appli2. Une activité peut la lancer ainsi :
intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.setClassName(
"eni.git.appli2",
" eni.git.appli2.MainActivity");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Cela consiste à créer un Intent d’action MAIN et de catégorie LAUNCHER pour la classe
MainActivity de l’autre application.
Autorisations d’une application
Une application doit déclarer les autorisations dont elle a besoin : accès à internet, caméra,
carnet d’adresse, GPS, etc. Cela se fait en rajoutant des éléments dans le manifeste : 40
Applications et activités
<manifest ... >
<uses-permission
android:name="android.permission.INTERNET" />
...
<application .../>
</manifest>
finish() fait terminer l’activité courante. L’utilisateur ne pourra pas faire back dessus, car elle
disparaît de la pile.
42
Applications et activités
Lancement avec attente de résultat
Le lancement d’une activité avec attente de résultat est plus complexe. Il faut définir un code
d’appel
private static final int APPEL_ACTIV2 = 1;
Intent intent = new Intent(this, Activ2.class);
startActivityForResult(intent, APPEL_ACTIV2);
Ce code identifie l’activité lancée, afin de savoir plus tard que c’est d’elle qu’on revient. Par
exemple, on pourrait lancer au choix plusieurs activités : édition, copie, suppression
d’informations. Il faut pouvoir les distinguer au retour.
Consulter cette page
Ensuite, il faut définir une méthode callback qui est appelée lorsqu’on revient dans notre
activité :
43
Applications et activités
@Override
protected void onActivityResult( int requestCode, int resultCode, Intent data)
{
if (resultCode == Activity.RESULT_CANCELED) return;
// selon le code d'appel
switch (requestCode) {
case APPEL_ACTIV2: // on revient de Activ2
...
}
}
setResult(RESULT_OK);
finish(); 44
Applications et activités
À cause du bouton « back » du téléphone, son action revient à faire ceci :
setResult(RESULT_CANCELED);
finish();
Dans ces deux cas, on revient dans l’activité appelante (sauf si elle-même avait fait finish().
Méthode onActivityResult
Quand on revient dans l’activité appelante, Android lui fait exécuter cette méthode :
onActivityResult(int requestCode, int resultCode, Intent data)
requestCode est le code d’appel de startActivityForResult
resultCode vaut soit RESULT_CANCELED soit RESULT_OK
data est fourni par l’activité appelée et qui vient de se terminer.
Ces deux dernières viennent d’un appel à setResult(resultCode, data)
45
Applications et activités
Transport d’informations dans un Intent
Les Intent servent aussi à transporter des informations d’une activité à l’autre : les extras.
Voici comment placer des données dans un Intent :
Intent intent =
new Intent(this, DeleteInfoActivity.class);
intent.putExtra("idInfo", idInfo);
intent.putExtra("hiddencopy", hiddencopy);
startActivity(intent);
putExtra(nom, valeur) rajoute un couple (nom, valeur) dans l’intent. La valeur doit être
sérialisable nombres, chaînes et structures simples.
Extraction d’informations d’un Intent
Ces instructions récupèrent les données d’un Intent :
46
Applications et activités
Intent intent = getIntent();
Integer idInfo = intent.getIntExtra("idInfo", -1);
bool hidden = intent.getBooleanExtra("hiddencopy", false);
getIntent() retourne l’Intent qui a démarré cette activité.
getTypeExtra(nom, valeur par défaut) retourne la valeur de ce nom si elle en fait partie, la valeur par défaut
sinon.
Il est très recommandé de placer les chaînes dans des constantes, dans la classe appelée :
public static final String EXTRA_IDINFO = "idInfo";
public static final String EXTRA_HIDDEN = "hiddencopy";
47
Activités
Une activité se trouve dans l’un de ces états :
active (resumed) : elle est sur le devant, l’utilisateur peut jouer avec,
en pause (paused) : partiellement cachée et inactive, car une autre activité est venue devant,
stoppée (stopped) : totalement invisible et inactive, ses variables sont préservées mais elle ne tourne plus.
Cycle de vie d’une activité
Le diagramme suivant résume les changements d’états d’une activité :
48
49
Activités
Événements de changement d’état
La classe Activity reçoit des événements de la part du système Android, ceci fait appel à des
fonctions appelées callbacks.
Exemples :
onCreate Un Intent arrive dans l’application, il déclenche la création d’une activité, dont l’interface.
onPause Le système prévient l’activité qu’une autre activité est passée devant, il faut enregistrer les
informations au cas où l’utilisateur ne revienne pas.
Squelette d’activité
public class EditActivity extends Activity
{
@Override
public void onCreate(Bundle savedInstanceState) {
// obligatoire
super.onCreate(savedInstanceState);
// met en place les vues de cette activité
setContentView(R.layout.edit_activity);
}
} 50
Activités
@Override signifie que cette méthode remplace celle héritée de la superclasse. Il faut quand même l’appeler
sur super en premier.
Terminaison d’une activité
Exemple de la prise en compte de la terminaison définitive d’une activité, avec la fermeture d’une base de
données :
@Override
public void onDestroy() {
// obligatoire
super.onDestroy();
// fermer la base
db.close();
}
53
Activités
static final String ETAT_SCORE = "ScoreJoueur"; // nom
private int mScoreJoueur = 0; // valeur
@Override
public void onSaveInstanceState(Bundle etat) {
// enregistrer l'état courant
etat.putInt(ETAT_SCORE, mScoreJoueur);
super.onSaveInstanceState(etat);
}
54
Activités
@Override
protected void onRestoreInstanceState(Bundle etat) {
super.onRestoreInstanceState(etat);
// restaurer l'état précédent
mScoreJoueur = etat.getInt(ETAT_SCORE);
}
Ces deux méthodes sont appelées automatiquement (sorte d’écouteurs), sauf si l’utilisateur
tue l’application. Cela permet de reprendre l’activité là où elle en était.
Vues et activités
Obtention des vues
La méthode setContentView charge une mise en page (layout) sur l’écran. Ensuite l’activité
peut avoir besoin d’accéder aux vues, par exemple lire la chaîne saisie dans un texte. Pour
cela, il faut obtenir l’objet Java correspondant. EditText nom = findViewById(R.id.edt_nom); 55
Activités
Cette méthode cherche la vue qui possède cet identifiant dans le layout de l’activité. Si cette
vue n’existe pas (mauvais identifiant, ou pas créée), la fonction retourne null.
Un mauvais identifiant peut être la raison d’un bug. Cela peut arriver quand on se trompe de
layout pour la vue. C’est néanmoins surveillé par Android Studio.
Pour éviter les problèmes de typage et de vues absentes d’un layout, il existe un dispositif
appelé ViewBindings. Ce sont des classes qui sont générées automatiquement à partir de
chaque layout et dont les variables membres sont les différentes vues.
Par exemple, soit un layout appelé activity_main.xml :
<LinearLayout ...>
<TextView android:id="@+id/titre" .../>
<Button android:id="@+id/btnOk" .../>
</LinearLayout>
Cela fait générer une classe appelée ActivityMainBinding.java et contenant à peu près ceci
56
:
Activités
public final class ActivityMainBinding implements ViewBinding
{
private final LinearLayout rootView; // voir getRoot()
public final Button btnOk;
public final TextView titre;
Chaque vue du layout xml possédant un identifiant est reliée à une variable membre publique
dans cette classe, et la vue racine est accessible par getRoot().
Propriétés des vues
La plupart des vues ont des setters et getters Java pour leurs propriétés XML. Consulter leur
documentation pour les propriétés, qui sont extrêmement nombreuses. Par exemple TextView.
En XML : <TextView android:id="@+id/titre" En Java: TextView tvTitre = ui.titre;
android:lines="2" tvTitre.setLines(2);
android:text="@string/debut" /> tvTitre.setText(R.string.debut); 57
Activités
Actions de l’utilisateur
Prenons l’exemple de ce Button. Lorsque l’utilisateur appuie dessus, ça appelle
automatiquement la méthode onValider de l’activité grâce à l’attribut onClick="onValider".
<Button
android:onClick="onValider"
android:id="@+id/btnValider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/valider"/>
Il faut définir la méthode onValider dans l’activité :
public void onValider(View btn) {
...
}
58
Activités
Définition d’un écouteur
Il y a une autre manière de définir une réponse à un clic : un écouteur (listener), comme un
EventHandler dans JavaFX. Un écouteur est une instance de classe implémentant l’interface
View.OnClickListener qui possède la méthode public void onClick(View v).
Cela peut être :
une classe privée anonyme,
une classe privée ou publique dans l’activité,
l’activité elle-même.
Dans tous les cas, on fournit cette instance en paramètre à la méthode setOnClickListener du
bouton :
59
Activités
Écouteur privé
Cela consiste à définir une classe privée dans l’activité ; cette classe implémente l’interface
OnClickListener ; et à en fournir une instance en tant qu’écouteur.
private class EcBtnValider implements View.OnClickListener {
public void onClick(View btn) {
// faire quelque chose
}
};
public void onCreate(...) {
...
Button btn = ui.btnValider;
btn.setOnClickListener(new EcBtnValider());
}
60
Activités
L’activité elle-même en tant qu’écouteur
Il suffit de mentionner this comme écouteur et d’indiquer qu’elle implémente l’interface OnClickListener. Ici, par
contre, tous les boutons appelleront la même méthode.
public class EditActivity extends Activity implements View.OnClickListener {
public void onCreate(...) {
...
Button btn = ui.btnValider;
btn.setOnClickListener(this);
}
public void onClick(View btn) {
// faire quelque chose
}
63
Fragments et Activités
64
Fragments et Activités
Structure d’un fragment
Un fragment est une activité très simplifiée qui contient au moins un constructeur vide et onCreateView
surchargée :
Intégrer un fragment dans une activité
De lui-même, un fragment n’est pas capable de s’afficher. Il ne peut apparaître que dans le cadre d’une activité,
comme une sorte de vue interne. On peut le faire de deux manières :
statiquement : les fragments à afficher sont prévus dans le layout de l’activité. C’est le plus simple à faire et
à comprendre.
dynamiquement : les fragments sont ajoutés, enlevés ou remplacés en cours de route selon les besoins
Fragments statiques dans une activité
Dans ce cas, c’est le layout de l’activité qui inclut les fragments. Ils ne peuvent pas être modifiés ultérieurement.
Chaque fragment doit avoir un identifiant et un nom de classe complet avec tout le package. Ne pas oublier les
attributs des tailles et éventuellement poids.
Communication entre fragment et activité
Elle se fait grâce à un callback via une interface 65
Fragments et Activités
Exercice: réaliser l’application suivante. Elle a deux activités, la première contient un fragment
contenant un bouton et la deuxième (lancée à partir de la première) contient un fragment
contenant une zone d’affichage de texte
66
Fragments et Activités
Fichier MainActivity.java :
package com.example.myapplication2;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity implements
MainFragment.OnButtonClickedListener{
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main)
}
@Override
public void onButtonClicked(View view) {
Log.e(getClass().getSimpleName(),"Button clicked !");
startActivity(new Intent(this, DetailActivity.class));
}
}
67
Fragments et Activités
Fichier MainFragment.java :
// 1 - Declare our interface that will be implemented by any container activity
package com.example.myapplication2; public interface OnButtonClickedListener {
public void onButtonClicked(View view);
import android.content.Context; }
import android.os.Bundle;
// --------------
import androidx.fragment.app.Fragment;
public MainFragment() {
import android.view.LayoutInflater; // Required empty public constructor
import android.view.View; }
import android.view.ViewGroup;
/**
/** * Use this factory method to create a new instance of
* A simple {@link Fragment} subclass. * this fragment using the provided parameters.
* Use the {@link MainFragment#newInstance} factory method to *
* create an instance of this fragment. * @param param1 Parameter 1.
*/ * @param param2 Parameter 2.
public class MainFragment extends Fragment implements View.OnClickListener{ * @return A new instance of fragment MainFragment.
*/
// TODO: Rename parameter arguments, choose names that match // TODO: Rename and change types and number of parameters
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER public static MainFragment newInstance(String param1, String param2) {
private static final String ARG_PARAM1 = "param1"; MainFragment fragment = new MainFragment();
private static final String ARG_PARAM2 = "param2"; Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
// TODO: Rename and change types of parameters args.putString(ARG_PARAM2, param2);
private String mParam1; fragment.setArguments(args);
private String mParam2; return fragment;
//2 - Declare callback }
private OnButtonClickedListener mCallback;
68
Fragments et Activités
Fichier MainFragment.java :
// --------------
@Override
// ACTIONS
public void onCreate(Bundle savedInstanceState) {
// --------------
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1); @Override
mParam2 = getArguments().getString(ARG_PARAM2); public void onClick(View v) {
} // 5 - Spread the click to the parent activity
} mCallback.onButtonClicked(v);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, // --------------
Bundle savedInstanceState) { // FRAGMENT SUPPORT
//Inflate the layout of MainFragment
// --------------
View result=inflater.inflate(R.layout.fragment_main, container, false);
package com.example.myapplication2;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
}
}
70
Fragments et Activités
/**
Fichier DetailFragment.java : * Use this factory method to create a new instance of
* this fragment using the provided parameters.
package com.example.myapplication2; *
* @param param1 Parameter 1.
import android.os.Bundle; * @param param2 Parameter 2.
* @return A new instance of fragment DetailFragment.
*/
import androidx.fragment.app.Fragment;
// TODO: Rename and change types and number of parameters
public static DetailFragment newInstance(String param1, String param2) {
import android.view.LayoutInflater; DetailFragment fragment = new DetailFragment();
import android.view.View; Bundle args = new Bundle();
import android.view.ViewGroup; args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
/** fragment.setArguments(args);
* A simple {@link Fragment} subclass. return fragment;
* Use the {@link DetailFragment#newInstance} factory method to }
* create an instance of this fragment.
@Override
*/
public void onCreate(Bundle savedInstanceState) {
public class DetailFragment extends Fragment { super.onCreate(savedInstanceState);
if (getArguments() != null) {
// TODO: Rename parameter arguments, choose names that match mParam1 = getArguments().getString(ARG_PARAM1);
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER mParam2 = getArguments().getString(ARG_PARAM2);
private static final String ARG_PARAM1 = "param1"; }
private static final String ARG_PARAM2 = "param2"; }
<fragment
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.example.myapplication2.MainFragment"/>
</androidx.constraintlayout.widget.ConstraintLayout>
72
Fragments et Activités
Fichier fragment_main.xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainFragment">
<Button
android:id="@+id/fragment_main_button"
android:layout_width="229dp"
android:layout_height="78dp"
android:layout_marginStart="32dp"
android:layout_marginTop="32dp"
android:layout_marginEnd="32dp"
android:background="#00000000"
android:text="Montre moi des details !"
android:textColor="#FFF"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> 73
Fragments et Activités
Fichier activity_detail.xml :
android:name="com.example.myapplication2.DetailFragment"/>
</androidx.constraintlayout.widget.ConstraintLayout>
74
Fragments et Activités
Fichier detail_fragment.xml :
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DetailFragment">
75
</androidx.constraintlayout.widget.ConstraintLayout>
Fragments et Activités
Setup your environment
Fragments require a dependency on the AndroidX Fragment library. You need to add the Google Maven
repository to your project’s build.gradle file in order to include this dependency.
buildscript {
...
dependencies {
repositories {
val fragment_version = "1.4.0"
google()
...
// Java language implementation
}
implementation("androidx.fragment:fragment:
}
$fragment_version")
allprojects {
// Kotlin
repositories {
implementation("androidx.fragment:fragment-ktx:
google()
$fragment_version")
...
}
}
}
To include the AndroidX Fragment library to your project, add the following dependencies in your
76
app's build.gradle file: