Vous êtes sur la page 1sur 53

Dev.

Android
1.1
1.
Programmation
concurrente
Réalisation des tâches parallèles
“ Une situation de compétition est le
comportement d'un système électronique,
logiciel ou autre, où la sortie dépend du
séquencement d'autres événements
incontrôlables. Elle devient un bug lorsque
les événements ne se produisent pas dans
l'ordre que le programmeur a prévu. Le
terme provient de l'idée de deux signaux qui
font la course les uns contre les autres pour
influencer la sortie en premier.

3
Les processus
● Processus "lourd" appelé par la
suite "service"
● Processus "léger" appelé par la
suite thread

4
Les processus
Processus Thread Service
Par défaut, une Il est responsable de Pour réaliser un service,
application android l'interface graphique et on hérite de la classe
s'exécute dans un des Service et on implémente
processus unique, le messages/notifications/é les méthodes de
processus dit "principal". vénements entre création/démarrage/arrêt
L'interface graphique composants graphiques. du service.
s'exécute elle aussi au La nouvelle méthode qu'il
travers de ce processus faut implémenter ici est
principal. onBind qui permet aux
IPC de faire des appels à
des méthodes distantes. 5
Les processus
Android peut devoir arrêter un processus à cause d'autres processus qui requièrent plus
d'importance. Par exemple, un service peut être détruit car une application gourmande en
ressources (navigateur web) occupe de plus en plus de mémoire. Plus classiquement,
le processus affecté à une activité qui n'est plus visible a de grandes chances d'être
détruit.

6
Les processus
Ainsi, une hiérarchie permet de classer le niveau d'importance des processus:
1. Processus en avant plan (activité en interaction utilisateur, service attaché à cette
activité, BroadCastReceiver exécutant onReceive())
2. Processus visible: il n'interagit pas avec l'utilisateur mais peut influer sur ce que
l'on voit à l'écran (activité ayant affiché une boîte de dialogue (onPause() a été appelé),
service lié à ces activité "visibles").
3. Processus de service
4. Processus tâche de fond (activité non visible (onStop() a été appelé))
5. Processus vide (ne comporte plus de composants actifs, gardé pour des raisons de
cache)

7
Les processus
Ainsi, il faut préférer l'utilisation d'un service à la création d'un thread pour accomplir une
tâche longue, par exemple l'upload d'une image. On garantit ainsi d'avoir le niveau 3 pour
cette opération, même si l'utilisateur quitte l'application ayant initié l'upload.

8
Les threads
si l'application doit effectuer des traitements longs, elle doit éviter de les faire dans ce
thread. Cependant, il est interdit d'effectuer des opérations sur l'interface graphique en
dehors du thread principal (aussi appelé UI thread), ce qui se résume dans la
documentation sur les threads par deux règles:
• Do not block the UI thread
• Do not access the Android UI toolkit from outside the UI thread
L'exemple à ne pas faire est donné dans la documentation et recopié ci-dessous. Le
comportement est imprévisible car le toolkit
graphique n'est pas thread-safe.

9
Les threads

Une exception peut parfois (pas toujours) être levée quand cela est détecté:
CalledFromWrongThreadException.

10
Les threads

La documentation donne les quelques méthodes utiles pour ces cas délicats:
• Activity.runOnUiThread(Runnable)
• View.post(Runnable)
• View.postDelayed(Runnable, long)
11
Les services

12
Les services

13
Les services (autostart)

14
2.
Connectivité
Communiquer avec les services
Téléphonie
Les fonctions de téléphonie sont relativement simples à utiliser. Elles permettent de
récupérer l'état de la fonction de téléphonie (appel en cours, appel entrant, ...), d'être
notifié lors d'un changement d'état, de passer des appels et de gérer l'envoi et réception
de SMS. L'état de la téléphonie est géré par la classe TelephonyManager qui permet de
récupérer le nom de l'opérateur, du téléphone, et l'état du téléphone. Pour lire ces
informations, il est nécessaire de disposer de la permission
android.permission.CALL_PHONE.

16
Réseau
Le réseau (cf Code-Network) peut être disponible ou indisponible, suivant que le
téléphone utilise une connexion Wifi, 3G, bluetooth, etc.
Si la permission android.permission;ACCESS_NETWORK_STATE est déclarée, la classe
NetworkInfo (depuis ConnectivityManager) permet de lire l'état de la connexion réseau
parmi les constantes de la classe State: CONNECTING, CONNECTED, DISCONNECTING,
DISCONNECTED, SUSPENDED, UNKNOWN.

17
Bluetooth
Le bluetooth se gère au travers de principalement 3 classes:
• BluetoothAdapter: similaire au WifiManager, cette classe permet de gérer les
autres appareils bluetooth et d'initier les communications avec ceux-ci.
• BluetoothDevice: objet représentant l'appareil distant.
• BluetoothSocket et BluetoothServerSocket: gère une connexion établie.
Pour pouvoir utiliser les fonctionnalités bluetooth, il faut activer les permissions
android.permission.BLUETOOTH et android.permission.BLUETOOTH_ADMIN pour
pouvoir chercher des appareils ou changer la configuration bluetooth du téléphone.

18
Localisation
Comme pour le réseau, Android permet d'utiliser plusieurs moyens de localisation. Cela
permet de rendre transparent l'utilisation du GPS, des antennes GSM ou des accès au
Wifi. La classe LocationManger permet de gérer ces différents fournisseurs de position.
• LocationManager.GPS_PROVIDER: fournisseur GPS
• LocationManager.NETWORK_PROVIDER: fournisseur basé réseau
La liste de tous les fournisseurs s'obtient au travers de la méthode getAllProviders() ou
getAllProviders(true) pour les fournisseurs activés

19
2.
Les fournisseurs de
contenu: ContentProvider
Communication avec les autres applications
“ Les fournisseurs de contenu peuvent aider une
application à gérer l'accès aux données stockées par
elle-même, stockées par d'autres applications, et fournir
un moyen de partager des données avec d'autres
applications. Ils encapsulent les données et fournissent
des mécanismes pour définir la sécurité des données.
Les fournisseurs de contenu constituent l'interface
standard qui connecte les données d'un processus à un
code exécuté dans un autre processus.

22
Plus important encore, vous pouvez
configurer un fournisseur de
contenu pour permettre à d'autres
applications d'accéder et de
modifier en toute sécurité les
données de votre application.
Un certain nombre d'autres classes s'appuient sur la classe ContentProvider:
● AbstractThreadedSyncAdapter
● CursorAdapter
● CursorLoader

La structure Android inclut des fournisseurs de contenu qui gèrent des données telles
que l'audio, la vidéo, les images et les informations de contact personnelles. Avec
certaines restrictions, ces fournisseurs sont accessibles à toute application Android.

Un fournisseur de contenu peut être utilisé pour gérer l'accès à diverses sources de
stockage de données, y compris des données structurées, telles qu'une base de
données relationnelle SQLite, ou des données non structurées telles que des fichiers
images.

24
Avantages
Les fournisseurs de contenu offrent un contrôle granulaire sur les autorisations d'accès
aux données.
Vous pouvez choisir de limiter l'accès à un fournisseur de contenu à partir de votre
application uniquement, d'accorder une autorisation générale pour accéder aux données
d'autres applications ou de configurer différentes autorisations pour la lecture et l'écriture
de données.

25
Vous pouvez utiliser un fournisseur de contenu pour extraire les détails permettant
d'accéder à différentes sources de données dans votre application.

Par exemple, votre application peut stocker des enregistrements structurés dans une
base de données SQLite, ainsi que des fichiers vidéo et audio.
Vous pouvez utiliser un fournisseur de contenu pour accéder à toutes ces données, si
vous implémentez ce modèle de développement dans votre application.

Notez également que les objets CursorLoader dépendent des fournisseurs de contenu
pour exécuter des requêtes asynchrones, puis renvoyer les résultats à la couche
d'interface utilisateur de votre application.

H 26
3.
Broadcast
Receivers
Les broadcast intents

Les broadcast intents sont définies de la
même façon que les intents implicites avec
quelques caractéristiques qui font la
différenciation
● Livrée avec sendBroadcast() au lieu de
startActivity qui démarre une acitvity
● Une opération en arrière plan,
l’utilisateur ne peut pas la voir
s’exécuter, par contre une intent d’une
acitivty est visible lors de la transition
28
Un composant qui répond aux annonces de diffusion à l'échelle du système
De nombreuses émissions proviennent du système.
● une émission annonçant que l'écran s'est éteint,
● la batterie est faible
● une image a été capturée.

Les applications peuvent également initier des diffusions,


➢ pour informer les autres applications que certaines données ont été
téléchargées sur le périphérique et sont disponibles pour utilisation.
➢ Notifier une application qu’un appel téléphonique est reçu

29
Bien que les BroadcastReceivers n'affichent pas d'interface utilisateur, ils
peuvent créer une notification de barre d'état pour avertir l'utilisateur lorsqu'un
événement de broadcast se produit.

Un broadcastReceiver est simplement une "passerelle" vers d'autres composants


et est destiné à effectuer un travail très minime.
➢ peut lancer un service pour effectuer certains travaux en fonction de
l'événement.

30
Mise en place
BroadcastReceiver:
● Subclass où on reçoit les intents
qui sont livrées
● Inclut toute logique à traiter dans
le broadcast

31
public class CustomBroadCastReceiver extends BroadcastReceiver {
public static final String ACTION_SHOW_TOAST = "com.package.SN";
@Override
public void onReceive(Context context, Intent intent){
if (intent.getAction().equals(ACTION_SHOW_TOAST)) {
CharSequence text = "Broadcast Received!";
int duration = Toast.LENGTH_SHORT;

Toast toast = Toast.makeText(context, text, duration);


toast.show();
}
}
}

32
Les applications peuvent recevoir des émissions de deux manières:
par le biais de récepteurs déclarés par manifest et de récepteurs enregistrés par contexte

Enregistrement dans le manifest


<receiver
android:name="com.example.myproject.AlarmReceiver"
android:exported="false">
<intent-filter>
<action android:name="com.package.SN"/>
</intent-filter>
</receiver>

Enregistrement dynamique: liaison de l’opération au cycle de vie de l’acitvity


IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(CustomBroadCastReceiver.ACTION_SHOW_TOAST);
mReceiver = new AlarmReceiver();
registerReceiver(mReceiver, intentFilter);

33
Inscription et désinsciption

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(receiver, new
IntentFilter(CustomBroadCastReceiver.ACTION_SHOW_TOAST));
}
@Override
protected void onDestroy() {
unregisterReceiver(receiver);
super.onDestroy();
}

34
Envoi d’un broadcast

Intent i = new Intent(CustomBroadCastReceiver.ACTION_SHOW_TOAST);


sendBroadcast(i);

Remarque: lors de la spécification de l'action pour l’intent, on utilise le nom de package unique
(com.example.myproject) pour s’assurer que l’intent n'entre pas en conflit avec une intent diffusée à
partir d'une autre application ou du système.

35
Changements dans les émissions du système

À mesure que la plate-forme Android évolue, elle modifie périodiquement le


comportement des diffusions système.
On doit penser aux modifications suivantes si l’application cible Android 7.0 (API
de niveau 24) ou supérieur, ou si elle est installée sur des appareils exécutant
Android 7.0 ou une version ultérieure.

36
Android 9
À partir de Android 9 (API niveau 28), la diffusion
NETWORK_STATE_CHANGED_ACTION ne reçoit aucune information sur
l'emplacement de l'utilisateur ni sur ses données personnellement identifiables.

sur un appareil fonctionnant sous Android 9 ou supérieur, les diffusions système


du Wi-Fi ne contiennent pas
● de SSID,
● de BSSID,
● d'informations de connexion
● de résultats d'analyse.

Pour obtenir cette information, on appelle getConnectionInfo () à la place.

37
Android 8.0
Depuis Android 8.0 (API de niveau 26), le système impose des restrictions
supplémentaires aux récepteurs déclarés.

Si une application cible Android 8.0 ou une version ultérieure,


➢ ne pas utiliser le manifest pour déclarer un destinataire de la plupart des
diffusions implicites (diffusions qui ne ciblent pas votre application
spécifiquement).

➢ utiliser un récepteur enregistré dans le contexte lorsque l'utilisateur utilise


activement votre application.

38
Android 7.0

Android 7.0 (API de niveau 24) et les versions ultérieures n'envoient pas les
diffusions système suivantes:

● ACTION_NEW_PICTURE
● ACTION_NEW_VIDEO

De plus, les applications ciblant Android 7.0 et versions ultérieures doivent


● enregistrer la diffusion CONNECTIVITY_ACTION à l'aide de
registerReceiver (BroadcastReceiver, IntentFilter).
● Déclarer un destinataire dans le manifeste ne fonctionne pas.

39
4.
Architecture
components
Les librairie de l’architecture
● Collection de bibliothèques
● Concevoir des applications robustes, testables et maintenables
● Des classes pour gérer le cycle de vie des composant d'interface utilisateur et gérer la
persistance des données

● L'utilisation de ces librairies et la mise en œuvre de l'architecture recommandée


comportent de nombreuses étapes.

● La chose la plus importante est de créer un modèle mental de ce qui se passe et de


comprendre comment les éléments s'emboîtent et comment les données circulent.

41
Liste des librairies
● Data binding: aide à lier de manière déclarative des éléments d'interface utilisateur
dans notre mise en page aux sources de données de notre application.

● Lyfecycles: gère l'activité et fragmente les cycles de vie de l’application, survit aux
changements de configuration, évite les fuites de mémoire et charge facilement les
données dans notre interface utilisateur.
Liste des librairies
● LiveData: informe les vues de toute modification de la base de données. Utilisée pour
créer des objets de données qui notifient les vues lorsque la base de données
sous-jacente change.

● Navigation: gère tout le nécessaire pour la navigation dans l'application Android.


Liste des librairies
● Paging: permet de charger progressivement des informations à la demande à partir de notre
source de données.

● Room: une bibliothèque de mappage d'objets SQLite. Utilisée pour éviter le code standard et
convertir facilement les données de la table SQLite en objets Java. Room fournit des
vérifications de temps de compilation des instructions SQLite et peut renvoyer des
observables RxJava, Flowable et LiveData.
Liste des librairies

● ViewModel: gère les données liées à l'interface utilisateur d'une manière soucieuse du cycle
de vie. Il stocke les données liées à l'interface utilisateur qui ne sont pas détruites lors des
rotations d'applications.

● WorkManager: gère tous les travaux d'arrière-plan dans Android avec les circonstances que
nous choisissons.
5.
httpurlconnection
● La bibliothèque HTTP est incluse dans l'API Android depuis l'API 1

● La bibliothèque n'est pas préparée pour les appels asynchrones natifs, ce qui nous oblige à
utiliser des workers, tels que AsyncTasks, pour effectuer des appels réseau HTTP en dehors
du thread d'interface utilisateur principal.
Intégration
● La logique principale du worker se trouve à l'intérieur de la méthode doInBackground. Tout
d'abord, on définit l'URL souhaitée, puis en établissant une connexion HTTP, via la méthode
openConnection. Après avoir vérifié si la connexion a réussi, on lit les données de la
connexion à partir d'un BufferedReader, dans ce cas, en les lisant ligne par ligne.
→ https://gist.github.com/dferreira-cvl/50697a479ebdb331b2e8a7ead2c8f4b5#file-httpurlconnection-get-java
Envoyer un POST
1. Créer l'URL de la publication à effectuer
2. Établir la connexion HTTP
3. Définir les options HttpURLConnection pour effectuer le POST
4. Écrire les données JSON dans la connexion.
5. Vérifier si le POST a bien été reçu par le serveur et vérifier la réponse du serveur
→ https://gist.github.com/dferreira-cvl/283056a95e65f85a02d3a61700fb9a80#file-httpurlconnection-post-java
6.
Les notifications
Création d’une simple notification
● Spécification du contenu
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_launcher) // notification icon
.setContentTitle("Simple notification") // title
.setContentText("Hello word") // body message
.setAutoCancel(true); // clear notification when clicked

● Intent à lancer suite au click

Intent intent = new Intent(this, MainActivity.class);


PendingIntent pi = PendingIntent.getActivity(this, 0, intent, Intent.FLAG_ACTIVITY_NEW_TASK);
mBuilder.setContentIntent(pi);
● Afficher la notification
NotificationManager mNotificationManager =
(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
Notification personnalisée
● Afficher un long texte

String message = "This is a custom notification with a very long text";

Bitmap largeIcon = BitmapFactory.decodeResource(getResources(),


android.R.drawable.ic_dialog_alert);

NotificationCompat.Builder builder = new NotificationCompat.Builder(context);


builder.setContentTitle("Title")
.setContentText(message)
.setSmallIcon(android.R.drawable.ic_dialog_alert)
.setLargeIcon(largeIcon)
.setAutoCancel(true)
.setWhen(System.currentTimeMillis())
.setStyle(new NotificationCompat.BigTextStyle().bigText(message));

Notification notification = builder.build();


NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(101, notification);
Notification personnalisée
● Ajouter un action button
Intent intent = new Intent("action.name");
PendingIntent pIntent = PendingIntent.getBroadcast(context, 1, intent, 0);
builder.addAction(R.drawable.action_button_icon, "Action button name",pIntent);

● Spécification de la priorité
NotificationCompat.Builder mBuilder = (NotificationCompat.Builder) new
NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.some_small_icon)
.setContentTitle("Title")
.setContentText("This is a test notification with MAX priority")
.setPriority(Notification.PRIORITY_MAX);

➢ PRIORITY_MAX
➢ PRIORITY_HIGH
➢ PRIORITY_DEFAULT
➢ PRIORITY_DEFAULT
➢ PRIORITY_LOW
➢ PRIORITY_MIN

Vous aimerez peut-être aussi