1 Android (Avec Android Studio) -...
-
Upload
nguyenxuyen -
Category
Documents
-
view
255 -
download
0
Transcript of 1 Android (Avec Android Studio) -...
1
Android (Avec Android Studio) J. ROMAGNY
I. BASES DE JAVA......................................................................................................................................... 3
1. VARIABLES ..................................................................................................................................................... 3 2. CONDITIONS .................................................................................................................................................. 3 3. BOUCLES ....................................................................................................................................................... 4 4. ENUM ........................................................................................................................................................... 4 5. COLLECTIONS ................................................................................................................................................. 5
a. Tableaux ................................................................................................................................................ 5 b. Liste ........................................................................................................................................................ 5 c. Map ....................................................................................................................................................... 5
6. METHODES ET FONCTIONS ................................................................................................................................ 5 7. OBJETS ......................................................................................................................................................... 6
II. ANDROID ................................................................................................................................................. 8
1. INSTALLATION (WINDOWS) ............................................................................................................................... 8 a. Installation du JDK ................................................................................................................................. 8 b. Android Studio ....................................................................................................................................... 8 c. Problèmes et astuces ........................................................................................................................... 10 d. AVD Manager ...................................................................................................................................... 11 e. Divers ................................................................................................................................................... 12
2.CREER UN NOUVEAU PROJET ANDROID .................................................................................................................... 12 3. ACTIVITES (« ACTIVITY ») ............................................................................................................................... 15
a. Créer une activité ................................................................................................................................. 17 b. Passer des données (Extra) .................................................................................................................. 19 c. Activité avec retour de résultat (« startActivityForResult ») ................................................................ 19 d. Menu .................................................................................................................................................... 20
Création du menu ...................................................................................................................................................... 20 Intercepter le clic sur un élément du menu ............................................................................................................... 20 Créer un eventHandler pour un élément de menu .................................................................................................... 21 Créer un élément de menu par code ......................................................................................................................... 21 Avoir le bouton de « retour » .................................................................................................................................... 21 Menu avec images ..................................................................................................................................................... 22 Menu contextuel........................................................................................................................................................ 22
4. LAYOUTS (« VIEWGROUP ») ................................................................................................................................ 23 a. Designer .................................................................................................................................................... 23 b. Propriétés « partagées » .......................................................................................................................... 24
Tailles ......................................................................................................................................................................... 24 Weight ....................................................................................................................................................................... 24 « wrap_content », « fill_parent » .............................................................................................................................. 24 Gravity et « layout_gravity » ...................................................................................................................................... 25
c. LinearLayout ........................................................................................................................................ 26 d. RelativeLayout ..................................................................................................................................... 26 e. GridLayout ........................................................................................................................................... 27 f. TableLayout ......................................................................................................................................... 28 g. Include ................................................................................................................................................. 29 h. Custom View et composant ................................................................................................................. 30
Custom View .............................................................................................................................................................. 30 Custom composant (classe + layout) ......................................................................................................................... 31
Balise « merge » .................................................................................................................................................... 32
2
i. Fragments ............................................................................................................................................ 33 5. WIDGETS .................................................................................................................................................... 36
a. Accéder à un widget (findViewById) .................................................................................................... 36 b. Utilisation « ImageView » .................................................................................................................... 36
6. VIEW EVENTS ............................................................................................................................................... 37 7. « ARRAYADAPTER » ...................................................................................................................................... 38
a. avec ListActivity ................................................................................................................................... 38 b. Avec ActionBarActivity ......................................................................................................................... 39 c. Personnalisé ......................................................................................................................................... 40
8. CYCLE DE VIE D’ACTIVITE ................................................................................................................................. 42 Sauver/ restaurer les états de contrôles d’une activité ................................................................................ 42
9. RESSOURCES ................................................................................................................................................ 43 10. PREFERENCES PARTAGEES ........................................................................................................................... 45
« PreferenceActivity » ................................................................................................................................... 45 11. FICHIERS ................................................................................................................................................. 47
XML ............................................................................................................................................................... 47 JSON.............................................................................................................................................................. 48
12. SQLITE ................................................................................................................................................... 49 13. HTTP ..................................................................................................................................................... 51
a. AsyncTask ............................................................................................................................................ 51 b. Tester la connexion .............................................................................................................................. 52 c. Avec « HttpURLConnection » ............................................................................................................... 53 d. Parser une réponse au format JSON .................................................................................................... 54 e. POST + passage de paramètre au format JSON ................................................................................... 55 f. Libraires ............................................................................................................................................... 55
14. TOASTS ................................................................................................................................................... 56 15. NOTIFICATIONS ........................................................................................................................................ 56 16. SERVICE ET INTENTSERVICE ......................................................................................................................... 59
a. Service .................................................................................................................................................. 59 b. IntentService ........................................................................................................................................ 60
17. « BROADCAST RECEIVER » ......................................................................................................................... 61 « Dynamic Broadcast Receiver» ................................................................................................................... 61
3
I. Bases de Java IDE : Intellij IDEA , Eclipse
1. Variables Typés primitifs : int, float, double, char, boolean, string (+ byte, short, long)
int myInt =10;
float myFloat = 9.99f;
double myDouble = 9.99;
boolean myBool = true;
String myString = "Bonjour!";
Afficher la sortie System.out.println(myInt);
System.out.println(myString);
// ...
2. Conditions if
int myInt = 10;
if(myInt > 10){
} else if (myInt == 10) {
} else {
}
Opérateur ternaire
int myInt =10;
boolean result = (myInt > 10) ? true : false;
Switch
int myInt = 10;
switch (myInt)
{
case 0 :
// ...
break;
default :
break;
}
4
3. Boucles While
int index = 1;
while(index < 10)
{
index++;
}
For
for (int i = 0; i < 10; i++) {
}
« For each »
int[] myArray = new int[]{1,2,3}; for (int i:myArray) { }
4. Enum public enum myEnum{
One,
Two,
Three
}
Utilisation
myEnum myValue = myEnum.Two;
if(myValue ==myEnum.Two){
}
5
5. Collections
a. Tableaux int[] myArray = new int[3];
Ou
int[] myArray = new int[]{1,2,3}; Accès aux éléments
myArray[1] = 20;
Parcours
for (int i:myArray) {
}
b. Liste import java.util.List;
import java.util.ArrayList;
List<Person> people = new ArrayList<Person>();
people.add(new Person("Jerome","[email protected]"));
people.add(new Person("Marie","[email protected]"));
for (Person person:people){
System.out.println(person.name);
}
c. Map import java.util.HashMap;
Map<Integer,String> myMap = new HashMap<Integer,String>();
myMap.put(10,"ma valeur 1");
myMap.put(20,"ma valeur 2");
String value = myMap.get(20);
6. Méthodes et fonctions public void myMethod(String name){
}
Appel
myMethod("Jerome");
« static »
public static String myMethod(String name){
String message = "Bonjour " + name + "!";
return message;
}
6
7. Objets Menu « File »… « New »… « Java class »
public class Person {
public String name;
private String email;
public Person(String name, String email){
this.name = name;
this.email = email;
}
public void sayHello(){
System.out.println("Bonjour " + name + "!");
}
}
Utilisation
Person marie = new Person("Marie", "[email protected]");
marie.sayHello();
Héritage
Créer une nouvelle classe..
public class Member extends Person{
public Member(String name, String email){
super(name,email);
}
@Override
public void sayHello() {
System.out.println("Bonjour " + name + ", bienvenue !");
}
}
Utilisation
Member jerome = new Member("Jerome","[email protected]");
jerome.sayHello();
On réécrit la méthode de la
classe de base
Appel du constructeur de
la classe de base
Hérite de « Person »
7
Interface
Création d’une interface . Plusieurs possibilités :
- Menu « File » .. « New » … « Java class » … puis sélectionner « Interface » dans la boite de dialogue
- Refactor : Depuis la classe pour laquelle créer une interface … Menu « Refactor » …
« Extract » … « Interface »
public interface IPerson {
void sayHello();
}
La classe implémentant l’interface
public class Person implements IPerson {
// etc.
@Override
public void sayHello(){
}
}
8
II. Android Documentation
1. Installation (Windows)
a. Installation du JDK 1. Télécharger, installer Java SE Development Kit 2. Variables d’environnement
Ajouter :
« JAVA_HOME » sur « C:\Program Files\Java\jdk1.8.0_45 »
Et « Path » sur « C:\Program Files\Java\jdk1.8.0_45\bin »
Vérifier que l’installation est correcte. Depuis une invite de commande (« cmd ») …
b. Android Studio 1. Télécharger et installer Android SDK et Android Studio
On peut changer le chemin
d’installation du SDK si on veut
pouvoir y accéder facilement
9
2. SDK Manager
Depuis l’écran d’accueil … « configure » … »SDK Manager »
Cocher selon les
besoins
HAXM
10
c. Problèmes et astuces
Recommandations : switch vers (« Android M Preview » faisant bugger le
designer)
Erreur : «the following class could not be found… android.support.v7.internal.widget.actionbaroverlaylayout »
Remplacer le thème par
<style name="AppTheme" parent="Base.Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
</style>
Erreur « app:compileDebugAidl » … dans « Build.gradle » changer
HAXM
Le pc doit supporter la virtualisation mais ne surtout pas activer Hyper-V si on est sous
Windows. Installer HAXM depuis SDK Manager ( « extras ») puis aller dans le dossier du SDK …
Intel… « Hardware_Accelerated_Execution_Manager » … exécuter « intelhaxm-android.exe ».
Avoir une « ActionBar » avec une activité « ListActivity » … Changer le thème
<style name="AppTheme"
parent="@android:style/Theme.DeviceDefault.Light.DarkActionBar"></style>
Probème des chaines de caractères « UTF-8 ». Dans « build.gradle », ajouter …
android {
compileOptions.encoding = 'ISO-8859-1'
Raccourcis utiles
Emulateur
CTRL + F12 (changer orientation de l’émulateur)
Android Studio
ALT + ENTREE pour résoudre les problèmes (imports manquants, etc.)
Commentaires : Ctrl + « / » ou Ctrl + MAJ + « / » (sur plusieurs lignes)
Utiliser les menus « Code » et « Refactor ». Exemple permet de reformater le code et
générer du code (constucteurs, getter/setter, etc.)
Debug
F7 « step into »
F8 « step over »
11
d. AVD Manager Menu « Tools » … « Android » … « AVD Manager »
Tester une application : Appuyer sur le bouton raccourci puis sélectionner un émulateur ouvert ou en lancer un
Il est possible de lancer plusieurs émulateurs en même temps (exemple un pour téléphone et un
autre pour tablette)
Créé par défaut
12
Raccourcis utiles : CTRL + F12 (changer orientation de l’émulateur)
Si l’application ne se lance pas … « swap » ou aller dans les applications
e. Divers AppInventor permet de développer des applications (et jeux) pour Android sans taper une ligne
de code (ne marche qu’avec Chrome et Firefox).
On a une partie Designer et une partie Blocks permettant de définir la logique de l’application.
2.Créer un nouveau projet Android L’écran d’accueil d’Android Studio
15
3. Activités (« Activity »)
« Navigation » entre activités
Vue « ANDROID »
« Action bar »
Menu (dossier « res\menu »)
« Layout « (dossier « res\layout »)
Intent : passage de paramètres possible
startActivity ou startActivityForResult (retour de « résultat »)
Activités (code JAVA), etc.
Layouts (UI des activités) éditables avec le
Designer
Menus et menus contextuels. Un menu
possible par activité
strings : chaines de caractères
dimens : dimensions (dp)
styles : styles des contrôles, thèmes
etc.
Ressources
Manifest contenant la liste des activités et
un filtre pour l’activité de départ
Images
16
Exemple de code « vide » d’activité
package com.romagny13.androiddemo;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
On définit le layout (xml) de l’activité avec
la méthode « setContentView »
17
a. Créer une activité 1. Menu « File » … « New » … « Activity » … puis « Blank Activity » par exemple
2. Lancer la seconde activité (depuis l’activité de départ)
import android.content.Intent;
On ajoute un bouton et un événement sur le click du bouton
public void startSecondActivity(View view) {
Intent intent = new Intent(this,SecondActivity.class);
startActivity(intent);
}
3. Fermer la seconde activité
On ajoute par exemple un bouton à la seconde activité et un event click
public void closeActivity(View view) {
finish();
}
18
4. Manifest
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.romagny13.androiddemo" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".SecondActivity"
android:label="@string/title_activity_second" >
</activity>
</application>
</manifest>
Filtre indiquant que
c’est l’activité de
départ Une
activité
Une
autre
activité
19
b. Passer des données (Extra) public static final String MY_MESSAGE = "MY_MESSAGE!" ;
…
public void startSecondActivity(View view) {
Intent intent = new Intent(this,SecondActivity.class);
intent.putExtra(MY_MESSAGE,"Bonjour!");
startActivity(intent);
}
Récupérer les données passées dans la seconde activité
public class SecondActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
String received_message = getIntent().getStringExtra(MainActivity.MY_MESSAGE);
}
// etc.
c. Activité avec retour de résultat (« startActivityForResult ») Activité de départ
static final int SECOND_ACTIVITY_REQUEST_CODE = 1000 ;
public void startSecondActivity(View view) {
Intent intent = new Intent(this,SecondActivity.class);
startActivityForResult(intent,SECOND_ACTIVITY_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent
data) {
if(requestCode == SECOND_ACTIVITY_REQUEST_CODE){
if(resultCode == RESULT_OK){
String name = data.getStringExtra("name");
// etc.
}
}
}
Seconde activité
public void closeActivity(View view) {
handleDone();
finish();
}
private void handleDone(){
EditText nameText = (EditText) findViewById(R.id.editText);
String name = nameText.getText().toString();
Intent intent = new Intent();
intent.putExtra("name",name);
setResult(RESULT_OK,intent);
}
Récupération dans « onCreate ». On peut
ensuite faire ce que l’on veut, l’afficher
dans une TextView par exemple
Utilisation de la méthode
« startActivityForResult »
Méthode appelée au
retour
Code de succès, on pourrrait
aussi utiliser RESULT_CANCELED
On teste si le code de résultat
est OK et on récupère les
données passées
20
d. Menu Chaque activité peut avoir ou non un menu.
Création du menu
Un menu (fichier *.xml) est automatiquement ajouté lors de la création d’une activité.
On peut toutefois en ajouter … sur le dossier « menu »… « New »… « Menu Resource File »
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/action_showSecondActivity"
android:title="Deuxième activité"
app:showAsAction="always" />
<item
android:id="@+id/action_close"
android:title="Quitter"
app:showAsAction="always" />
</menu>
Intercepter le clic sur un élément du menu
(Dans le code de l’activité)
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_showSecondActivity) {
startSecondActivity();
return true;
}
if (id == R.id.action_close) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
« Always » élément de menu
toujours visible, sinon il faut
appuyer sur le bouton
« Hamburger » pour le faire
apparaitre
On pourrait aussi utiliser
un « Switch »
21
Créer un eventHandler pour un élément de menu
Il est possible également de créer un « eventHandler » pour le clic sur un élément de menu
(Menu *.xml)
<item
android:id="@+id/action_close"
android:title="Quitter"
app:showAsAction="always"
android:onClick="exitApp"/>
(Activité correspondante)
public void exitApp(MenuItem item) {
}
Créer un élément de menu par code
Dans le code de l’activité
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
MenuItem item = menu.add(Menu.NONE,Menu.NONE,103,"Nouveau menu ...");
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
return true;
}
Avoir le bouton de « retour »
Dans le manifest
<activity
android:name=".SecondActivity"
android:label="@string/title_activity_second"
android:parentActivityName=".MainActivity">
Par code
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
On définit le nom de
l’activité parente
22
Menu avec images <item
android:id="@+id/action_youtube"
android:icon="@drawable/youtube"
android:title="Youtube"
app:showAsAction="always" />
Menu contextuel
1. On ajoute un nouveau menu (*.xml) au dossier « menu »
Sur le dossier « menu » … Menu « New » … « menu Resource File » <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:id="@+id/group1">
<item android:id="@+id/item1" android:title="Option 1"></item>
<item android:id="@+id/item2" android:title="Option 2"></item>
</group>
</menu>
2. Code de l’activité @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button2);
registerForContextMenu(button);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo
menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
getMenuInflater().inflate(R.menu.my_context_menu, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Boolean result= true;
int id = item.getItemId();
switch (id)
{
case R.id.item1:
// do something
break;
case R.id.item2:
break;
default: result = super.onContextItemSelected(item);
}
return result;
}
Quand on clique sur le bouton
cela ouvre le menu contextuel
Quand on clique sur les
éléments du menu
contextuel
23
4. Layouts (« ViewGroup »)
a. Designer
Vue « Design » et « Text » (xml) Designer Propriétés de
l’élément sélectionné
Vue en « arbre »
des composants
Composants « glissables »
sur l’interface
Permet d’avoir des
prévisualisations à
différentes résolutions
Version du device
dans l’aperçu
Changer
l’orientation
Changer le thème Permet de switch
directement vers le code
java de l’activité
API Version
Permet de mettre en forme
l’élément sélectionné
(« wrap_content », etc.)
Zoom
24
Différents layouts
LinearLayout : alignement horizontal ou vertical des éléments
RelativeLayout : éléments positionnés les uns par rapport aux autres
GridLayout (seulement à partir API Level 14)
FrameLayout : pour n’afficher qu’un élément
TableLayout
b. Propriétés « partagées »
Tailles
- « dp » (« ratio », exemple 1dp = 1px sur un écran à 160px)
- et « sp » pour la taille des fonts
Weight
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Un" />
<Button
android:id="@+id/button4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4"
android:text="Deux" />
« wrap_content », « fill_parent »
On peut régler la hauteur et la largeur :
- « fill_parent » occupe toute l’espace disponible
- (« match_parent » presque comme fill_parent) - « wrap_content » n’occupe que l’espace nécessaire au contenu
Bouton de poids « 4 » occupera 80% de
l’espace total du parent
1 + 4 = 5 (100%)
25
Gravity et « layout_gravity »
Appliqué au contrôle (TextView par exemple) : centre le contenu
<TextView
android:id="@+id/textView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Mon texte"
android:textAppearance="?android:attr/textAppearanceLarge" />
« layout_gravity » appliqué au contrôle par rapport à son parent
(Avec orientation « verticale » pour le conteneur « LinearLayout »)
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Mon texte"
android:textAppearance="?android:attr/textAppearanceLarge" />
« fill_parent » sur la
hauteur et largeur de
la TextView
« wrap_content » sur
la hauteur et largeur de
la TextView
26
c. LinearLayout Eléments disposés sur une ligne horizontalement ou verticalement
Exemple
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal">
</LinearLayout>
Exemple de conteneur de base
<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="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.romagny13.androiddemo.ThirdActivity">
</LinearLayout>
d. RelativeLayout Eléments placés les uns par rapport aux autres.
Par défaut les éléments sont placés en haut à gauche.
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nom" />
<EditText
android:id="@+id/editText1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/textView1" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/editText1"
android:text="OK" />
Orientation « horizontal » par défaut
« layout_toRightOf » de la TextView
« layout_below » de l’EditText
27
A cela on peut ajouter : les propriétés d’alignement, « alignBaseligne » (pour aligner le texte), la
visibilié (« visibility » et « alignWithParentIfMissing »), les marges
Le designer offre des aides pour bien placer les éléments
e. GridLayout Même exemple que précédemment avec une grille (à partir API Level 14).
<GridLayout 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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.romagny13.androiddemo.ThirdActivity"
android:columnCount="2"
android:rowCount="2">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nom" />
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/editText1"
android:layout_row="0"
android:layout_column="1" />
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_row="1"
android:layout_column="0"
android:layout_columnSpan="2"
android:text="OK" />
</GridLayout>
La grille a 2 colonnes et
2 lignes
Placement dans la grille.
L’index commence à 0
« ColumnSpan »
28
f. TableLayout
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Nom" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ems="10" >
<requestFocus />
</EditText>
</TableRow>
<View android:layout_height="2dip" android:background="#000000"/>
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</TableRow>
</TableLayout>
29
g. Include Création d’un layout (exemple « youtube.xaml » dans le dossier « layouts » affiche une image)
<?xml version="1.0" encoding="utf-8"?>
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/youtube" />
Utilisation (dans le layout par ex de l’activité principale)
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<!-- etc. -->
<include layout="@layout/youtube"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true" />
</RelativeLayout>
On pourrait également utiliser « ViewStub » pour gérer la visibilité
Propriété « layout » pointe sur le
layout créé, on peut également
réglé le positionnement
30
h. Custom View et composant
Custom View
Exemple avec une « custom TextView ».
1. On crée une classe héritant de la View désirée (dans l’exemple « TextView »)
public class CustomTextView extends TextView {
public CustomTextView(Context context) {
super(context);
init();
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
this.setText("Bonjour!");
this.setBackgroundColor(Color.DKGRAY);
this.setTextColor(Color.WHITE);
}
}
2. Utilisation
En code, exemple on définit le contenu d’une activité
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomTextView view = new CustomTextView(this);
setContentView(view);
}
XML (à préférer car cela permet d’avoir accès à toutes les propriétés depuis le Xml)
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<!-- etc. -->
<com.romagny13.androiddemo.CustomTextView
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
31
Custom composant (classe + layout)
On définit composant comprenant par exemple une boite de texte (EditText) et un bouton.
Lorsque l’utilisateur clique sur le bouton, un toast « bonjour …» apparait.
1. layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4"
android:inputType="textPersonName"
android:text="Name" />
<Button
android:id="@+id/okButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Go" />
</LinearLayout>
2. classe
public class CustomCompound extends LinearLayout {
private EditText nameText;
private Button okButton;
public CustomCompound(Context context) {
super(context);
init();
}
public CustomCompound(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomCompound(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.custom_compound,this);
nameText = (EditText) findViewById(R.id.nameText);
okButton = (Button) findViewById(R.id.okButton);
okButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
String message = "Bonjour " + nameText.getText() + "!";
Toast.makeText(getContext(), message, Toast.LENGTH_LONG).show();
}
});
}
}
On pourrait utiliser le tag
« Merge »
32
3. Utilisation
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<!-- etc. -->
<com.romagny13.androiddemo.CustomCompound
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/imageView2">
</com.romagny13.androiddemo.CustomCompound>
</RelativeLayout>
Balise « merge »
Permet d’éviter d’avoir une « imbrication » de plusieurs « LinearLayout »
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<EditText
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="4"
android:inputType="textPersonName"
android:text="Name" />
<Button
android:id="@+id/okButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Go" />
</merge>
Si on avait besoin de définir l’orientation on le ferait dans le code
public class CustomCompound extends LinearLayout {
// etc.
private void init(){
LayoutInflater inflater = LayoutInflater.from(getContext());
inflater.inflate(R.layout.custom_compound,this);
setOrientation(LinearLayout.HORIZONTAL);
}
}
33
i. Fragments 1. Créer le « layout » (xml) du fragment
Sur le dossier « layouts » … Menu « New » … « Layout Resource File ». Commencer le nom du
fragment par « fragment_ »
Définition du contenu du fragment
2. Créer la classe (java) du fragment
Menu « File » … « New » … « Java class »
public class MyFragment extends Fragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_my_fragment, container,false);
return view;
}
}
3. Ajouter un fragment à une activité
XML
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<fragment
android:id="@+id/my_fragment"
android:name="com.romagny13.fragmentdemo.MyFragment"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:layout="@layout/fragment_my_fragment" />
</RelativeLayout>
Donner un id, un nom,…
On définit le contenu (le layout du fragment)
34
Ou en code
Ne pas oublier de donner un id au layout « conteneur » (ici pour « activity_main.xml »)
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/my_container"
…
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction()
.add(R.id.my_container, new MyFragment())
.commit();
}
}
// etc.
Communication entre fragments d’une même activité
Créer une interface : Menu « File » … « New » … « Java class » … puis sélectionner « Interface »
public interface OnPersonSelectionChangeListener {
public void onPersonSelectionChanged(int index);
}
Déclenchement au changement d’élément sélectionné
public class PeopleListFragment extends ListFragment {
private PeopleData peopleData = new PeopleData();
// etc.
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
List<String> people = peopleData.getPeopleNames();
ArrayAdapter<String> adapter =
new ArrayAdapter(getActivity(),android.R.layout.simple_list_item_1, people);
setListAdapter(adapter);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
OnPersonSelectionChangeListener listener =
(OnPersonSelectionChangeListener) getActivity();
listener.onPersonSelectionChanged(position);
}
}
Ajout d’une instance du fragment
au conteneur
35
Activité
public class MainActivity extends ActionBarActivity
implements OnPersonSelectionChangeListener{
// etc.
@Override
public void onPersonSelectionChanged(int index) {
FragmentManager manager = getFragmentManager();
PersonDetailsFragment fragment =
(PersonDetailsFragment) manager.findFragmentById(R.id.fragment_person_details);
fragment.setPerson(index);
}
}
Fragment « abonné »
public class PersonDetailsFragment extends Fragment {
private PeopleData peopleData = new PeopleData();
// etc.
public void setPerson(int index){
Person person = peopleData.getOne(index);
TextView textView =(TextView) getView().findViewById(R.id.nameText);
textView.setText(person.name);
}
}
36
5. Widgets
Les Widgets dérivent de la classe de base View Méthodes findViewById, getRootView
TextView (Label)
Button (sous classe de TextView) ImageView
EditText (champ de saisie)
o andoid :autoText (correction automatique active ou non)
o andoid :capitalize (Majuscule première lettre)
o andoid :digits (inique si le champ n’accepte que certains chiffres)
o andoid :singleLine (une seule ligne)
o Méthodes setText,getText
CheckBox
o andoid :isChecked
o Méthodes setChecked et toggle (inverse l’état de la case)
RadioButton (dans un RadioGroup)
o Méthodes check(), clearCheck(), getCheckedRadionButtonId()
Etc.
a. Accéder à un widget (findViewById) Button button = (Button) findViewById(R.id.button1);
b. Utilisation « ImageView » Copier d’images dans le dossier « drawable »
Utilisation de la ressource : on définit la propriété « src » (par code ou depuis le panneau
propriétés du Designer)
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:src="@drawable/twitter"
android:layout_below="@+id/checkBox1"
android:layout_centerHorizontal="true" />
Par code
int resource = getResources().getIdentifier("youtube","drawable",getPackageName());
ImageView imageView = (ImageView) findViewById(R.id.imageView2);
imageView.setImageResource(resource);
37
6. View Events
public class MainActivity extends ActionBarActivity implements View.OnClickListener{
// etc.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button2);
button.setOnClickListener(this);
}
@Override
public void onClick(View v) {
}
Ou plus simplement
Button button = (Button) findViewById(R.id.button2);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
}
});
38
7. « ArrayAdapter »
a. avec ListActivity Exemple « ArrayAdapter »
<RelativeLayout
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ListView
android:id="@android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></ListView>
</RelativeLayout>
public class MainActivity extends ListActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
String[] fruits = new String[]{"Pomme","Poire","Banane"};
ArrayAdapter<String> adapter =
new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, fruits);
setListAdapter(adapter);
}
On ajoute une
« ListView » dans le
layout de l’activité.
Attention à l’id
L’activité hérite de « ListActivity »
Contexte (« this »)
39
Autre exemple
List<Person> people = peopleService.getAll();
ArrayAdapter<Person> adapter =
new ArrayAdapter<Person>(this,android.R.layout.simple_list_item_1, people);
setListAdapter(adapter);
public class Person {
private String name;
// etc.
@Override
public String toString() {
return name;
}
}
b. Avec ActionBarActivity On pourrait également ajouter une « ListView » à une activité de « base »
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Person> people = peopleService.getAll();
ArrayAdapter<Person> adapter =
new ArrayAdapter<Person>(this,android.R.layout.simple_list_item_1, people);
ListView list = (ListView) findViewById(android.R.id.list);
list.setAdapter(adapter);
}
// etc.
La listView affichera le nom de chaque
personne
On récupère la ListView du layout et on définit l’ « adapter »
40
c. Personnalisé
1. On crée un layout (« person_item » par ex)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp">
<ImageView
android:id="@+id/imageView"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_weight="1" />
<TextView
android:id="@+id/nameText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/imageView"
android:layout_toRightOf="@+id/imageView"
android:layout_weight="3" />
<ImageButton
android:id="@+id/deleteButton"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_toEndOf="@+id/nameText"
android:layout_toRightOf="@+id/nameText"
android:src="@drawable/close"
android:scaleType="fitCenter"/>
</LinearLayout>
Chaque élément aura une
image, un texte et un
bouton « delete »
41
2. On crée une classe pour l’adapter personnalisé
public class PeopleArrayAdapter extends ArrayAdapter<Person> {
Context context;
List<Person> objects;
PeopleRepository peopleRepository;
public PeopleArrayAdapter(Context context, int resource, List<Person> objects) {
super(context, resource, objects);
this.context = context;
this.objects = objects;
peopleRepository = new PeopleRepository(context);
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.person_item, null);
Person person = objects.get(position);
ImageView imageView = (ImageView) view.findViewById(R.id.imageView);
TextView nameText = (TextView) view.findViewById(R.id.nameText);
ImageButton deleteButton = (ImageButton) view.findViewById(R.id.deleteButton);
int id =
context.getResources().getIdentifier("avatar1", "drawable", context.getPackageName());
imageView.setImageResource(id);
nameText.setText(person.getName());
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Person person = objects.get(position);
peopleRepository.open();
int result = peopleRepository.delete(person);
if (result == 1) {
objects.remove(position);
notifyDataSetChanged();
}
}
});
return view;
}
3. Utilisation
ArrayAdapter<Person> adapter = new PeopleArrayAdapter(this,0, people);
On définit la
vue
On « remplit » les
contrôles
Gestion du clic sur
le bouton
suprrimer
42
8. Cycle de vie d’activité Lancement de l’activité … onCreate…onStart…onResume…onPause…onStop…onDestroy
On peut suivre le cycle de vie d’une activité par exemple (dans « MainActivity »)
@Override
protected void onStart() {
super.onStart();
Log.i("MainActivity","onStart");
}
@Override
protected void onResume() {
super.onResume();
Log.i("MainActivity", "onResume");
}
@Override
protected void onPause() {
super.onPause();
Log.i("MainActivity", "onStart");
}
@Override
protected void onStop() {
super.onStop();
Log.i("MainActivity", "onStop");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i("MainActivity", "onDestroy");
}
Sauver/ restaurer les états de contrôles d’une activité Par exemple on ajoute une case à cocher et on sauvegarde son état (coché ?)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState != null) {
restoreState(savedInstanceState);
}
}
private void restoreState(Bundle savedInstanceState) {
boolean isChecked = savedInstanceState.getBoolean("checkBox1Checked");
CheckBox checkBox = (CheckBox) findViewById(R.id.checkBox1);
checkBox.setChecked(isChecked);
}
@Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
super.onSaveInstanceState(outState, outPersistentState);
CheckBox checkBox = (CheckBox) findViewById(R.id.checkBox1);
outState.putBoolean("checkBox1Checked", checkBox.isChecked());
}
Sauvegarde clé et
valeur
Récupération de la
valeur sauvegardée et
Restauration de l’état
On pourrait créer des
constantes
43
9. Ressources Dossier « res » : toutes les ressources … accessibles avec « R » (classe générée).
o res/drawable : images (PNG, JPEG et GIF)
o res/layout : interfaces utilisateurs
o res/values :
string.xml : chaines de caractères
dimens.xml : dimensions (dp, sp)
arrays.xml définit les tableaux
o res/xml : fichiers xml supplémentaires (préférences, etc.)
o res/menu : menus
o res/raw ressources empaquetées sans aucun traitement
o assets : ressources « brutes » accessibles par un flux de données
o Styles
Ajout d’une ressource (« strings.xml ») … avec le Refactor
44
« strings.xml »
<resources>
<!-- etc. -->
<string name="my_title">Activité de départ</string>
</resources>
Il serait bien sur possible d’ajouter les ressources « à la main ».
Utilisation de la ressource
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/my_title" />
Par code … R.string.my_title
On accède aux ressources par l’intermédiaire du fichier R généré (documentation)
45
10. Préférences partagées Sauvegarder de préférences
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor editor = preferences.edit();
editor.putString("MyPreference", "ma valeur de préférence");
// autres variables
editor.commit();
Ou
SharedPreferences preferences = getPreferences(MODE_PRIVATE); // etc.
Retrouver des préférences
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
String myPreference = preferences.getString("MyPreference",null);
if(myPreference!=null){
// utilisation
}
« PreferenceActivity » On peut également créer une activité dédiée aux préférences. Menu « File » … « New » …
« Activity » … « Settings Activity »
On lance l’activité au clic sur un élément de menu
Intent intent = new Intent(this,SettingsActivity.class);
startActivity(intent);
… On peut également ajouter les éléments un par un… sur le dossier « xml » … « New » … « Xml
Resource File »
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="General settings" >
<EditTextPreference
android:key="pref_email"
android:title="Email" />
</PreferenceCategory>
</PreferenceScreen>
Préférences de l’activité
uniquement et « private »
accessible qu’à l’application
Préférences partagées
46
Ajout d’une activité nommée « SettingsActivity » par ex
public class SettingsActivity extends PreferenceActivity {
@Override
public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
super.onCreate(savedInstanceState, persistentState);
addPreferencesFromResource(R.xml.settings);
}
}
Ajouter l’activité au Manifest
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<!-- ect -->
<activity
android:name=".SettingsActivity"
android:label="Préférences" >
</activity>
</application>
Et on lance l’activité comme précédemment depuis le menu de l’activité de départ
Retrouver la préférence
SharedPreferences preferences =
PreferenceManager.getDefaultSharedPreferences(this);
String prefEmail = preferences.getString("pref_email", "Non trouvé");
47
11. Fichiers private void saveFile(String text, String fileName) throws IOException {
FileOutputStream fos = openFileOutput(fileName, MODE_PRIVATE);
fos.write(text.getBytes());
fos.close();
}
private String readFile(String fileName) throws IOException {
FileInputStream fis = openFileInput(fileName);
BufferedInputStream bis = new BufferedInputStream(fis);
StringBuffer result = new StringBuffer();
while (bis.available() != 0) {
char c = (char) bis.read();
result.append(c);
}
bis.close();
fis.close();
return result.toString();
}
Utilisation au clic sur boutons
public void read(View view) {
try{
String text = readFile("myfile.txt");
Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}
catch (Exception e){
e.printStackTrace();
}
}
public void write(View view) {
try{
saveFile("Bonjour!","myfile.txt");
}
catch (Exception e){
e.printStackTrace();
}
}
XML Utiliser XmlPullParser ou Document (DOM)
48
JSON (Utiliser les classes « JSONArray » et « JSONObject »)
private JSONArray readJSON(String fileName) throws JSONException, IOException {
String text = readFile(fileName);
JSONArray data = new JSONArray(text);
return data;
}
Utilisation
public void read(View view) {
try{
JSONArray array = readJSON("people.json");
Toast.makeText(this, array.toString(), Toast.LENGTH_LONG).show();
}
catch (Exception e){
e.printStackTrace();
}
}
public void write(View view) {
try{
String json = "[\n" +
" {\n" +
" \"name\": \"Jerome\",\n" +
" \"email\": \"[email protected]\"\n" +
" },\n" +
" {\n" +
" \"name\": \"Marie\",\n" +
" \"email\": \"[email protected]\"\n" +
" }\n" +
"]";
saveFile(json,"people.json");
}
catch (Exception e){
e.printStackTrace();
}
}
Créer un objet JSON
Person person = new Person(1,"jerome","[email protected]");
JSONObject json = new JSONObject();
json.put("id", person.getId());
json.put("name", person.getName());
json.put("email", person.getEmail());
Avec « json.toString() » on obtient
{"id":"1","name":"jerome","email":"[email protected]"}
On peut également utiliser JSONArray.
49
12. SQLite Base de données « légère » ne demandant pas de serveur. Documentation
DbHelper
public class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context, String name, SQLiteDatabase.CursorFactory factory,
int version) {
super(context, name, factory, version);
}
@Override
public void onCreate(SQLiteDatabase db) {
String request ="Create table Person (" +
"Id integer primary key autoincrement," +
"Name text not null," +
"Email text not null" +
");";
db.execSQL(request);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
String request = "Drop table Person;";
db.execSQL(request);
}
}
Le « model »
public class Person {
private long id;
private String name;
private String email;
public Person(){ }
public Person(String name, String email){
this.name = name;
this.email = email;
}
public void setId(long id){ this.id = id; }
public void setName(String name){ this.name = name; }
public void setEmail(String email){ this.email = email; }
public long getId(){ return id; }
public String getName(){ return name; }
public String getEmail(){ return email; }
public String toString() {
return name;
}
}
« Service »
On peut utiliser la méthode « execSQL » dans le cas de requêtes ne retournant pas de résultat.
Lecture : on utilise la méthode « query » de « SQLiteDatabase » et un « Cursor » pour parcourir
les données retournées
Ecriture : utilisation des méthodes « insert », « update », « delete » de « SQLiteDatabase
Création de la table
si elle n’existe pas
50
Utilisation : On ouvre la connexion dans « onCreate » de l’activité et la ferme dans « onResume »
ou « onStop »
public class PeopleRepository {
DbHelper dbHelper;
SQLiteDatabase db;
public PeopleRepository(Context context) {
dbHelper = new DbHelper(context, "dbPeople", null, 1);
}
public void open() {
db = dbHelper.getWritableDatabase();
}
public void close() {
dbHelper.close();
}
public List<Person> getAll() {
List<Person> people = new ArrayList<>();
String[] columns = new String[]{"Id", "Name", "Email"};
Cursor cursor = db.query("Person", columns, null, null, null, null, null);
while (cursor.moveToNext()) {
Person person = new Person();
person.setId(cursor.getLong(cursor.getColumnIndex("Id")));
person.setName(cursor.getString(cursor.getColumnIndex("Name")));
person.setEmail(cursor.getString(cursor.getColumnIndex("Email")));
people.add(person);
}
cursor.close();
return people;
}
public Person insert(Person person) {
ContentValues values = new ContentValues();
values.put("Name", person.getName());
values.put("Email", person.getEmail());
long newId = db.insert("Person", null, values);
person.setId(newId);
return person;
}
public int update(Person person) {
ContentValues values = new ContentValues();
values.put("Name", person.getName());
values.put("Email", person.getEmail());
String where = "Id = " + person.getId();
return db.update("Person", values,where,null);
}
public int delete(Person person) {
String where = "Id = " + person.getId();
return db.delete("Person", where,null);
}
}
Clause « where »
Récupération de l’id
(autoincrement)
On pourrait créer des
constantes (avec nom de table,
colonnes) réutilisables dans
toutes les requêtes
51
13. HTTP
a. AsyncTask Ajouter la classe à l’activité (« nested class »)
private class MyTask extends AsyncTask<String,String,String>{
@Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
displayMessage("Starting task");
}
@Override
protected String doInBackground(String... params) {
for(int i=0;i < params.length; i++){
publishProgress(params[i]);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
return "Tâche terminée.";
}
@Override
protected void onPostExecute(String result) {
progressBar.setVisibility(View.INVISIBLE);
displayMessage(result);
}
@Override
protected void onProgressUpdate(String... values) {
displayMessage(values[0]);
}
}
Exécution de la tâche (au clic sur l’élément de menu « Tasks »)
MyTask task = new MyTask();
task.execute("message 1", "message 2", "message 3");
Si on utilise « Thread.sleep » lancer la tâche avec task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, "message 1",
"message 2", "message 3");
Exécution de la tâche.
« publishProgress » appelle
« onProgressUpdate »
Avant que la tâche
soit exécutée
A la fin de la tâche
Types : Params, Progress,
result
On a une TextView dans laquelle on
affiche les messages et une
ProgressBar visible durant
l’exécution de la tâche
Pour la démo
52
Code de l’activité
public class MainActivity extends ActionBarActivity {
TextView messagesText;
ProgressBar progressBar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
messagesText = (TextView) findViewById(R.id.messagesText);
messagesText.setMovementMethod(new ScrollingMovementMethod());
progressBar = (ProgressBar) findViewById(R.id.progressBar);
progressBar.setVisibility(View.INVISIBLE);
}
// etc.
public void displayMessage(String message){
messagesText.append(message + "\n");
}
private class MyTask extends AsyncTask<String,String,String>{
// code de la tâche
}
}
b. Tester la connexion private boolean isOnline(){
ConnectivityManager manager = (ConnectivityManager)
getSystemService(CONNECTIVITY_SERVICE);
NetworkInfo info = manager.getActiveNetworkInfo();
return(info!=null && info.isConnectedOrConnecting());
}
Permissions à ajouter au manifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
53
c. Avec « HttpURLConnection » Documentation
public class HttpManager {
public static String getData(String uri) {
BufferedReader reader = null;
try {
URL url = new URL(uri);
HttpURLConnection connection =
(HttpURLConnection) url.openConnection();
StringBuilder builder = new StringBuilder();
reader =
new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + "\n");
}
return builder.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
54
d. Parser une réponse au format JSON
[{"id":1,"name":"Marie","email":"[email protected]"},{"id":2,"name":"Jerome","email":"[email protected]"}]
On créé une classe « JSONParser » par exemple qui renvoie une liste de personnes à partir du
json reçu
public class JSONParser {
public static List<Person> getPeople(String content) {
try {
JSONArray array = new JSONArray(content);
List<Person> people = new ArrayList<>();
for (int i = 0; i < array.length() ; i++) {
JSONObject object = array.getJSONObject(i);
Person person = new Person();
person.setId(object.getInt("id"));
person.setName(object.getString("name"));
person.setEmail(object.getString("email"));
people.add(person);
}
return people;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
Utilisation dans l’activité (au clic sur un menu par exemple)
if(isOnline()){
MyTask task = new MyTask();
task.execute("http://monservice123.com/people");
}
La tâche
private class MyTask extends AsyncTask<String,String,String>{
@Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);
}
@Override
protected String doInBackground(String... params) {
String content = HttpManager.getData(params[0]);
return content;
}
@Override
protected void onPostExecute(String result) {
List<Person> people = JSONParser.getPeople(result);
displayPeople(people);
progressBar.setVisibility(View.INVISIBLE);
}
}
On peut adapter la méthode affichant la sortie
public void displayPeople(List<Person> people){
for(Person person : people){
messagesText.append(person.getName() + "\n");
}
}
55
e. POST + passage de paramètre au format JSON public static String postData(Person person,String uri) {
BufferedReader reader = null;
try {
// json
JSONObject json = new JSONObject();
json.put("id", person.getId());
json.put("name", person.getName());
json.put("email", person.getEmail());
URL url = new URL(uri);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(json.toString());
writer.flush();
// réponse
StringBuilder builder = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line = "";
while ((line = reader.readLine()) != null) {
builder.append(line + "\n");
}
return builder.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
}
finally {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
f. Libraires OkHttp, Retrofit, Volley
« fabrication » de la chaine
de caractères json à partir
d’un objet « personne »
56
14. Toasts Documentation
import android.widget.Toast;
Toast.makeText(this, "Mon message!", Toast.LENGTH_LONG).show();
15. Notifications 1. On définit les propriétés de la notification (« NotificationCompat.Builder »)
2. On déclenche la notification avec « NotificationManager »
Propriétés de base
String title = "Mon titre";
String contentText = "Message ...";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder .setSmallIcon(R.drawable.message)
.setContentTitle(title)
.setContentText(text)
Affichage
Notification notification = builder.build();
NotificationManager manager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(1,notification);
57
Avec activité
On créé une activité qui sera affichée au clic sur la notification
String title = "Mon titre";
String contentText = "Message ...";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder .setSmallIcon(R.drawable.message)
.setContentTitle(title)
.setContentText(text)
// intent
Intent intent = new Intent(this,ShowNotificationActivity.class);
intent.putExtra("Title",title);
intent.putExtra("ContentText",contentText);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent,0);
builder.setContentIntent(pendingIntent);
//
Notification notification = builder.build();
NotificationManager manager =
(NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(1,notification);
Plus de propriétés …
Définir une grande icone en plus d’une petite icone
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.myimage))
Définir un nombre
builder.setNumber(100)
Activité affichée au clic sur
la notification
58
« BigTextStyle »
String title = "Mon titre";
String contentText = "Message ...";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.message);
NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle();
style.setBigContentTitle(title)
.setSummaryText(text)
.bigText("Lorem ipsum dolor sit …");
builder.setStyle(style);
// etc.
« BigPictureStyle »
String title = "Mon titre";
String contentText = "Message ...";
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.drawable.message);
NotificationCompat.BigPictureStyle style = new NotificationCompat.BigPictureStyle();
style.setBigContentTitle(title)
.setSummaryText(text)
.bigPicture(BitmapFactory.decodeResource(getResources(),R.drawable.foodies));
builder.setStyle(style);
// etc.
59
« addAction »
Peut-être couplé à un service par exemple pour stopper celui-ci
builder.addAction(R.drawable.close,"Stop",pendingIntent);
16. Service et IntentService
a. Service Menu « File » … « New » … « Service »
public class MyService extends Service {
public MyService() {
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
Log.i("MyIntentSerice", "valeur de i : " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return 0;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
}
Problème : ici le service est bloquant
Pour la
démo
60
b. IntentService … pour un service en tâche de fond (le service s’exécute sur son propre thread ce qui n’est pas
bloquant)
Menu « File » … « New » … « Service » … « IntentService »
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
Log.i("MyIntentSerice", "valeur de i : " + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Lancement du service
Intent intent = new Intent(this,MyIntentService.class);
startService(intent);
Pour la démo
On passe le nom du thread
61
17. « Broadcast Receiver » Sorte de « Messenger »
Abonnement (dans activitié par exemple)
IntentFilter filter = new IntentFilter("MyFilter");
MyReceiver receiver = new MyReceiver();
registerReceiver(receiver, filter);
Envoi de message (service par exemple)
Intent dointent = new Intent();
dointent.setAction("MyFilter");
sendBroadcast(dointent);
Menu « File »… « New »… « Other »… « Broadcast Receiver »
public class MyReceiver extends BroadcastReceiver {
public MyReceiver() {
}
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Tâche finie", Toast.LENGTH_LONG).show();
}
}
« Dynamic Broadcast Receiver» Au lieu de créer une classe héritant de « BroadcastReceiver » … on définit directement le code
dans son activité (dans « onCreate » par exemple)
IntentFilter filter = new IntentFilter("MyFilter");
BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(getApplicationContext(), "Tâche finie", Toast.LENGTH_SHORT).show();
}
};
registerReceiver(receiver, filter);
Se désenregistrer dans « onDestroy » par exemple
unregisterReceiver(receiver);