SlideShare uma empresa Scribd logo
1 de 100
Baixar para ler offline
session sept 2014 Yann Caron (c) 2014 1
IN01
Programmation Android
07 – Techniques avancées
Yann Caron
session sept 2014 Yann Caron (c) 2014 2
Sommaire - Séance 07
 Programmation avancée
➔
Capteurs
➔
Optimisations
➔
Tests unitaires
➔
Concurrence
 IHM avancées
➔
Vues personnalisées
➔
Fragments
 Autres
➔
Stratégies et alternatives
➔
Jeux vidéo mobiles
session sept 2014 Yann Caron (c) 2014 3
IN01 – Séance 07
Programmation avancée
Capteurs
session sept 2014 Yann Caron (c) 2014 4
Généralités

La miniaturisation et l'industrialisation rendent
aujourd'hui accessibles des capteurs précis au
grand public

La majorité des appareils Android embarquent
au moins un accéléromètre, un gyroscope et
un magnétomètre

Les trois tiennent sur ce circuit :
session sept 2014 Yann Caron (c) 2014 5
Différents capteurs Android
TYPE_ACCELE
ROMETER
3 m/s2 Mesure de l'accélération
(gravité incluse)
[0] axe x [1] axe y [2]
axe z
TYPE_GYROS
COPE
3 Rad / s Mesure la rotation en termes
de vitesse autour de chaque
axe
[0] vitesse x
[1] vitesse y
[2] vitesse z
TYPE_LIGHT 1 Lux Mesure de la luminosité [0]valeur
TYPE_MAGNE
TIC_FIELD
3 µTesla Mesure du champ magnétique [0] axe x [1] axe y [2]
axe z
TYPE_ORIENT
ATION
3 degrés Mesure l'angle entre le nord
magnétique
[0] Azimut y / nord
[1] Rotation x (-
180,180)
[2] Rotation y (-90,90)
TYPE_PRESSU
RE
1 KPas Mesure la pression [0]valeur
TYPE_PROXIM
ITY
1 mètre Mesure la distance entre
l'appareil et un objet cible
[0]valeur
TYPE_TEMPER
ATURE
1 Celsius Mesure la température [0]valeur
session sept 2014 Yann Caron (c) 2014 6
Présence du capteur

On peut interdire (ou pas) l'utilisation de l'application
aux appareils qui ne possèdent pas un certain
capteur

Utile si votre application ne peut pas fonctionner
sans de façon correcte

Dans le manifest (toujours !!) :
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="true" />
session sept 2014 Yann Caron (c) 2014 7
Sensor Manager

Pour accéder aux senseurs, on appelle une
méthode de l'Activity qui renvoie un objet de
type SensorManager

On peut récupérer la liste des capteurs
disponibles sur l'appareil
SensorManager sensorManager =
(SensorManager)getSystemService(Context.SENSOR_SERVICE);
ArrayList<Sensor> liste = (ArrayList<Sensor>)
sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
session sept 2014 Yann Caron (c) 2014 8
Obtenir une instance de capteur

On peut maintenant obtenir une instance du
capteur souhaité

Attention !! Si le capteur n'est pas disponible,
l'objet renvoie la valeur null. Si le capteur n'est
pas requis, il faut tester et gérer s'il est absent.
Sensor accelerometre =
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
session sept 2014 Yann Caron (c) 2014 9
Évènement

Les capteurs fonctionnent aussi sur un modèle
évènementiel
final SensorEventListener mSensorEventListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Que faire en cas de changement de précision ?
}
public void onSensorChanged(SensorEvent sensorEvent) {
// Que faire en cas d'évènements sur le capteur ?
}
};
Si la précision
a changé
Si les valeurs
ont changé
session sept 2014 Yann Caron (c) 2014 10
Évènement

Attention, il est préférable d'enregistrer
l'évènement lorsque l'application est active et
de le désenregistrer lorsque celle-ci est inactive

Sinon, il continue de s'exécuter
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorEventListener, mAccelerometer,
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(mSensorEventListener, mAccelerometer);
}
session sept 2014 Yann Caron (c) 2014 11
Évènement – Valeurs

L'évènement du capteur renvoie un tableau de
valeurs float

Leur nombre et leur signification varient selon
les capteurs (voir tableau précédent)
public void onSensorChanged(SensorEvent sensorEvent) {
float[] values = sensorEvent.values;
Log.d("Sensors", "Acceleration sur l'axe x : " + values[0]);
Log.d("Sensors", "Acceleration sur l'axe y : " + values[1]);
Log.d("Sensors", "Acceleration sur l'axe z : " + values[2]);
}
session sept 2014 Yann Caron (c) 2014 12
Rotation

Doit être calculée avec les valeurs de l'accéléromètre et du
magnétomètre combinées à l'aide de formules complexes

Deux méthodes existent pour faciliter ce calcul :
getRotationMatrix() et getOrientation()
float[] values = new float[3];
float[] R = new float[9];
SensorManager.getRotationMatrix(R, null,
accelerometreValues, magnetometreValues);
SensorManager.getOrientation(R, values);
Log.d("Sensors", "Rotation sur l'axe z : " + values[0]);
Log.d("Sensors", "Rotation sur l'axe x : " + values[1]);
Log.d("Sensors", "Rotation sur l'axe y : " + values[2]);
session sept 2014 Yann Caron (c) 2014 13
Quelques applications
session sept 2014 Yann Caron (c) 2014 14
IN01 – Séance 07
Programmation avancée
Optimisation
session sept 2014 Yann Caron (c) 2014 15
Optimisation sous Android

Pourquoi ??
➔
Pour de meilleures performances !!

Oui, mais pour qui ??
➔
Les applications de bas niveau (un compilateur de
langage comme Algoid par exemple ;-))
➔
Des applications gourmandes en ressources (les
jeux vidéo, les applications graphiques)
session sept 2014 Yann Caron (c) 2014 16
Règles – Les objets

Éviter de créer des objets non nécessaires

En règle générale, éviter de créer trop d'objets !
➔
Parce que la création d'objets c'est gourmand
➔
Et la destruction encore pire : la dalvikVM bloque tout
processus lors du GC (GC dit Stop the World)
➔
Préférer les StringBuffer aux concaténations de strings à
outrance
➔
Un tableau d'int est meilleur qu'un tableau d'integer
(utilisation des types primitifs)
session sept 2014 Yann Caron (c) 2014 17
Règles – Les listes

Un tableau est meilleur qu'une ArrayList, même
règle que précédemment sur les types primitifs

Une ArrayList est moins coûteuse à lire qu'une
LinkedList (création d'objets entry qui seront à
gérer par le GC)
session sept 2014 Yann Caron (c) 2014 18
Règles – Les boucles

Idéal :

Catastrophique :
int size = myArray.length);
for (int i = 0; i < size; i ++) {
}
La taille est évaluée à chaque itération
Map<Integer, String> myMap = new HashMap();
for (Entry<Integer, String> item : myMap.entrySet()) {
}
Un objet Entry<Key, Value> créé à chaque itération
session sept 2014 Yann Caron (c) 2014 19
Règles – Méthodes et variables

Préférer les méthodes statiques aux méthodes de classe,
si aucun attribut de la classe n'est nécessaire

Utiliser static final pour les constantes

Éviter les inner class, surtout si elles ne sont pas statiques

Éviter les getter et setter (antipattern)

Les float 2x plus lents que les int

Les double sont 2x plus gourmands en mémoire que les
float
session sept 2014 Yann Caron (c) 2014 20
Règles - Conclusion

Attention toutefois à ne pas abuser des règles
d'optimisation

Évaluer si l'application nécessite une optimisation

Toujours mettre en relation le gain de
performances (CPU/Mem) et la lisibilité du code

Car attention ! Ces règles dégradent la qualité du
code et donc la lisibilité et la réutilisabilité
session sept 2014 Yann Caron (c) 2014 21
Optimisation - Outils

Toujours mesurer les gains par des micro-benchmarks :

Et le JIT (Just In Time Compiler) ?

Profilers netbeans ou Eclipse sont nos amis

Résultat : Algoid Language aussi rapide que Python est
plus rapide que JavaScript sur Android :-) Pas mal pour
un langage seulement interprété force brute
long time = System.currentTimeMillis();
for (int i=0; i<1000000; i++) {
// le code à tester
}
long timeSpent = System.currentTimeMillis() - time;
System.out.println("Time spent " + timeSpent);
session sept 2014 Yann Caron (c) 2014 22
IN01 – Séance 07
Programmation avancée
Tests unitaires
session sept 2014 Yann Caron (c) 2014 23
Vue d'ensemble

Créer des tests unitaires pour tester des apps
Android, c'est possible

Ça fonctionne avec JUnit

On peut tester l'interface utilisateur
(manipulation)
session sept 2014 Yann Caron (c) 2014 24
Création du projet de test

Depuis
Eclipse
session sept 2014 Yann Caron (c) 2014 25
Création du projet de test

On choisit le
projet à tester
session sept 2014 Yann Caron (c) 2014 26
Test Fixture

Pour créer un test case, il suffit de créer une
nouvelle classe de test

Celle-ci devra hériter de la classe
ActivityInstrumentationTestCase2

Et fournir la classe à tester dans son constructeur
public class ActivityTest
extends ActivityInstrumentationTestCase2<MainActivity>{
public ActivityTest() {
super(MainActivity.class);
}
}
La Classe à tester
session sept 2014 Yann Caron (c) 2014 27
SetUp

Lors du setUp, on récupère les instances de
l'activity et des composants à tester
private MainActivity activity = null;
private TextView myTextView = null;
private Button myButton = null;
@Override
protected void setUp() throws Exception {
super.setUp();
activity = getActivity();
myTextView = (TextView) activity.findViewById(
fr.cnam.helloworld.R.id.myTextView);
myButton = (Button)activity.findViewById(
fr.cnam.helloworld.R.id.myButton);
}
R (ressources)
du projet à tester
session sept 2014 Yann Caron (c) 2014 28
Préconditions

Une bonne pratique consiste à tester que le
setUp s'est bien déroulé
@SmallTest
public void testPreconditions() {
assertNotNull("activity is null", activity);
assertNotNull("myTextView is null", myTextView);
assertNotNull("myButton is null", myButton);
}
session sept 2014 Yann Caron (c) 2014 29
Layout test

Tester le layout des composants
@MediumTest
public void testMyTextView_layout() {
final View decorView = activity.getWindow().getDecorView();
ViewAsserts.assertOnScreen(decorView, myTextView);
final ViewGroup.LayoutParams layoutParams =
myTextView.getLayoutParams();
assertNotNull(layoutParams);
assertEquals(layoutParams.width,
WindowManager.LayoutParams.WRAP_CONTENT);
assertEquals(layoutParams.height,
WindowManager.LayoutParams.WRAP_CONTENT);
}
Test que le composant
est présent
session sept 2014 Yann Caron (c) 2014 30
@MediumTest
public void testMyButton_click() {
String initialText = activity.getString(
fr.cnam.helloworld.R.string.hello_world);
String expectedText = activity.getString(
fr.cnam.helloworld.R.string.after_click);
assertEquals(initialText, myTextView.getText());
TouchUtils.clickView(this, myButton);
assertEquals(expectedText, myTextView.getText());
}
Tester les comportements souhaités

Utilisation de TouchUtils pour simuler les
actions utilisateur
Clic sur le bouton
session sept 2014 Yann Caron (c) 2014 31
Test Annotations

@SmallTest :
➔
Un test court, moins de 100 ms

@MediumTest :
➔
Un test de durée moyenne, supérieure à 100 ms

@LargeTest :
➔
Idem que le mediumTest, avec un accès plus
important aux ressources
session sept 2014 Yann Caron (c) 2014 32
Résultats

Et voilà le travail !!

Les sources complètes
sont dans le projet du
cours

Bons tests !!
session sept 2014 Yann Caron (c) 2014 33
IN01 – Séance 07
Programmation avancée
Concurrence
session sept 2014 Yann Caron (c) 2014 34
Généralités

Pour gérer des traitements et pour ne pas bloquer
l'interface utilisateur, on utilise des Threads

Problème !! Il nous est interdit de modifier l'IHM
depuis un autre Thread que le Thread principal

Deux outils existent sur Android : Handler et
AsyncTask

cf. SwingWorker de Swing
session sept 2014 Yann Caron (c) 2014 35
Handler - Pattern

Son but : synchroniser de petites tâches et les ordonner (comme un
ordonnanceur)

Un handler particulier attaché à l'IHM

C'est une queue de tâches

Le consommateur se met en attente sur la queue

Lorsqu'une tâche est ajoutée par un des multiples producteurs
(threads), la queue est notifiée, débloquant ainsi le consommateur

Lorsque le consommateur a tout consommé, il se remet en attente

Ça ressemble au patron Reader – Writer lock, mais, inversé (multiple
writer et mono reader)

Utilisation massive dans Algoid (le script emploie son propre thread)
session sept 2014 Yann Caron (c) 2014 36
Handler - Utilisation

Il faut créer un handler (ou en récupérer un
d'une vue)

Puis lui envoyer des tâches
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
}
});
session sept 2014 Yann Caron (c) 2014 37
Handler - Les méthodes

Plusieurs méthodes pour poster une tâche sont
disponibles :
➔
post() : place la tâche à la fin de la queue (sera exécutée
après toutes les autres)
➔
postAtFrontOfQueue() : place la tâche au début, juste
après celle en cours d'exécution
➔
postAtTime() : place la tâche avec un marqueur temps
➔
postDelayed() : place la tâche avec un marqueur de délai
session sept 2014 Yann Caron (c) 2014 38
AsyncTask

Utilisé pour des tâches généralement plus
longues

Et/ou, pour gérer l'affichage de la progression
dans l'IHM

On utilise la classe AsyncTask 
<TypeDesParamètres, 
TypeDeProgression, TypeDuRésultat>
session sept 2014 Yann Caron (c) 2014 39
AsyncTast - Création
class MyAsyncTask extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... params) {
return null;
}
@Override
protected void onCancelled(String result) {
}
@Override
protected void onPostExecute(String result) {
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
}
}
Si la tâche est annulée
Tâche principale
Une fois finie
Gérer la progression
session sept 2014 Yann Caron (c) 2014 40
AsyncTask - Utilisation

Il suffit maintenant de l'instancier et de la
lancer

Les données seront transférées dans les
paramètres de la méthode
doInBackground(String... params)
MyAsyncTask task = new MyAsyncTask();
task.execute(new String[] { "my String" });
session sept 2014 Yann Caron (c) 2014 41
IN01 – Séance 07
IHM avancées
Vues personnalisées
session sept 2014 Yann Caron (c) 2014 42
Vue d'ensemble

Les Activities sont utilisées pour agréger des vues ensemble
(traitement d'un ensemble de données)

Une vue permet de traiter une donnée en particulier

Il existe quatre façons de créer des vues personnalisées :
➔
Une vue composée (héritage d'une sous-classe de ViewGroup)
➔
Un layout (héritage de ViewGroup)
➔
Spécialisation d'une vue existante (héritage d'une sous-classe de View)
➔
Création d'une vue de bout en bout (hérite de View)

Possibilité de combiner les approches
session sept 2014 Yann Caron (c) 2014 43
Vue composée

On doit créer une classe qui hérite d'une classe
elle-même héritant d'un viewGroup

Par exemple LinearLayout

Ensuite, dans le constructeur ou dans une
méthode spécifique, on ajoute dynamiquement
des vues enfants !!
session sept 2014 Yann Caron (c) 2014 44
Vue composée

Deux façons d'ajouter des composants :
➔
Par programmation grâce à la méthode addView (héritée de view)
➔
Par XML avec la méthode LayoutInflater
public class MyView extends LinearLayout {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
EditText txt1 = new EditText(context);
EditText txt2 = new EditText(context);
super.addView(txt1);
super.addView(txt2);
}
}
session sept 2014 Yann Caron (c) 2014 45
Vue composée - Utilisation

Utile pour afficher des listes de données, des tableaux

Dans Algoid j'ai utilisé cette technique pour :
➔
Le File Manager

Construction dynamique de la vue en fonction des fichiers
➔
Invite de commande

Entrées sorties utilisateur pilotées par programme
➔
Scope View

Construction d'une vue hiérarchique en fonction de l'état de la
mémoire
session sept 2014 Yann Caron (c) 2014 46
Création d'un layout

Principe : hériter de la classe ViewGroup

Surcharger la méthode onLayout et placer les vues enfants
(getChildCount() et getChildAt())
public class MyLayout extends ViewGroup{
@Override
protected void onLayout(boolean changed, int l,
int t, int r, int b) {
for (int i = 0; i< getChildCount(); i++) {
View child = this.getChildAt(i);
child.setX(10);
child.setY(10 * i);
}
}
}
session sept 2014 Yann Caron (c) 2014 47
Spécialisation

Principe : hériter d'une vue existante (elle-même
spécialisation de la classe View)

Ajouter des comportements en surchargeant des
méthodes (il faut bien lire la documentation)

Ajouter des comportements sur des évènements
(onTouch, onLongClick,onKey)

Ajouter des dessins (surcharge de la méthode
onDraw)
session sept 2014 Yann Caron (c) 2014 48
Spécialisation – Exemple

L'IDE d'Algoid par exemple : AutoCompletion,
coloration syntaxique et breakpoints
public class SourceEditorTextView extends MultiAutoCompleteTextView {
public SourceEditorTextView(Context context, AttributeSet attrs) {
super(context, attrs);
setOnLongClickListener(new OnLongClickListener() {
// ajouter les breakpoints
}
}
@Override
protected void onDraw(Canvas canvas) {
// dessiner ici les breakpoints
super.onDraw(canvas);
}
}
En réalité,
3 constructeurs
Ajoute un breakpoint
Dessine les breakpoints
session sept 2014 Yann Caron (c) 2014 49
Création de bout en bout

Principe : hériter de la classe View

Comme une vue spécialisée, mais sans
comportement préalable
➔
Gérer des évènements et implémenter les méthodes
nécessaires comme onDraw

Peut être long et fastidieux, il vaut mieux bien
évaluer si la vue n'existe pas au préalable

Exemple : Algo la petite tortue
session sept 2014 Yann Caron (c) 2014 50
Utilisation de la vue

Une fois la vue créée, il est possible de l'ajouter à un
conteneur :
➔
Activity, ViewGroup, Fragment

Toujours de deux façons :
➔
En Java
➔
En XML
addView(new MyView(context, attrs));
<fr.cnam.in01.techniques.MyView
android:id="@+id/myView"
myView:text1="myText1" myView:text2="myText2"/>
session sept 2014 Yann Caron (c) 2014 51
Paramètres personnalisés

Plusieurs étapes pour créer un attribut
personnalisé

But : pouvoir paramétrer la vue depuis des
valeurs passées dans l'XML

Un “Vrai” composant graphique !!
session sept 2014 Yann Caron (c) 2014 52
Paramètres personnalisés

Pour chaque attribut (ici text1 et text2), il faut
créer une paire getter/setter (setText1 etc.)

Il faut déclarer ces attributs dans une
ressource sous res/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyView">
<attr name="text1" format="string" />
<attr name="text2" format="string" />
</declare-styleable>
</resources>
session sept 2014 Yann Caron (c) 2014 53
Paramètres personnalisés

Il faut ensuite déclarer le nouveau NameSpace
dans le fichier XML de l'activity (là où est
utilisé MyView)

Puis utiliser les paramètres dans la déclaration
du composant
xmlns:myview="http://schemas.android.com/apk/res-auto"
<fr.cnam.in01.techniques.MyView
android:id="@+id/myView"
myview:text1="myText one"
myview:text2="myText two"/>
session sept 2014 Yann Caron (c) 2014 54
Paramètres personnalisés

Et enfin, récupérer les valeurs dans le
constructeur de la vue
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedAttrs = getContext()
.obtainStyledAttributes(attrs, R.styleable.MyView);
String text1 = typedAttrs.getString(R.styleable.MyView_text1);
txt1.setText(text1);
String text2 = typedAttrs.getString(R.styleable.MyView_text2);
txt2.setText(text2);
}
session sept 2014 Yann Caron (c) 2014 55
Conclusion

De quoi créer des bibliothèques de
composants entièrement personnalisées

Idéal pour la réutilisabilité du code

Ou la distribution de celui-ci

Pourtant, encore assez peu de bibliothèques
graphiques ne sont disponibles sur Android !!
session sept 2014 Yann Caron (c) 2014 56
IN01 – Séance 07
IHM avancées
Fragments
session sept 2014 Yann Caron (c) 2014 57
Vue d'ensemble

Un fragment est un composant graphique qui se situe entre la vue et
l'activity

Il est lié à une activity

Il peut être graphique ou logique

Il peut être chargé/déchargé dynamiquement (par programmation)

Ou être utilisé de façon statique (en XML)

Il est disponible depuis la version 11 de l'API (HoneyComb), mais grâce à
l'app compat générée avec un projet Android, il peut être utilisé sur des
API plus anciennes

Il sert à adapter les interfaces aux différentes résolutions des appareils
session sept 2014 Yann Caron (c) 2014 58
Vue d'ensemble

Les activities peuvent être composées d'un ou plusieurs
fragments en fonction de la place à disposition
session sept 2014 Yann Caron (c) 2014 59
Cycle de vie

Il a son propre cycle de vie

Cela permet d'isoler son comportement et ainsi de rendre
plus “léger” le code de l'activity

onAttach : sert à récupérer l'instance de l'activity

onCreate : sert à instancier les objets non graphiques

onCreateView : idem, mais graphiques

onStart : lancer les traitements

onResume : s'abonner aux évènements, récupérer le contexte

onPause : s'y désabonner et sauver le contexte

onStop, onDestroyView, onDestroy, onDetach : on
désalloue les ressources créées ci-dessus
session sept 2014 Yann Caron (c) 2014 60
Création d'un fragment

Un fichier XML, comme pour une activity
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<!-- content -->
</LinearLayout>
session sept 2014 Yann Caron (c) 2014 61
Création d'un fragment

Et la classe associée (qui hérite de Fragment)

Laquelle implémente l'évènement onCreateView
public class MenuFragment extends Fragment
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.menu_fragment,
container, false);
return view;
}
session sept 2014 Yann Caron (c) 2014 62
layout/main_activity
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="fr.cnam.in01.in01_fragments.MainActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:id="@+id/menu"
android:name="fr.cnam.in01.in01_fragments.MenuFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" />
</FrameLayout>
Un seul fragment
session sept 2014 Yann Caron (c) 2014 63
layout-land/main_activity
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:name="fr.cnam.in01.in01_fragments.MenuFragment"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1" />
<fragment
android:name="fr.cnam.in01.in01_fragments.MainFragment"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="2" />
</LinearLayout>
Plusieurs fragments
session sept 2014 Yann Caron (c) 2014 64
Instance du fragment

Dans la méthode onLoad() de l'activity, on a
accès à l'instance du/des fragments

Attention, ils peuvent ne pas exister dans le
XML, leur référence est null dans ce cas !!

On utilise la méthode
Activity.getFragmentManager()
MenuFragment fragment = (MenuFragment) getFragmentManager()
.findFragmentById(R.id.menu);
session sept 2014 Yann Caron (c) 2014 65
Du fragment vers l'activity

Pour que les fragments soient réutilisables, il
ne faut pas qu'ils communiquent directement
avec l'activity

On utilise une inversion de dépendance

Par exemple un template method (design
pattern, peu utilisé dans les IHM)

Ou un observer/observable
session sept 2014 Yann Caron (c) 2014 66
Évènements

On définit une interface et un mécanisme d'évènement
public class MenuFragment extends Fragment {
private MenuChangeEvent menuChanged;
public interface MenuChangeEvent {
void menuChanger(int id);
}
public void setOnMenuChange(MenuChangeEvent menuChanged) {
this.menuChanged = menuChanged;
}
private void fireMenuChanged(int id) {
if (this.menuChanged != null) {
this.menuChanged.menuChanger(id);
}
}
Invertion de dépendance
Abonnement
session sept 2014 Yann Caron (c) 2014 67
Évènements

Dans l'activity, lorsque le fragment est chargé,
on s'abonne à l'évènement
menuFragment.setOnMenuChange(new MenuChangeEvent() {
@Override
public void menuChanger(int id) {
switch (id) {
case R.id.button1:
navigate(MenuFragment.class);
break;
case R.id.button2:
navigate(MainFragment.class);
break;
}
}
});
session sept 2014 Yann Caron (c) 2014 68
Placeholder

Les fragments peuvent être placés de façon
statique dans le XML, comme on l'a vu

Ils peuvent également être chargés
dynamiquement (par programmation) dans des
placeholders

En général, on utilise des FrameLayout
session sept 2014 Yann Caron (c) 2014 69
Placeholder
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<FrameLayout
android:id="@+id/placeholder1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="@+id/placeholder2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" />
</LinearLayout>
session sept 2014 Yann Caron (c) 2014 70
Placeholder

On peut ensuite, charger les fragments à l'aide d'un
objet de type FragmentTransaction

La méthode addToBackStack permet de gérer le
bouton back (conserve un historique des fragments
chargés, comme pour les activities)
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(placeholder, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(null);
ft.commit();
session sept 2014 Yann Caron (c) 2014 71
Navigation

Ensuite, selon le nombre de placeholder à disposition,
on choisit quel type de navigation l'on souhaite :
➔
Une seule, on peut lancer une nouvelle activity ou
remplacer le placeholder 1
➔
Deux, on peut choisir le placeholder à charger et remplacer
le précédent

Le mieux étant de toujours passer le nom de la classe
du fragment de façon à l'instancier par introspection
Class<? extends Fragment> frClass = MenuFragment.class;
Fragment fragment = frClass.newInstance();
session sept 2014 Yann Caron (c) 2014 72
Persistance des états du fragment

On l'a vu, les Fragments sont des objets autonomes avec leur
cycle de vie propre

L'idée initiale est de décharger l'activity des tâches propres aux
sous-éléments graphiques qui se chargent et se déchargent de
façon dynamique

De cette façon, il est possible de gérer la sauvegarde des états
dans un Bundle

Comme pour les activity, on utilise les évènements du cycle de
vie du fragment : onCreateView() et
onSaveInstanceState()
session sept 2014 Yann Caron (c) 2014 73
Menus

Les fragments apportent leur propre menu lorsqu'ils sont chargés
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.fragment_menu, menu);
super.onCreateOptionsMenu(menu, inflater);
}
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.fragment_menu_item1:
// Action 1
return true;
default:
// Quelqu'un d'autre peut gérer ce menu
return super.onOptionsItemSelected(item);
}
}
session sept 2014 Yann Caron (c) 2014 74
Navigation drawer

Un menu qui glisse
quand on en a besoin

Source :
http://developer.android.
com/training/implement
ing-navigation/nav-
drawer.html
session sept 2014 Yann Caron (c) 2014 75
Navigation drawer

Création de l'activity
<android.support.v4.widget.DrawerLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"/>
</android.support.v4.widget.DrawerLayout>
Contenu
Menu sous forme
de liste
session sept 2014 Yann Caron (c) 2014 76
Navigation drawer

Chargement du menu dans l'activity
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ListView menu = (ListView) findViewById(R.id.menu);
String[] menuItems = getResources().getStringArray(R.array.menu_items_array);
// Set the adapter for the list view
menu.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, menuItems));
// Set the list's click listener
menu.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// TODO Auto-generated method stub
}
});
}
Items dans des tableaux
res/values
Gestion des événements
Icône + texte
session sept 2014 Yann Caron (c) 2014 77
Navigation drawer

Idéal avec les fragments

Google fournit un ensemble d'icônes

http://developer.android.com/downloads/desi
gn/Android_Design_Icons_20130926.zip
session sept 2014 Yann Caron (c) 2014 78
Navigation drawer
session sept 2014 Yann Caron (c) 2014 79
Conclusion

Les fragments offrent une réelle souplesse dans
l'organisation des IHM en fonction des résolutions

Une bonne pratique consiste à toujours concevoir ses
IHM selon des fragments, même pour des apps ne
nécessitant que peu d'écran

Une navigation plus riche pourra être conçue par la suite

Les composants de l'application bénéficieront également
d'une plus grande réutilisabilité
session sept 2014 Yann Caron (c) 2014 80
IN01 – Séance 07
Autres
Stratégies et alternatives
session sept 2014 Yann Caron (c) 2014 81
Stratégie – Choix de l'application

Red Ocean Strategy :
➔
Compléter un marché existant
➔
Exploiter une demande existante
➔
Battre la concurrence

Exemples : Pet rescue, Points and clicks

Avantage : Le marché existe déjà

Inconvénient : Pas d'innovation, pas passionnant
session sept 2014 Yann Caron (c) 2014 82
Stratégie – Choix de l'application

Blue Ocean Strategy :
➔
Créer un marché inexploité
➔
Créer ou capter de nouveaux besoins
➔
Pas de concurrence

Exemple : AIDE

Avantages : Avoir une longueur d'avance, être innovant,
développement motivant

Difficultés : Identifier le besoin, faire connaitre son
application
session sept 2014 Yann Caron (c) 2014 83
Dégager du revenu

Android une plateforme où il est difficile de
dégager du revenu
session sept 2014 Yann Caron (c) 2014 84
Enjeux du multiplateforme

De plus, il existe beaucoup d'applications sur le
Play Store (phénomène de flooding, noyade)

Les utilisateurs n'ont pas l'habitude d'acheter
sur cette plateforme

Il vaut mieux viser la publicité

Une meilleure stratégie consiste à viser
plusieurs plateformes
session sept 2014 Yann Caron (c) 2014 85
Enjeux du multiplateforme

Double avantage :
➔
Doubler potentiellement l'audience
➔
Gagner en crédibilité

Inconvénient :
➔
Il faut programmer plusieurs fois la même chose
➔
Dans des langages différents (Java – Objective C)

Ce n'est pas une obligation, des alternatives existent
session sept 2014 Yann Caron (c) 2014 86
C++

Un tronc commun, le C++ finalement le
langage le plus multiplateforme (Cross-
compilation vs Interpretation VM)

Une stratégie : écrire le middleware en C++ et
les UI en natif sur les deux plateformes

Inconvénients : compliqué, difficile à mettre en
place (database ?, bibliothèque ?)
session sept 2014 Yann Caron (c) 2014 87
C++/Qt

Une alternative : Qt 5.2

La version 5 annonçait les prémices, la 5.2 officialise le portage
iOS et Android

Une UI non native, mais complètement portable (la force de Qt)

C++ plus rapide que Java

Pas de Garbage collector

On peut faire des jeux

Exemple : FlyingBus de Digia
session sept 2014 Yann Caron (c) 2014 88
Xaramin/Mono

Mono est une implémentation de la plateforme .net sur UNIX

Xaramin est une startup des créateurs de Mono pour viser les
plateformes mobiles

Solution payante (démo puis 299 $/année)

Mais un gain de temps

Et C# est vraiment un langage puissant
➔
Objet/Fonctionnel (Linq)
➔
Nombreux sucres syntaxiques : propriétés, évènements, lambdas, extension
méthods
➔
Un framework riche : Reflexion, Emit, LightWeight AOP (LinFu)
session sept 2014 Yann Caron (c) 2014 89
Xaramin

Un IDE multiplateforme (Win, MacOS), mais pas Linux
session sept 2014 Yann Caron (c) 2014 90
RobotVM

RobotVM compile le bytecode Java en Assembleur à
destination des processeurs ARM ou X86

Bridge avec les API Objective C comme CocoaTouch

Open source (GPLv2)

Support Eclipse (plugin) et Maven

Stratégie : développement en couche, middleware
commun en Java et deux applications UI natives

Le langage AL et JASI (le parser) fonctionnent
session sept 2014 Yann Caron (c) 2014 91
JavaFX

Expérimental

Utilisation de l'OpenJFX 8, projet non officiel :
https://bitbucket.org/javafxports/android/wiki/Home

Utilisation de RobotVM pour
viser iOS

Il existe même un plugin
NetBeans
session sept 2014 Yann Caron (c) 2014 92
IN01 – Séance 07
Autres
Jeux Vidéo Mobiles
session sept 2014 Yann Caron (c) 2014 93
Parts de marché

Le jeu vidéo mobile progresse de façon
spectaculaire sur le marché
Source : Flurry Analytics (un concurrent de Google Analytics)
session sept 2014 Yann Caron (c) 2014 94
Game engines

AndEngine :
➔
2D – OpenGL ES - Physic
➔
Android
➔
Java based – simple d'utilisation
➔
Gratuit et Open Source

JmonkeyEngine :
➔
3D – OpenGL ES
➔
Java based
➔
Open Source free BSD
session sept 2014 Yann Caron (c) 2014 95
Multiplateforme - Java

LibGDX :
➔
2D / 3D – OpenGL ES – Physics
➔
Multiplateforme (Android, iOS,
Sybian, Win, Linux, MacOS, html 5)
➔
RobotVM ©

cross compilation
➔
Java
➔
Open source
session sept 2014 Yann Caron (c) 2014 96
OpenFl

OpenFl :
➔
2d uniquement
➔
massivement multiplateforme
➔
Fonctionne sur le langage Haxe (multiparadigme)

Créé par un Français
➔
Sur une VM NekoVM dont l'intermediate language est
un langage de script (et pas du byteCode)
➔
Initialement inspiré par Flash
session sept 2014 Yann Caron (c) 2014 97
NoJava – Alternative 2D

Sencyl :
➔
2D, multiplateforme (iOS, Android, Flash, etc.)
➔
Basé sur OpenFl
➔
NoCode - Payant
session sept 2014 Yann Caron (c) 2014 98
No Java – Alternative 3D

Unity 3D :
➔
2D / 3D
➔
WYSIWYG Lua scripting
➔
Payant
session sept 2014 Yann Caron (c) 2014 99
NoJava – Alternative 3D

ShiVa 3D :
➔
3D multiplateforme
➔
WYSIWYD – Lua scripting
➔
Server MMO
➔
Gratuit
session sept 2014 Yann Caron (c) 2014 100
Fin
 Merci de votre attention
 Des questions ?

Mais conteúdo relacionado

Mais procurados

In01 - Programmation Android - 03 - HMI
In01 - Programmation Android - 03 - HMIIn01 - Programmation Android - 03 - HMI
In01 - Programmation Android - 03 - HMIYann Caron
 
Programmation Android - 06 - Publication
Programmation Android - 06 - PublicationProgrammation Android - 06 - Publication
Programmation Android - 06 - PublicationYann Caron
 
Programmation Android - 05 - Google map
Programmation Android - 05 - Google mapProgrammation Android - 05 - Google map
Programmation Android - 05 - Google mapYann Caron
 
In01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationIn01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationYann Caron
 
Programmation Android - 00 - Présentation
Programmation Android - 00 - PrésentationProgrammation Android - 00 - Présentation
Programmation Android - 00 - PrésentationYann Caron
 
Programmation Android - 04 - Databases
Programmation Android - 04 - DatabasesProgrammation Android - 04 - Databases
Programmation Android - 04 - DatabasesYann Caron
 
Programmation Android - 10 - Spatialite
Programmation Android - 10 - SpatialiteProgrammation Android - 10 - Spatialite
Programmation Android - 10 - SpatialiteYann Caron
 
In01 - Programmation Android - 02 - android
In01 - Programmation Android - 02 - androidIn01 - Programmation Android - 02 - android
In01 - Programmation Android - 02 - androidYann Caron
 
Programmation Android - 03 - IHM bases
Programmation Android - 03 - IHM basesProgrammation Android - 03 - IHM bases
Programmation Android - 03 - IHM basesYann Caron
 
Programmation Android - 08 - Android debug bridge
Programmation Android - 08 - Android debug bridgeProgrammation Android - 08 - Android debug bridge
Programmation Android - 08 - Android debug bridgeYann Caron
 

Mais procurados (10)

In01 - Programmation Android - 03 - HMI
In01 - Programmation Android - 03 - HMIIn01 - Programmation Android - 03 - HMI
In01 - Programmation Android - 03 - HMI
 
Programmation Android - 06 - Publication
Programmation Android - 06 - PublicationProgrammation Android - 06 - Publication
Programmation Android - 06 - Publication
 
Programmation Android - 05 - Google map
Programmation Android - 05 - Google mapProgrammation Android - 05 - Google map
Programmation Android - 05 - Google map
 
In01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publicationIn01 - Programmation Android - 06 - publication
In01 - Programmation Android - 06 - publication
 
Programmation Android - 00 - Présentation
Programmation Android - 00 - PrésentationProgrammation Android - 00 - Présentation
Programmation Android - 00 - Présentation
 
Programmation Android - 04 - Databases
Programmation Android - 04 - DatabasesProgrammation Android - 04 - Databases
Programmation Android - 04 - Databases
 
Programmation Android - 10 - Spatialite
Programmation Android - 10 - SpatialiteProgrammation Android - 10 - Spatialite
Programmation Android - 10 - Spatialite
 
In01 - Programmation Android - 02 - android
In01 - Programmation Android - 02 - androidIn01 - Programmation Android - 02 - android
In01 - Programmation Android - 02 - android
 
Programmation Android - 03 - IHM bases
Programmation Android - 03 - IHM basesProgrammation Android - 03 - IHM bases
Programmation Android - 03 - IHM bases
 
Programmation Android - 08 - Android debug bridge
Programmation Android - 08 - Android debug bridgeProgrammation Android - 08 - Android debug bridge
Programmation Android - 08 - Android debug bridge
 

Destaque

In01 - Programmation Android - 01 - introduction
In01 - Programmation Android - 01 - introductionIn01 - Programmation Android - 01 - introduction
In01 - Programmation Android - 01 - introductionYann Caron
 
Développement Android
Développement AndroidDéveloppement Android
Développement AndroidFranck SIMON
 
Android Studio, premier contact
Android Studio, premier contactAndroid Studio, premier contact
Android Studio, premier contactJasmine Conseil
 
Formation JavaScript full-stack (JS, jQuery, Node.js...)
Formation JavaScript full-stack (JS, jQuery, Node.js...)Formation JavaScript full-stack (JS, jQuery, Node.js...)
Formation JavaScript full-stack (JS, jQuery, Node.js...)guicara
 
Alphorm.com Formation Android 5
Alphorm.com Formation Android 5Alphorm.com Formation Android 5
Alphorm.com Formation Android 5Alphorm
 
Introductions Aux Servlets
Introductions Aux ServletsIntroductions Aux Servlets
Introductions Aux ServletsFrançois Charoy
 
Ecoscan guide fr
Ecoscan guide frEcoscan guide fr
Ecoscan guide frGroupe One
 
Coordination of Activities in Dynamic Situations – The Case Of Crisis Management
Coordination of Activities in Dynamic Situations – The Case Of Crisis ManagementCoordination of Activities in Dynamic Situations – The Case Of Crisis Management
Coordination of Activities in Dynamic Situations – The Case Of Crisis ManagementFrançois Charoy
 
Les outils technologiques au service de l'accueil sur le territoire : le proj...
Les outils technologiques au service de l'accueil sur le territoire : le proj...Les outils technologiques au service de l'accueil sur le territoire : le proj...
Les outils technologiques au service de l'accueil sur le territoire : le proj...UETR2011Bergerac
 
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...François Charoy
 

Destaque (19)

In01 - Programmation Android - 01 - introduction
In01 - Programmation Android - 01 - introductionIn01 - Programmation Android - 01 - introduction
In01 - Programmation Android - 01 - introduction
 
Programmation sous Android
Programmation sous AndroidProgrammation sous Android
Programmation sous Android
 
Développement Android
Développement AndroidDéveloppement Android
Développement Android
 
Android Studio, premier contact
Android Studio, premier contactAndroid Studio, premier contact
Android Studio, premier contact
 
Formation JavaScript full-stack (JS, jQuery, Node.js...)
Formation JavaScript full-stack (JS, jQuery, Node.js...)Formation JavaScript full-stack (JS, jQuery, Node.js...)
Formation JavaScript full-stack (JS, jQuery, Node.js...)
 
Cours JavaScript
Cours JavaScriptCours JavaScript
Cours JavaScript
 
Alphorm.com Formation Android 5
Alphorm.com Formation Android 5Alphorm.com Formation Android 5
Alphorm.com Formation Android 5
 
Android cours
Android coursAndroid cours
Android cours
 
Les Fragments
Les FragmentsLes Fragments
Les Fragments
 
Introductions Aux Servlets
Introductions Aux ServletsIntroductions Aux Servlets
Introductions Aux Servlets
 
Les Servlets et JSP
Les Servlets et JSPLes Servlets et JSP
Les Servlets et JSP
 
Ecoscan guide fr
Ecoscan guide frEcoscan guide fr
Ecoscan guide fr
 
Pilote5
Pilote5Pilote5
Pilote5
 
Coordination of Activities in Dynamic Situations – The Case Of Crisis Management
Coordination of Activities in Dynamic Situations – The Case Of Crisis ManagementCoordination of Activities in Dynamic Situations – The Case Of Crisis Management
Coordination of Activities in Dynamic Situations – The Case Of Crisis Management
 
Les outils technologiques au service de l'accueil sur le territoire : le proj...
Les outils technologiques au service de l'accueil sur le territoire : le proj...Les outils technologiques au service de l'accueil sur le territoire : le proj...
Les outils technologiques au service de l'accueil sur le territoire : le proj...
 
SQLite 3
SQLite 3SQLite 3
SQLite 3
 
Les applications mobiles
Les applications mobilesLes applications mobiles
Les applications mobiles
 
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...
Keynote IEEE Wetice conference 2016 - From group collaboration to large scale...
 
Présentation de Node.js
Présentation de Node.jsPrésentation de Node.js
Présentation de Node.js
 

Semelhante a In01 - Programmation Android - 07 - techniques avancées

Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Bruno Delb
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introductionneuros
 
Les capteurs sous android
Les capteurs sous androidLes capteurs sous android
Les capteurs sous androidSaber LAJILI
 
AXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesAXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesACIC
 
AXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesAXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesACIC
 
Cours_P627_19_03_2024.pptfjghgfjjfjhggjb
Cours_P627_19_03_2024.pptfjghgfjjfjhggjbCours_P627_19_03_2024.pptfjghgfjjfjhggjb
Cours_P627_19_03_2024.pptfjghgfjjfjhggjbAbdo Brahmi
 
Cours_P627_09_03_2023.pptghfgggghgghhghh
Cours_P627_09_03_2023.pptghfgggghgghhghhCours_P627_09_03_2023.pptghfgggghgghhghh
Cours_P627_09_03_2023.pptghfgggghgghhghhAbdo Brahmi
 
Cours_P627_09_03_2023.pptafrsecxghgghjgj
Cours_P627_09_03_2023.pptafrsecxghgghjgjCours_P627_09_03_2023.pptafrsecxghgghjgj
Cours_P627_09_03_2023.pptafrsecxghgghjgjAbdo Brahmi
 
rapport_ecrit_final
rapport_ecrit_finalrapport_ecrit_final
rapport_ecrit_finalJean Ibarz
 
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014Benoît de CHATEAUVIEUX
 
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...Informatique verte des capteurs intelligents à la fouille de données - 2014-1...
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...Jérôme Rocheteau
 
Machine Leargning_supérvisé.pptx
Machine Leargning_supérvisé.pptxMachine Leargning_supérvisé.pptx
Machine Leargning_supérvisé.pptxbely26
 
ACDM approche detection malware
ACDM approche detection malware ACDM approche detection malware
ACDM approche detection malware youssra chaib
 
Rapport belgacem khaled
Rapport belgacem khaledRapport belgacem khaled
Rapport belgacem khaledBoughraraanis
 
Seminaire serres andrieu_profils vitesse
Seminaire serres andrieu_profils vitesseSeminaire serres andrieu_profils vitesse
Seminaire serres andrieu_profils vitesseGuillaumeSaintPierre
 
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...Institut de l'Elevage - Idele
 
20100608 2 - TNR automatisés (Generali)
20100608 2 - TNR automatisés (Generali)20100608 2 - TNR automatisés (Generali)
20100608 2 - TNR automatisés (Generali)LeClubQualiteLogicielle
 

Semelhante a In01 - Programmation Android - 07 - techniques avancées (20)

Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)Android Lab Test : Le capteur gyroscope (français)
Android Lab Test : Le capteur gyroscope (français)
 
Design Pattern introduction
Design Pattern introductionDesign Pattern introduction
Design Pattern introduction
 
Patron observer
Patron observerPatron observer
Patron observer
 
J Unit
J UnitJ Unit
J Unit
 
Les capteurs sous android
Les capteurs sous androidLes capteurs sous android
Les capteurs sous android
 
AXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesAXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensibles
 
AXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensiblesAXIS ACIC protection perimetrique de sites sensibles
AXIS ACIC protection perimetrique de sites sensibles
 
Cours_P627_19_03_2024.pptfjghgfjjfjhggjb
Cours_P627_19_03_2024.pptfjghgfjjfjhggjbCours_P627_19_03_2024.pptfjghgfjjfjhggjb
Cours_P627_19_03_2024.pptfjghgfjjfjhggjb
 
Cours_P627_09_03_2023.pptghfgggghgghhghh
Cours_P627_09_03_2023.pptghfgggghgghhghhCours_P627_09_03_2023.pptghfgggghgghhghh
Cours_P627_09_03_2023.pptghfgggghgghhghh
 
Cours_P627_09_03_2023.pptafrsecxghgghjgj
Cours_P627_09_03_2023.pptafrsecxghgghjgjCours_P627_09_03_2023.pptafrsecxghgghjgj
Cours_P627_09_03_2023.pptafrsecxghgghjgj
 
rapport_ecrit_final
rapport_ecrit_finalrapport_ecrit_final
rapport_ecrit_final
 
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014
"La Performance en Continue" à JMaghreb 3.0 - 05/11/2014
 
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...Informatique verte des capteurs intelligents à la fouille de données - 2014-1...
Informatique verte des capteurs intelligents à la fouille de données - 2014-1...
 
Machine Leargning_supérvisé.pptx
Machine Leargning_supérvisé.pptxMachine Leargning_supérvisé.pptx
Machine Leargning_supérvisé.pptx
 
Perf university
Perf universityPerf university
Perf university
 
ACDM approche detection malware
ACDM approche detection malware ACDM approche detection malware
ACDM approche detection malware
 
Rapport belgacem khaled
Rapport belgacem khaledRapport belgacem khaled
Rapport belgacem khaled
 
Seminaire serres andrieu_profils vitesse
Seminaire serres andrieu_profils vitesseSeminaire serres andrieu_profils vitesse
Seminaire serres andrieu_profils vitesse
 
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...
Projet CAPRIMAM 3D, mise au point d’un scanner 3D des mamelles caprines : où ...
 
20100608 2 - TNR automatisés (Generali)
20100608 2 - TNR automatisés (Generali)20100608 2 - TNR automatisés (Generali)
20100608 2 - TNR automatisés (Generali)
 

Mais de Yann Caron

Théorie des langages - TP - WellKnownText
Théorie des langages - TP  - WellKnownTextThéorie des langages - TP  - WellKnownText
Théorie des langages - TP - WellKnownTextYann Caron
 
Théorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langagesThéorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langagesYann Caron
 
Théorie des langages - 03 - Principes et paradigmes
Théorie des langages - 03 - Principes et paradigmesThéorie des langages - 03 - Principes et paradigmes
Théorie des langages - 03 - Principes et paradigmesYann Caron
 
Théorie des langages - 02 - Code gen
Théorie des langages - 02 - Code genThéorie des langages - 02 - Code gen
Théorie des langages - 02 - Code genYann Caron
 
Théorie des langages - 01.1 - Parcours d'arbres
Théorie des langages - 01.1 - Parcours d'arbresThéorie des langages - 01.1 - Parcours d'arbres
Théorie des langages - 01.1 - Parcours d'arbresYann Caron
 
Théorie des langages - 01 - Compilation
Théorie des langages - 01 - CompilationThéorie des langages - 01 - Compilation
Théorie des langages - 01 - CompilationYann Caron
 
Théorie des langages - 00 - Introduction
Théorie des langages - 00 - IntroductionThéorie des langages - 00 - Introduction
Théorie des langages - 00 - IntroductionYann Caron
 
Algea - 04 - conclusion
Algea - 04 - conclusionAlgea - 04 - conclusion
Algea - 04 - conclusionYann Caron
 
Algea - 03 - ennemis
Algea - 03 - ennemisAlgea - 03 - ennemis
Algea - 03 - ennemisYann Caron
 
Algea - 02 - gemmes
Algea - 02 - gemmesAlgea - 02 - gemmes
Algea - 02 - gemmesYann Caron
 
Algea - 01 - hero
Algea - 01 - heroAlgea - 01 - hero
Algea - 01 - heroYann Caron
 
ALGEA - 00 - introduction
ALGEA - 00 - introductionALGEA - 00 - introduction
ALGEA - 00 - introductionYann Caron
 
Cours CNAM In01 - Programmation Android - Septembre 2014
Cours CNAM In01 - Programmation Android - Septembre 2014Cours CNAM In01 - Programmation Android - Septembre 2014
Cours CNAM In01 - Programmation Android - Septembre 2014Yann Caron
 

Mais de Yann Caron (13)

Théorie des langages - TP - WellKnownText
Théorie des langages - TP  - WellKnownTextThéorie des langages - TP  - WellKnownText
Théorie des langages - TP - WellKnownText
 
Théorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langagesThéorie des langages - 04 Théorie des langages
Théorie des langages - 04 Théorie des langages
 
Théorie des langages - 03 - Principes et paradigmes
Théorie des langages - 03 - Principes et paradigmesThéorie des langages - 03 - Principes et paradigmes
Théorie des langages - 03 - Principes et paradigmes
 
Théorie des langages - 02 - Code gen
Théorie des langages - 02 - Code genThéorie des langages - 02 - Code gen
Théorie des langages - 02 - Code gen
 
Théorie des langages - 01.1 - Parcours d'arbres
Théorie des langages - 01.1 - Parcours d'arbresThéorie des langages - 01.1 - Parcours d'arbres
Théorie des langages - 01.1 - Parcours d'arbres
 
Théorie des langages - 01 - Compilation
Théorie des langages - 01 - CompilationThéorie des langages - 01 - Compilation
Théorie des langages - 01 - Compilation
 
Théorie des langages - 00 - Introduction
Théorie des langages - 00 - IntroductionThéorie des langages - 00 - Introduction
Théorie des langages - 00 - Introduction
 
Algea - 04 - conclusion
Algea - 04 - conclusionAlgea - 04 - conclusion
Algea - 04 - conclusion
 
Algea - 03 - ennemis
Algea - 03 - ennemisAlgea - 03 - ennemis
Algea - 03 - ennemis
 
Algea - 02 - gemmes
Algea - 02 - gemmesAlgea - 02 - gemmes
Algea - 02 - gemmes
 
Algea - 01 - hero
Algea - 01 - heroAlgea - 01 - hero
Algea - 01 - hero
 
ALGEA - 00 - introduction
ALGEA - 00 - introductionALGEA - 00 - introduction
ALGEA - 00 - introduction
 
Cours CNAM In01 - Programmation Android - Septembre 2014
Cours CNAM In01 - Programmation Android - Septembre 2014Cours CNAM In01 - Programmation Android - Septembre 2014
Cours CNAM In01 - Programmation Android - Septembre 2014
 

In01 - Programmation Android - 07 - techniques avancées

  • 1. session sept 2014 Yann Caron (c) 2014 1 IN01 Programmation Android 07 – Techniques avancées Yann Caron
  • 2. session sept 2014 Yann Caron (c) 2014 2 Sommaire - Séance 07  Programmation avancée ➔ Capteurs ➔ Optimisations ➔ Tests unitaires ➔ Concurrence  IHM avancées ➔ Vues personnalisées ➔ Fragments  Autres ➔ Stratégies et alternatives ➔ Jeux vidéo mobiles
  • 3. session sept 2014 Yann Caron (c) 2014 3 IN01 – Séance 07 Programmation avancée Capteurs
  • 4. session sept 2014 Yann Caron (c) 2014 4 Généralités  La miniaturisation et l'industrialisation rendent aujourd'hui accessibles des capteurs précis au grand public  La majorité des appareils Android embarquent au moins un accéléromètre, un gyroscope et un magnétomètre  Les trois tiennent sur ce circuit :
  • 5. session sept 2014 Yann Caron (c) 2014 5 Différents capteurs Android TYPE_ACCELE ROMETER 3 m/s2 Mesure de l'accélération (gravité incluse) [0] axe x [1] axe y [2] axe z TYPE_GYROS COPE 3 Rad / s Mesure la rotation en termes de vitesse autour de chaque axe [0] vitesse x [1] vitesse y [2] vitesse z TYPE_LIGHT 1 Lux Mesure de la luminosité [0]valeur TYPE_MAGNE TIC_FIELD 3 µTesla Mesure du champ magnétique [0] axe x [1] axe y [2] axe z TYPE_ORIENT ATION 3 degrés Mesure l'angle entre le nord magnétique [0] Azimut y / nord [1] Rotation x (- 180,180) [2] Rotation y (-90,90) TYPE_PRESSU RE 1 KPas Mesure la pression [0]valeur TYPE_PROXIM ITY 1 mètre Mesure la distance entre l'appareil et un objet cible [0]valeur TYPE_TEMPER ATURE 1 Celsius Mesure la température [0]valeur
  • 6. session sept 2014 Yann Caron (c) 2014 6 Présence du capteur  On peut interdire (ou pas) l'utilisation de l'application aux appareils qui ne possèdent pas un certain capteur  Utile si votre application ne peut pas fonctionner sans de façon correcte  Dans le manifest (toujours !!) : <uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
  • 7. session sept 2014 Yann Caron (c) 2014 7 Sensor Manager  Pour accéder aux senseurs, on appelle une méthode de l'Activity qui renvoie un objet de type SensorManager  On peut récupérer la liste des capteurs disponibles sur l'appareil SensorManager sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE); ArrayList<Sensor> liste = (ArrayList<Sensor>) sensorManager.getSensorList(Sensor.TYPE_MAGNETIC_FIELD);
  • 8. session sept 2014 Yann Caron (c) 2014 8 Obtenir une instance de capteur  On peut maintenant obtenir une instance du capteur souhaité  Attention !! Si le capteur n'est pas disponible, l'objet renvoie la valeur null. Si le capteur n'est pas requis, il faut tester et gérer s'il est absent. Sensor accelerometre = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
  • 9. session sept 2014 Yann Caron (c) 2014 9 Évènement  Les capteurs fonctionnent aussi sur un modèle évènementiel final SensorEventListener mSensorEventListener = new SensorEventListener() { public void onAccuracyChanged(Sensor sensor, int accuracy) { // Que faire en cas de changement de précision ? } public void onSensorChanged(SensorEvent sensorEvent) { // Que faire en cas d'évènements sur le capteur ? } }; Si la précision a changé Si les valeurs ont changé
  • 10. session sept 2014 Yann Caron (c) 2014 10 Évènement  Attention, il est préférable d'enregistrer l'évènement lorsque l'application est active et de le désenregistrer lorsque celle-ci est inactive  Sinon, il continue de s'exécuter @Override protected void onResume() { super.onResume(); mSensorManager.registerListener(mSensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { super.onPause(); mSensorManager.unregisterListener(mSensorEventListener, mAccelerometer); }
  • 11. session sept 2014 Yann Caron (c) 2014 11 Évènement – Valeurs  L'évènement du capteur renvoie un tableau de valeurs float  Leur nombre et leur signification varient selon les capteurs (voir tableau précédent) public void onSensorChanged(SensorEvent sensorEvent) { float[] values = sensorEvent.values; Log.d("Sensors", "Acceleration sur l'axe x : " + values[0]); Log.d("Sensors", "Acceleration sur l'axe y : " + values[1]); Log.d("Sensors", "Acceleration sur l'axe z : " + values[2]); }
  • 12. session sept 2014 Yann Caron (c) 2014 12 Rotation  Doit être calculée avec les valeurs de l'accéléromètre et du magnétomètre combinées à l'aide de formules complexes  Deux méthodes existent pour faciliter ce calcul : getRotationMatrix() et getOrientation() float[] values = new float[3]; float[] R = new float[9]; SensorManager.getRotationMatrix(R, null, accelerometreValues, magnetometreValues); SensorManager.getOrientation(R, values); Log.d("Sensors", "Rotation sur l'axe z : " + values[0]); Log.d("Sensors", "Rotation sur l'axe x : " + values[1]); Log.d("Sensors", "Rotation sur l'axe y : " + values[2]);
  • 13. session sept 2014 Yann Caron (c) 2014 13 Quelques applications
  • 14. session sept 2014 Yann Caron (c) 2014 14 IN01 – Séance 07 Programmation avancée Optimisation
  • 15. session sept 2014 Yann Caron (c) 2014 15 Optimisation sous Android  Pourquoi ?? ➔ Pour de meilleures performances !!  Oui, mais pour qui ?? ➔ Les applications de bas niveau (un compilateur de langage comme Algoid par exemple ;-)) ➔ Des applications gourmandes en ressources (les jeux vidéo, les applications graphiques)
  • 16. session sept 2014 Yann Caron (c) 2014 16 Règles – Les objets  Éviter de créer des objets non nécessaires  En règle générale, éviter de créer trop d'objets ! ➔ Parce que la création d'objets c'est gourmand ➔ Et la destruction encore pire : la dalvikVM bloque tout processus lors du GC (GC dit Stop the World) ➔ Préférer les StringBuffer aux concaténations de strings à outrance ➔ Un tableau d'int est meilleur qu'un tableau d'integer (utilisation des types primitifs)
  • 17. session sept 2014 Yann Caron (c) 2014 17 Règles – Les listes  Un tableau est meilleur qu'une ArrayList, même règle que précédemment sur les types primitifs  Une ArrayList est moins coûteuse à lire qu'une LinkedList (création d'objets entry qui seront à gérer par le GC)
  • 18. session sept 2014 Yann Caron (c) 2014 18 Règles – Les boucles  Idéal :  Catastrophique : int size = myArray.length); for (int i = 0; i < size; i ++) { } La taille est évaluée à chaque itération Map<Integer, String> myMap = new HashMap(); for (Entry<Integer, String> item : myMap.entrySet()) { } Un objet Entry<Key, Value> créé à chaque itération
  • 19. session sept 2014 Yann Caron (c) 2014 19 Règles – Méthodes et variables  Préférer les méthodes statiques aux méthodes de classe, si aucun attribut de la classe n'est nécessaire  Utiliser static final pour les constantes  Éviter les inner class, surtout si elles ne sont pas statiques  Éviter les getter et setter (antipattern)  Les float 2x plus lents que les int  Les double sont 2x plus gourmands en mémoire que les float
  • 20. session sept 2014 Yann Caron (c) 2014 20 Règles - Conclusion  Attention toutefois à ne pas abuser des règles d'optimisation  Évaluer si l'application nécessite une optimisation  Toujours mettre en relation le gain de performances (CPU/Mem) et la lisibilité du code  Car attention ! Ces règles dégradent la qualité du code et donc la lisibilité et la réutilisabilité
  • 21. session sept 2014 Yann Caron (c) 2014 21 Optimisation - Outils  Toujours mesurer les gains par des micro-benchmarks :  Et le JIT (Just In Time Compiler) ?  Profilers netbeans ou Eclipse sont nos amis  Résultat : Algoid Language aussi rapide que Python est plus rapide que JavaScript sur Android :-) Pas mal pour un langage seulement interprété force brute long time = System.currentTimeMillis(); for (int i=0; i<1000000; i++) { // le code à tester } long timeSpent = System.currentTimeMillis() - time; System.out.println("Time spent " + timeSpent);
  • 22. session sept 2014 Yann Caron (c) 2014 22 IN01 – Séance 07 Programmation avancée Tests unitaires
  • 23. session sept 2014 Yann Caron (c) 2014 23 Vue d'ensemble  Créer des tests unitaires pour tester des apps Android, c'est possible  Ça fonctionne avec JUnit  On peut tester l'interface utilisateur (manipulation)
  • 24. session sept 2014 Yann Caron (c) 2014 24 Création du projet de test  Depuis Eclipse
  • 25. session sept 2014 Yann Caron (c) 2014 25 Création du projet de test  On choisit le projet à tester
  • 26. session sept 2014 Yann Caron (c) 2014 26 Test Fixture  Pour créer un test case, il suffit de créer une nouvelle classe de test  Celle-ci devra hériter de la classe ActivityInstrumentationTestCase2  Et fournir la classe à tester dans son constructeur public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity>{ public ActivityTest() { super(MainActivity.class); } } La Classe à tester
  • 27. session sept 2014 Yann Caron (c) 2014 27 SetUp  Lors du setUp, on récupère les instances de l'activity et des composants à tester private MainActivity activity = null; private TextView myTextView = null; private Button myButton = null; @Override protected void setUp() throws Exception { super.setUp(); activity = getActivity(); myTextView = (TextView) activity.findViewById( fr.cnam.helloworld.R.id.myTextView); myButton = (Button)activity.findViewById( fr.cnam.helloworld.R.id.myButton); } R (ressources) du projet à tester
  • 28. session sept 2014 Yann Caron (c) 2014 28 Préconditions  Une bonne pratique consiste à tester que le setUp s'est bien déroulé @SmallTest public void testPreconditions() { assertNotNull("activity is null", activity); assertNotNull("myTextView is null", myTextView); assertNotNull("myButton is null", myButton); }
  • 29. session sept 2014 Yann Caron (c) 2014 29 Layout test  Tester le layout des composants @MediumTest public void testMyTextView_layout() { final View decorView = activity.getWindow().getDecorView(); ViewAsserts.assertOnScreen(decorView, myTextView); final ViewGroup.LayoutParams layoutParams = myTextView.getLayoutParams(); assertNotNull(layoutParams); assertEquals(layoutParams.width, WindowManager.LayoutParams.WRAP_CONTENT); assertEquals(layoutParams.height, WindowManager.LayoutParams.WRAP_CONTENT); } Test que le composant est présent
  • 30. session sept 2014 Yann Caron (c) 2014 30 @MediumTest public void testMyButton_click() { String initialText = activity.getString( fr.cnam.helloworld.R.string.hello_world); String expectedText = activity.getString( fr.cnam.helloworld.R.string.after_click); assertEquals(initialText, myTextView.getText()); TouchUtils.clickView(this, myButton); assertEquals(expectedText, myTextView.getText()); } Tester les comportements souhaités  Utilisation de TouchUtils pour simuler les actions utilisateur Clic sur le bouton
  • 31. session sept 2014 Yann Caron (c) 2014 31 Test Annotations  @SmallTest : ➔ Un test court, moins de 100 ms  @MediumTest : ➔ Un test de durée moyenne, supérieure à 100 ms  @LargeTest : ➔ Idem que le mediumTest, avec un accès plus important aux ressources
  • 32. session sept 2014 Yann Caron (c) 2014 32 Résultats  Et voilà le travail !!  Les sources complètes sont dans le projet du cours  Bons tests !!
  • 33. session sept 2014 Yann Caron (c) 2014 33 IN01 – Séance 07 Programmation avancée Concurrence
  • 34. session sept 2014 Yann Caron (c) 2014 34 Généralités  Pour gérer des traitements et pour ne pas bloquer l'interface utilisateur, on utilise des Threads  Problème !! Il nous est interdit de modifier l'IHM depuis un autre Thread que le Thread principal  Deux outils existent sur Android : Handler et AsyncTask  cf. SwingWorker de Swing
  • 35. session sept 2014 Yann Caron (c) 2014 35 Handler - Pattern  Son but : synchroniser de petites tâches et les ordonner (comme un ordonnanceur)  Un handler particulier attaché à l'IHM  C'est une queue de tâches  Le consommateur se met en attente sur la queue  Lorsqu'une tâche est ajoutée par un des multiples producteurs (threads), la queue est notifiée, débloquant ainsi le consommateur  Lorsque le consommateur a tout consommé, il se remet en attente  Ça ressemble au patron Reader – Writer lock, mais, inversé (multiple writer et mono reader)  Utilisation massive dans Algoid (le script emploie son propre thread)
  • 36. session sept 2014 Yann Caron (c) 2014 36 Handler - Utilisation  Il faut créer un handler (ou en récupérer un d'une vue)  Puis lui envoyer des tâches Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } });
  • 37. session sept 2014 Yann Caron (c) 2014 37 Handler - Les méthodes  Plusieurs méthodes pour poster une tâche sont disponibles : ➔ post() : place la tâche à la fin de la queue (sera exécutée après toutes les autres) ➔ postAtFrontOfQueue() : place la tâche au début, juste après celle en cours d'exécution ➔ postAtTime() : place la tâche avec un marqueur temps ➔ postDelayed() : place la tâche avec un marqueur de délai
  • 38. session sept 2014 Yann Caron (c) 2014 38 AsyncTask  Utilisé pour des tâches généralement plus longues  Et/ou, pour gérer l'affichage de la progression dans l'IHM  On utilise la classe AsyncTask  <TypeDesParamètres,  TypeDeProgression, TypeDuRésultat>
  • 39. session sept 2014 Yann Caron (c) 2014 39 AsyncTast - Création class MyAsyncTask extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... params) { return null; } @Override protected void onCancelled(String result) { } @Override protected void onPostExecute(String result) { } @Override protected void onProgressUpdate(Integer... values) { super.onProgressUpdate(values); } } Si la tâche est annulée Tâche principale Une fois finie Gérer la progression
  • 40. session sept 2014 Yann Caron (c) 2014 40 AsyncTask - Utilisation  Il suffit maintenant de l'instancier et de la lancer  Les données seront transférées dans les paramètres de la méthode doInBackground(String... params) MyAsyncTask task = new MyAsyncTask(); task.execute(new String[] { "my String" });
  • 41. session sept 2014 Yann Caron (c) 2014 41 IN01 – Séance 07 IHM avancées Vues personnalisées
  • 42. session sept 2014 Yann Caron (c) 2014 42 Vue d'ensemble  Les Activities sont utilisées pour agréger des vues ensemble (traitement d'un ensemble de données)  Une vue permet de traiter une donnée en particulier  Il existe quatre façons de créer des vues personnalisées : ➔ Une vue composée (héritage d'une sous-classe de ViewGroup) ➔ Un layout (héritage de ViewGroup) ➔ Spécialisation d'une vue existante (héritage d'une sous-classe de View) ➔ Création d'une vue de bout en bout (hérite de View)  Possibilité de combiner les approches
  • 43. session sept 2014 Yann Caron (c) 2014 43 Vue composée  On doit créer une classe qui hérite d'une classe elle-même héritant d'un viewGroup  Par exemple LinearLayout  Ensuite, dans le constructeur ou dans une méthode spécifique, on ajoute dynamiquement des vues enfants !!
  • 44. session sept 2014 Yann Caron (c) 2014 44 Vue composée  Deux façons d'ajouter des composants : ➔ Par programmation grâce à la méthode addView (héritée de view) ➔ Par XML avec la méthode LayoutInflater public class MyView extends LinearLayout { public MyView(Context context, AttributeSet attrs) { super(context, attrs); EditText txt1 = new EditText(context); EditText txt2 = new EditText(context); super.addView(txt1); super.addView(txt2); } }
  • 45. session sept 2014 Yann Caron (c) 2014 45 Vue composée - Utilisation  Utile pour afficher des listes de données, des tableaux  Dans Algoid j'ai utilisé cette technique pour : ➔ Le File Manager  Construction dynamique de la vue en fonction des fichiers ➔ Invite de commande  Entrées sorties utilisateur pilotées par programme ➔ Scope View  Construction d'une vue hiérarchique en fonction de l'état de la mémoire
  • 46. session sept 2014 Yann Caron (c) 2014 46 Création d'un layout  Principe : hériter de la classe ViewGroup  Surcharger la méthode onLayout et placer les vues enfants (getChildCount() et getChildAt()) public class MyLayout extends ViewGroup{ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { for (int i = 0; i< getChildCount(); i++) { View child = this.getChildAt(i); child.setX(10); child.setY(10 * i); } } }
  • 47. session sept 2014 Yann Caron (c) 2014 47 Spécialisation  Principe : hériter d'une vue existante (elle-même spécialisation de la classe View)  Ajouter des comportements en surchargeant des méthodes (il faut bien lire la documentation)  Ajouter des comportements sur des évènements (onTouch, onLongClick,onKey)  Ajouter des dessins (surcharge de la méthode onDraw)
  • 48. session sept 2014 Yann Caron (c) 2014 48 Spécialisation – Exemple  L'IDE d'Algoid par exemple : AutoCompletion, coloration syntaxique et breakpoints public class SourceEditorTextView extends MultiAutoCompleteTextView { public SourceEditorTextView(Context context, AttributeSet attrs) { super(context, attrs); setOnLongClickListener(new OnLongClickListener() { // ajouter les breakpoints } } @Override protected void onDraw(Canvas canvas) { // dessiner ici les breakpoints super.onDraw(canvas); } } En réalité, 3 constructeurs Ajoute un breakpoint Dessine les breakpoints
  • 49. session sept 2014 Yann Caron (c) 2014 49 Création de bout en bout  Principe : hériter de la classe View  Comme une vue spécialisée, mais sans comportement préalable ➔ Gérer des évènements et implémenter les méthodes nécessaires comme onDraw  Peut être long et fastidieux, il vaut mieux bien évaluer si la vue n'existe pas au préalable  Exemple : Algo la petite tortue
  • 50. session sept 2014 Yann Caron (c) 2014 50 Utilisation de la vue  Une fois la vue créée, il est possible de l'ajouter à un conteneur : ➔ Activity, ViewGroup, Fragment  Toujours de deux façons : ➔ En Java ➔ En XML addView(new MyView(context, attrs)); <fr.cnam.in01.techniques.MyView android:id="@+id/myView" myView:text1="myText1" myView:text2="myText2"/>
  • 51. session sept 2014 Yann Caron (c) 2014 51 Paramètres personnalisés  Plusieurs étapes pour créer un attribut personnalisé  But : pouvoir paramétrer la vue depuis des valeurs passées dans l'XML  Un “Vrai” composant graphique !!
  • 52. session sept 2014 Yann Caron (c) 2014 52 Paramètres personnalisés  Pour chaque attribut (ici text1 et text2), il faut créer une paire getter/setter (setText1 etc.)  Il faut déclarer ces attributs dans une ressource sous res/values/attrs.xml <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyView"> <attr name="text1" format="string" /> <attr name="text2" format="string" /> </declare-styleable> </resources>
  • 53. session sept 2014 Yann Caron (c) 2014 53 Paramètres personnalisés  Il faut ensuite déclarer le nouveau NameSpace dans le fichier XML de l'activity (là où est utilisé MyView)  Puis utiliser les paramètres dans la déclaration du composant xmlns:myview="http://schemas.android.com/apk/res-auto" <fr.cnam.in01.techniques.MyView android:id="@+id/myView" myview:text1="myText one" myview:text2="myText two"/>
  • 54. session sept 2014 Yann Caron (c) 2014 54 Paramètres personnalisés  Et enfin, récupérer les valeurs dans le constructeur de la vue public MyView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedAttrs = getContext() .obtainStyledAttributes(attrs, R.styleable.MyView); String text1 = typedAttrs.getString(R.styleable.MyView_text1); txt1.setText(text1); String text2 = typedAttrs.getString(R.styleable.MyView_text2); txt2.setText(text2); }
  • 55. session sept 2014 Yann Caron (c) 2014 55 Conclusion  De quoi créer des bibliothèques de composants entièrement personnalisées  Idéal pour la réutilisabilité du code  Ou la distribution de celui-ci  Pourtant, encore assez peu de bibliothèques graphiques ne sont disponibles sur Android !!
  • 56. session sept 2014 Yann Caron (c) 2014 56 IN01 – Séance 07 IHM avancées Fragments
  • 57. session sept 2014 Yann Caron (c) 2014 57 Vue d'ensemble  Un fragment est un composant graphique qui se situe entre la vue et l'activity  Il est lié à une activity  Il peut être graphique ou logique  Il peut être chargé/déchargé dynamiquement (par programmation)  Ou être utilisé de façon statique (en XML)  Il est disponible depuis la version 11 de l'API (HoneyComb), mais grâce à l'app compat générée avec un projet Android, il peut être utilisé sur des API plus anciennes  Il sert à adapter les interfaces aux différentes résolutions des appareils
  • 58. session sept 2014 Yann Caron (c) 2014 58 Vue d'ensemble  Les activities peuvent être composées d'un ou plusieurs fragments en fonction de la place à disposition
  • 59. session sept 2014 Yann Caron (c) 2014 59 Cycle de vie  Il a son propre cycle de vie  Cela permet d'isoler son comportement et ainsi de rendre plus “léger” le code de l'activity  onAttach : sert à récupérer l'instance de l'activity  onCreate : sert à instancier les objets non graphiques  onCreateView : idem, mais graphiques  onStart : lancer les traitements  onResume : s'abonner aux évènements, récupérer le contexte  onPause : s'y désabonner et sauver le contexte  onStop, onDestroyView, onDestroy, onDetach : on désalloue les ressources créées ci-dessus
  • 60. session sept 2014 Yann Caron (c) 2014 60 Création d'un fragment  Un fichier XML, comme pour une activity <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <!-- content --> </LinearLayout>
  • 61. session sept 2014 Yann Caron (c) 2014 61 Création d'un fragment  Et la classe associée (qui hérite de Fragment)  Laquelle implémente l'évènement onCreateView public class MenuFragment extends Fragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View view = inflater.inflate(R.layout.menu_fragment, container, false); return view; }
  • 62. session sept 2014 Yann Caron (c) 2014 62 layout/main_activity <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="fr.cnam.in01.in01_fragments.MainActivity" tools:ignore="MergeRootFrame" > <fragment android:id="@+id/menu" android:name="fr.cnam.in01.in01_fragments.MenuFragment" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" /> </FrameLayout> Un seul fragment
  • 63. session sept 2014 Yann Caron (c) 2014 63 layout-land/main_activity <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <fragment android:name="fr.cnam.in01.in01_fragments.MenuFragment" android:layout_height="match_parent" android:layout_width="0dp" android:layout_weight="1" /> <fragment android:name="fr.cnam.in01.in01_fragments.MainFragment" android:layout_height="match_parent" android:layout_width="0dp" android:layout_weight="2" /> </LinearLayout> Plusieurs fragments
  • 64. session sept 2014 Yann Caron (c) 2014 64 Instance du fragment  Dans la méthode onLoad() de l'activity, on a accès à l'instance du/des fragments  Attention, ils peuvent ne pas exister dans le XML, leur référence est null dans ce cas !!  On utilise la méthode Activity.getFragmentManager() MenuFragment fragment = (MenuFragment) getFragmentManager() .findFragmentById(R.id.menu);
  • 65. session sept 2014 Yann Caron (c) 2014 65 Du fragment vers l'activity  Pour que les fragments soient réutilisables, il ne faut pas qu'ils communiquent directement avec l'activity  On utilise une inversion de dépendance  Par exemple un template method (design pattern, peu utilisé dans les IHM)  Ou un observer/observable
  • 66. session sept 2014 Yann Caron (c) 2014 66 Évènements  On définit une interface et un mécanisme d'évènement public class MenuFragment extends Fragment { private MenuChangeEvent menuChanged; public interface MenuChangeEvent { void menuChanger(int id); } public void setOnMenuChange(MenuChangeEvent menuChanged) { this.menuChanged = menuChanged; } private void fireMenuChanged(int id) { if (this.menuChanged != null) { this.menuChanged.menuChanger(id); } } Invertion de dépendance Abonnement
  • 67. session sept 2014 Yann Caron (c) 2014 67 Évènements  Dans l'activity, lorsque le fragment est chargé, on s'abonne à l'évènement menuFragment.setOnMenuChange(new MenuChangeEvent() { @Override public void menuChanger(int id) { switch (id) { case R.id.button1: navigate(MenuFragment.class); break; case R.id.button2: navigate(MainFragment.class); break; } } });
  • 68. session sept 2014 Yann Caron (c) 2014 68 Placeholder  Les fragments peuvent être placés de façon statique dans le XML, comme on l'a vu  Ils peuvent également être chargés dynamiquement (par programmation) dans des placeholders  En général, on utilise des FrameLayout
  • 69. session sept 2014 Yann Caron (c) 2014 69 Placeholder <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <FrameLayout android:id="@+id/placeholder1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> <FrameLayout android:id="@+id/placeholder2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" /> </LinearLayout>
  • 70. session sept 2014 Yann Caron (c) 2014 70 Placeholder  On peut ensuite, charger les fragments à l'aide d'un objet de type FragmentTransaction  La méthode addToBackStack permet de gérer le bouton back (conserve un historique des fragments chargés, comme pour les activities) FragmentTransaction ft = getFragmentManager().beginTransaction(); ft.replace(placeholder, fragment); ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE); ft.addToBackStack(null); ft.commit();
  • 71. session sept 2014 Yann Caron (c) 2014 71 Navigation  Ensuite, selon le nombre de placeholder à disposition, on choisit quel type de navigation l'on souhaite : ➔ Une seule, on peut lancer une nouvelle activity ou remplacer le placeholder 1 ➔ Deux, on peut choisir le placeholder à charger et remplacer le précédent  Le mieux étant de toujours passer le nom de la classe du fragment de façon à l'instancier par introspection Class<? extends Fragment> frClass = MenuFragment.class; Fragment fragment = frClass.newInstance();
  • 72. session sept 2014 Yann Caron (c) 2014 72 Persistance des états du fragment  On l'a vu, les Fragments sont des objets autonomes avec leur cycle de vie propre  L'idée initiale est de décharger l'activity des tâches propres aux sous-éléments graphiques qui se chargent et se déchargent de façon dynamique  De cette façon, il est possible de gérer la sauvegarde des états dans un Bundle  Comme pour les activity, on utilise les évènements du cycle de vie du fragment : onCreateView() et onSaveInstanceState()
  • 73. session sept 2014 Yann Caron (c) 2014 73 Menus  Les fragments apportent leur propre menu lorsqu'ils sont chargés public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setHasOptionsMenu(true); } public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { inflater.inflate(R.menu.fragment_menu, menu); super.onCreateOptionsMenu(menu, inflater); } public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.fragment_menu_item1: // Action 1 return true; default: // Quelqu'un d'autre peut gérer ce menu return super.onOptionsItemSelected(item); } }
  • 74. session sept 2014 Yann Caron (c) 2014 74 Navigation drawer  Un menu qui glisse quand on en a besoin  Source : http://developer.android. com/training/implement ing-navigation/nav- drawer.html
  • 75. session sept 2014 Yann Caron (c) 2014 75 Navigation drawer  Création de l'activity <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/drawer_layout" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:id="@+id/content_frame" android:layout_width="match_parent" android:layout_height="match_parent" /> <ListView android:id="@+id/left_drawer" android:layout_width="240dp" android:layout_height="match_parent" android:layout_gravity="start" android:choiceMode="singleChoice" android:divider="@android:color/transparent"/> </android.support.v4.widget.DrawerLayout> Contenu Menu sous forme de liste
  • 76. session sept 2014 Yann Caron (c) 2014 76 Navigation drawer  Chargement du menu dans l'activity @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView menu = (ListView) findViewById(R.id.menu); String[] menuItems = getResources().getStringArray(R.array.menu_items_array); // Set the adapter for the list view menu.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, menuItems)); // Set the list's click listener menu.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // TODO Auto-generated method stub } }); } Items dans des tableaux res/values Gestion des événements Icône + texte
  • 77. session sept 2014 Yann Caron (c) 2014 77 Navigation drawer  Idéal avec les fragments  Google fournit un ensemble d'icônes  http://developer.android.com/downloads/desi gn/Android_Design_Icons_20130926.zip
  • 78. session sept 2014 Yann Caron (c) 2014 78 Navigation drawer
  • 79. session sept 2014 Yann Caron (c) 2014 79 Conclusion  Les fragments offrent une réelle souplesse dans l'organisation des IHM en fonction des résolutions  Une bonne pratique consiste à toujours concevoir ses IHM selon des fragments, même pour des apps ne nécessitant que peu d'écran  Une navigation plus riche pourra être conçue par la suite  Les composants de l'application bénéficieront également d'une plus grande réutilisabilité
  • 80. session sept 2014 Yann Caron (c) 2014 80 IN01 – Séance 07 Autres Stratégies et alternatives
  • 81. session sept 2014 Yann Caron (c) 2014 81 Stratégie – Choix de l'application  Red Ocean Strategy : ➔ Compléter un marché existant ➔ Exploiter une demande existante ➔ Battre la concurrence  Exemples : Pet rescue, Points and clicks  Avantage : Le marché existe déjà  Inconvénient : Pas d'innovation, pas passionnant
  • 82. session sept 2014 Yann Caron (c) 2014 82 Stratégie – Choix de l'application  Blue Ocean Strategy : ➔ Créer un marché inexploité ➔ Créer ou capter de nouveaux besoins ➔ Pas de concurrence  Exemple : AIDE  Avantages : Avoir une longueur d'avance, être innovant, développement motivant  Difficultés : Identifier le besoin, faire connaitre son application
  • 83. session sept 2014 Yann Caron (c) 2014 83 Dégager du revenu  Android une plateforme où il est difficile de dégager du revenu
  • 84. session sept 2014 Yann Caron (c) 2014 84 Enjeux du multiplateforme  De plus, il existe beaucoup d'applications sur le Play Store (phénomène de flooding, noyade)  Les utilisateurs n'ont pas l'habitude d'acheter sur cette plateforme  Il vaut mieux viser la publicité  Une meilleure stratégie consiste à viser plusieurs plateformes
  • 85. session sept 2014 Yann Caron (c) 2014 85 Enjeux du multiplateforme  Double avantage : ➔ Doubler potentiellement l'audience ➔ Gagner en crédibilité  Inconvénient : ➔ Il faut programmer plusieurs fois la même chose ➔ Dans des langages différents (Java – Objective C)  Ce n'est pas une obligation, des alternatives existent
  • 86. session sept 2014 Yann Caron (c) 2014 86 C++  Un tronc commun, le C++ finalement le langage le plus multiplateforme (Cross- compilation vs Interpretation VM)  Une stratégie : écrire le middleware en C++ et les UI en natif sur les deux plateformes  Inconvénients : compliqué, difficile à mettre en place (database ?, bibliothèque ?)
  • 87. session sept 2014 Yann Caron (c) 2014 87 C++/Qt  Une alternative : Qt 5.2  La version 5 annonçait les prémices, la 5.2 officialise le portage iOS et Android  Une UI non native, mais complètement portable (la force de Qt)  C++ plus rapide que Java  Pas de Garbage collector  On peut faire des jeux  Exemple : FlyingBus de Digia
  • 88. session sept 2014 Yann Caron (c) 2014 88 Xaramin/Mono  Mono est une implémentation de la plateforme .net sur UNIX  Xaramin est une startup des créateurs de Mono pour viser les plateformes mobiles  Solution payante (démo puis 299 $/année)  Mais un gain de temps  Et C# est vraiment un langage puissant ➔ Objet/Fonctionnel (Linq) ➔ Nombreux sucres syntaxiques : propriétés, évènements, lambdas, extension méthods ➔ Un framework riche : Reflexion, Emit, LightWeight AOP (LinFu)
  • 89. session sept 2014 Yann Caron (c) 2014 89 Xaramin  Un IDE multiplateforme (Win, MacOS), mais pas Linux
  • 90. session sept 2014 Yann Caron (c) 2014 90 RobotVM  RobotVM compile le bytecode Java en Assembleur à destination des processeurs ARM ou X86  Bridge avec les API Objective C comme CocoaTouch  Open source (GPLv2)  Support Eclipse (plugin) et Maven  Stratégie : développement en couche, middleware commun en Java et deux applications UI natives  Le langage AL et JASI (le parser) fonctionnent
  • 91. session sept 2014 Yann Caron (c) 2014 91 JavaFX  Expérimental  Utilisation de l'OpenJFX 8, projet non officiel : https://bitbucket.org/javafxports/android/wiki/Home  Utilisation de RobotVM pour viser iOS  Il existe même un plugin NetBeans
  • 92. session sept 2014 Yann Caron (c) 2014 92 IN01 – Séance 07 Autres Jeux Vidéo Mobiles
  • 93. session sept 2014 Yann Caron (c) 2014 93 Parts de marché  Le jeu vidéo mobile progresse de façon spectaculaire sur le marché Source : Flurry Analytics (un concurrent de Google Analytics)
  • 94. session sept 2014 Yann Caron (c) 2014 94 Game engines  AndEngine : ➔ 2D – OpenGL ES - Physic ➔ Android ➔ Java based – simple d'utilisation ➔ Gratuit et Open Source  JmonkeyEngine : ➔ 3D – OpenGL ES ➔ Java based ➔ Open Source free BSD
  • 95. session sept 2014 Yann Caron (c) 2014 95 Multiplateforme - Java  LibGDX : ➔ 2D / 3D – OpenGL ES – Physics ➔ Multiplateforme (Android, iOS, Sybian, Win, Linux, MacOS, html 5) ➔ RobotVM ©  cross compilation ➔ Java ➔ Open source
  • 96. session sept 2014 Yann Caron (c) 2014 96 OpenFl  OpenFl : ➔ 2d uniquement ➔ massivement multiplateforme ➔ Fonctionne sur le langage Haxe (multiparadigme)  Créé par un Français ➔ Sur une VM NekoVM dont l'intermediate language est un langage de script (et pas du byteCode) ➔ Initialement inspiré par Flash
  • 97. session sept 2014 Yann Caron (c) 2014 97 NoJava – Alternative 2D  Sencyl : ➔ 2D, multiplateforme (iOS, Android, Flash, etc.) ➔ Basé sur OpenFl ➔ NoCode - Payant
  • 98. session sept 2014 Yann Caron (c) 2014 98 No Java – Alternative 3D  Unity 3D : ➔ 2D / 3D ➔ WYSIWYG Lua scripting ➔ Payant
  • 99. session sept 2014 Yann Caron (c) 2014 99 NoJava – Alternative 3D  ShiVa 3D : ➔ 3D multiplateforme ➔ WYSIWYD – Lua scripting ➔ Server MMO ➔ Gratuit
  • 100. session sept 2014 Yann Caron (c) 2014 100 Fin  Merci de votre attention  Des questions ?