Cours Android développement d'applications avancées PDF


Télécharger Cours Android développement d'applications avancées PDF

★★★★★★★★★★3.5 étoiles sur 5 basé sur 1 votes.
Votez ce document:

Télécharger aussi :


Android Introduction

Notes de cours

 

Sommaire

•    Un peu d’historique

•    Andoid OS comme middleware

•    Du Java sans JVM

•    Principes de base

•    Ces notes représentent une introduction …

Bibliographie utilisée

Le livre de Mark Murphy chez Pearson

Le livre écrit par Florent Garin

       Android

Le cours de Victor Matos

            

Plusieurs livres

 Android A Programmers Guide - McGraw Hill

   Professional Android Application Development - Wrox

Android : les objectifs

•   

•   

“… Open Handset Alliance™, a group of 47 technology and mobile companies have come together to accelerate innovation in mobile and offer consumers a richer, less expensive, and better mobile experience.

•    Together we have developed Android™, the first complete, open, and free mobile platform.

•    We are committed to commercially deploy handsets and

services using the Android Platform. “

Qu’est-ce que Android ?

•    Une plate forme ouverte, un ensemble de librairies, de composants logiciels pour les systèmes embarqués et mobiles

–    Un système d’exploitation

•    Linux

–    Un intergiciel (middleware)

•    Un canevas (framework) pour différents types d’applications

–    Nombreuses librairies 

•     IHM,

•     Téléphonie,

•     Multimédia,

•     Capteurs,

•     Internet, cartographie

•    

Pourquoi Android ?

•     Indépendant d’une architecture matérielle

•     Dédié aux systèmes embarqués et pas seulement

•     Ambitions de Google/Apple

–    Marketing

–    Retard : au 25 Juin 2010

•   67000 applications sur AndroidMarket

•   270000 sur AppStore

Les autres

•    Apple

•    Microsoft

•    Nokia

•    Palm

•    Research in Motion (BlackBerry)

•    Symbian

•    Quid de JavaFX et javaME ? ….

–    JavaFX/Flash prometteur mais

–    Lancé en 2009, qui l’utilise ?

•   

Android les grandes lignes

•    Composants Android

•    Outils de Développement

•    Architecture Logicielle

•    Développement 

–    en java avec quelques directives en syntaxe XML

•    Deux exemples

–    Démonstration 

•    Un navigateur en deux appels de méthodes

•    Un MVC façon Android

Composants Android

•    Framework de déploiement d’applications

•    Dalvik comme machine virtuelle (à registres != JVM de Sun à pile)

•    Navigateur intégré, WebKit ( webkit utilisé par safari, Google Chrome…)

•    SQLite

•    Multimédia support PNG, JPG, GIF, MPEG4, MP3, H.263

•    Dépendant du matériel

–    GSM

–    Bluetooth, EDGE, 3G, WiFi

–    Caméra, GPS, boussole et accéléromètre

–    Température, 

–   

Outils de développement

SDK Android

En ligne de commandes

Plug-in sous eclipse

Émulateur

Débogueur

Traces fines d’exécution

Tests unitaires

Outils de mise au point

Mesure de mémoire et performance

Composants Android

 

Développement 1/2

•    Fichier de configuration XML

–    Un source Java est généré, le fichier de ressources R.java

•    Configuration de l’application, IHM, String, …

•    Java

–    Paquetage , 

•    Attention ce ne sont pas les librairies du JavaSE ( n’est pas )

•    Compilateur javac de Sun

javac –bootclasspath android/introduction/*.java

Développement 2/2

•    Du .class en .dex

–    De la JVM à la machine Dalvik

–    D’une machine à pile en machine à registres

•    Génération de l’application  .apk

–    Une archive signée

–    Téléchargement : émulateur ou mobile


En détail, développement 1/2

Compilation : obtention des .class

 

Source :

Développement 1/2

Fichier de configuration,

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="; package="test.biblio"       android:versionCode="1"

android:versionName="1.0">

<uses-permission android:name="android.permission.INTERNET" />

<application android:icon="@drawable/icon" android:label="@string/app_name">

        <activity android:name=".BrowserDemo" android:label="@string/app_name">

            <intent-filter>

                <action android:name="" />

                <category android:name="android.intent.category.LAUNCHER" />

            </intent-filter>

</activity>

</application>

</manifest>

Le fichier de Ressources, R.java

•  

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout 

  android:orientation="vertical" android:layout_width="fill_parent"   android:layout_height="fill_parent">

  …

</LinearLayout>

•     AUTO-GENERATED FILE.  DO NOT MODIFY.

package test.biblio; public final class R {

   

     public static final class layout {         public static final int main=0x7f030000;

    }}

Un Source java, juste pour la syntaxe… 

import .Activity;

import .Bundle;

public class BrowserDemo extends Activity {

…. @Override

    public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState); setContentView(R.layout.main);

        ….

} }

Développement 2/2

Du .class en .dex

–    Assemblage de tous les .class vers un .dex Un décompilateur :

–    Une machine par application, un processus Linux Les applications communiquent via l’intergiciel

Génération de l’application  .apk

–    Assemblage de 

–    Une archive signée

–    Téléchargement : émulateur ou mobile


Développement 2/2 Génération de l’application

 

Source :

Exécution émulateur et/ou mobile .apk

 

Android OS

 

Un ensemble d’API

Middleware Android OS, un extrait

•    System listes, boutons,… navigateur (WebView)

•    , accès aux String, aux descriptifs de l’ihm – R.java …

•    gestion du cycle de vie d’une application

–    Une application android

•    Accès aux données d’autres applications, partage de données

–    autorise des alertes dans la barre de statut – TelephonyManager – ….

–   

Librairies

 

C/C++ …

•   SGL comme moteur pour le 2D

•   FreeType comme fontes de caractères

Dalvik VM, au lieu de JVM

•     Machines à registres

 

•     Chaque application à sa propre DVM

Communication inter-applications assurée par le middleware

Multi thread assuré par Linux

Accès aux capteurs par le noyau Linux

 

Introduction aux Applications Android

•    Mots-clés 

–    Applications,

–    Communication, évènements, intentions, Services en tâche de fond, Persistance.

•    Une Application hérite le la classe Activity

–    Surcharge de certaines méthodes, 

•    Du déjà vu : MIDlet, Applet, Servlet,…

–    Le cycle de vie est imposé par le framework

•    Déjà vu : pour une Applette init() puis …

Avertissement

•    C’est une introduction

–    Le vocabulaire

–    Les grandes lignes

–    Quelques analogies seront faites avec du java « traditionnel »

•    Les Essentiels

–    Activity

–    BroadcastReceiver

–    Service

–    ContentProvider

Introduction … Classes

•    Activity

–    Une interface utilisateur

–    Une configuration de type XML, permissions, librairies,

•    BroadcastReceiver

–    Bus de messages

–    Émission et réception d’intentions

•    Service

–    Pas d’interface, un service à rendre, en tache de fond

–    Intention de servir

•    ContentProvider

–    Données rendues persistantes pour d’autres applications Un fichier, base SQLLite

Deux exemples, deux Activity

1.    Usage de WebKit



–     Installation d’un navigateur en 2 lignes (WebView)

2.    Une IHM

                            • Un bouton, un écouteur, un clic et l’heure est affichée !

–     À télécharger ici

                                            •   

Activity Usage du WebKit, 2 lignes

import .Activity; import .Bundle; import android.webkit.WebView;

public class BrowserDemo extends Activity {     private WebView browser;

@Override

    public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState); setContentView(R.layout.main);

 

OnCreate est déclenché par le framework Android

public class BrowserDemo extends Activity {     private WebView browser;

    @Override

    public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState); setContentView(R.layout.main);

        browser=(WebView)findViewById(R.id.webkit);         browser.loadUrl(";);

    }

}

                        R.layout.main , R.id.webkit ?

Une configuration XML

R.id.webkit  ? ?

En Entrée

Fichiers de configuration XML

En Sortie

Source Java, R.java

 

Activity Un Click et l’heure est actualisée

 import .Activity;  import .Bundle;  import ;  import android.widget.Button; import ; 

public class Now extends Activity implements View.OnClickListener {    private Button btn;

@Override 

public void onCreate(Bundle bundle) {super.onCreate(bundle); btn = new Button(this); 

btn.setOnClickListener(this);// <- un écouteur auprès de cette vue     setContentView(btn); 

}  

public void onClick(View view) {  // <- à chaque click btn.setText(new Date().toString());

}  } 

Notes : Vue apparentée swing, sans descrpiption XML de l’IHM Ici un MVC à lui tout seul …

Un clic et l’heure…  

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="; package="cnam.intro"       android:versionCode="1" android:versionName="1.0">

<application android:icon="@drawable/icon" android:label="@string/app_name">

<activity android:name=".Now" android:label="@string/app_name">

<intent-filter>

<action android:name="" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

</manifest>

Activity

•    Une Vue

•    En inversion de contrôle,

Méthodes onStart()…. Déclenchées par le middleware

•    Diagramme d’états

public class .Activity

 package ;

public class Activity extends ApplicationContext {

         protected void onCreate(Bundle savedInstanceState){

     protected void onStart();

     protected void onRestart();

     protected void onResume();

     protected void onPause();

     protected void onStop();

     protected void onDestroy();

}

Inversion de Contrôle… Rappel

 

              public class Activity extends ApplicationContext {       1

protected void onCreate(Bundle savedInstanceState);

protected void onStart();

…..}

Activity : les états,

C’est le framework  qui contrôle tout

En tache de fond :

  Empiler(l’activité);

onResume

  activité au 1er plan = Dépiler()

Démonstration, Activity dans tous ses états

public class BrowserDemo extends Activity {   private WebView browser;     public void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);

        Log.i("=======","onCreate");

// cf. page précédente

}     public void onDestroy(){       super.onDestroy();

      Log.i("******", "onDestroy");

}

            }

En résumé : émulateur + LogCat : traces bien utiles

 

Démonstration, Activity dans tous ses états

public class BrowserDemo extends Activity {

  public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);Log.i("=======","onCreate");}

  public void onStart(){super.onStart();Log.i("=======","onStart");}

  public void onResume(){      super.onResume();

Log.i("=======","onResume");

}     public void onPause(){      super.onPause();

Log.i("=======","onPause");

}     public void onStop(){      super.onStop();

 Log.i("******","onStop");

}

public void onDestroy(){       super.onDestroy();

      Log.i("******", "onDestroy");

    }

}

OnPause -> onResume

1)         2-1) telnet localhost 5554

   

Sauvegarde, restitution, Bundle

•     Un Bundle est une map, 

une table dont 

•     les clés sont des String, 

•     les valeurs des objets (Parcelable vu ensuite <T extends Parcelable>)

•     Sauvegarde

@Override public void onSaveInstanceState( Bundle out){   out.putString("CurrentDate", new Date().toString()); super. onSaveInstanceState(out);

}

•     Restitution

@Override public void onRestoreInstanceState( Bundle save){   out.putString("CurrentDate", new Date().toString());

}

Attention au cycle de vie, onRestoreInstanceState à vérifier

Communication inter-activités

Communication comme intention

–    Entre deux applications, entre deux dalvik

–    Abonnements 

Intention de … porter un toast

 

Intent

Android : Intents, comme Intention

 

Il faut : 

•    Un receveur

public static class Receiver extends BroadcastReceiver {   public void onReceive(Context context, Intent intent) {    ….

•    Enregistrement auprès du middleware

•    Une intention d’émettre

Intention de 

Un receveur, qui porte un toast public static class Receiver extends BroadcastReceiver {   public void onReceive(Context context, Intent intent) {

    Toast.makeText(context,intent.getStringExtra("message"),3000).show(); }

}

Enregistrement auprès du middleware :  Receiver receiver = new Receiver();

 registerReceiver(receiver, new IntentFilter("PORTER_UN_TOAST"));  registerReceiver(receiver,new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

Émission de l’intention :

intent = new Intent("PORTER_UN_TOAST"); intent.putExtra("message", getResources().getString(R.string.message)); sendBroadcast(intent);

           •      Intent.ACTION_AIRPLANE_MODE_CHANGED, un abonné à cet Intent

À votre santé !

 

Intention de… auprès du middleware 

Enregistrement auprès du middleware :

 Receiver receiver = new Receiver();

 registerReceiver(receiver, new IntentFilter("PORTER_UN_TOAST"));

 registerReceiver(receiver,new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED));

•       Intent.ACTION_AIRPLANE_MODE_CHANGED, je suis maintenant abonné à cet Intent

Avec   private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED"; 

Et 

 registerReceiver(receiver,new IntentFilter(SMS_RECEIVED));

Je suis maintenant abonné aux réception de SMS

Publish-Subscribe/Intent & Context

 

            •    Extrait de

Sous Android

•    Mediator, classe Context

–   

•    Subscriber, classe BroadcastReceiver

–   

•    X,Y les thèmes, classe Intent

–   

•    IntentFilter

–   

Intention de téléphoner, à la pause …

•    Intent

•    Comme Communication

•    Démarrer une activité prédéfinie : téléphoner

Intention de téléphoner

public class Telephone extends Activity implements  OnClickListener {

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);         setContentView(R.layout.main);

        ((Button)this.findViewById(R.id.Button01)).setOnClickListener(this);

    }

    public void onClick(View v){

        Intent intent = new Intent(Intent.ACTION_DIAL);

        startActivity(intent);

    }

}

 

En Images, activité de téléphoner

 

Activités un résumé

•    Activity

–    Cycle de vie

–    Gérée par le framework

–    Une application est constituée de plusieurs activity (et services)

•    startActivity

–    Une activité peut en démarrer une autre

•    Communication

–    Intent

Service

•    En tache de fond

•    Toujours disponible

–    Locaux

•    Service personnel, inaccessible pour les autres applications

–    Distants

•    Rmi en plus simple … même machine

•    J’écoute un fichier audio mp3, pendant que je navigue sur le web

Un Service

 

Service distant,

Découverte du service par une intention …

SMSService : un exemple

•    Un compteur de SMS entrants



–    A chaque sms un compteur est incrémenté

–    Accessible par toute application

•    Le service a l’intention de recevoir des SMS

–    IntentFilter filter = new IntentFilter(SMS_RECEIVED);

–    registerReceiver(new SMSReceiver(), filter);

•    Un client recherchera ce service via le middleware

•    Le service : SMSService

Service, aidl (android interface description language)

package cnam.android;

/*

This file is auto-generated.  DO NOT MODIFY.

*/

package cnam.android; import …; public interface SMSService extends .IInterface{ 

/** Local-side IPC implementation stub class. */

public static abstract class Stub extends .Binder implements cnam.android.SMSService{ …

interface SMSService{ void start();   void stop();   long received();

}

Le Client recherche le service

private SMSService statsSMS;

bindService(new Intent(SMSService.class.getName()),              connexion,

            Context.BIND_AUTO_CREATE);

}

// Traitement asynchrone de la réponse venant de l’intergiciel

private ServiceConnection connexion = new ServiceConnection() {   public void onServiceConnected(ComponentName name, IBinder service) {     Log.v("service","onServiceConnected()");

.statsSMS = .asInterface(service);   }

public void onServiceDisconnected(ComponentName name) {

.statsSMS = null;

}

};

Le service 1/3, réveillé à chaque SMS

public class SMSServiceImpl extends Service {

 private static final String TAG = "SMSServiceImpl"; private static final String SMS_RECEIVED =

"android.provider.Telephony.SMS_RECEIVED";

         private boolean active;     private int     countSMSReceived;

       public void onCreate() {     super.onCreate();

IntentFilter filter = new IntentFilter(SMS_RECEIVED); registerReceiver(new SMSReceiver(), filter);

}

Le service 2/3, réveillé à chaque SMS

private class SMSReceiver extends BroadcastReceiver{ public SMSReceiver(){

    Log.v("SMSReceiver","SMSReceiver()");

  }

@Override

public void onReceive(Context context, Intent intent) {   Log.v("SMSReceiver","onReceive()"); if(active) .countSMSReceived++;

}

}


Le service 3/3, La souche le stub fournie à la demande

public IBinder onBind(Intent arg0) {   return new SMSServiceStubImpl();

}

 public class SMSServiceStubImpl extends {

public long received() throws .RemoteException{     return .countSMSReceived;

  public void start(){     active = true;

}

public void stop() throws RemoteException {     active = false;

}

}

Le Client, une activity

 

Démonstration…


ContentProvider

•    Sauvegarde et restitution de données

–    Données accessibles à toutes applications

•    ContentProvider

–    Persistance

–    DAO/CRUD

•    Data Access Object

•    Create Retrieve Update et Delete

Mes Contacts, un client  le ContentProvider prédéfini : phone

 

ContentProvider

•    ContentProvider, comme les contacts, accès 

–    ContentResolver resolver = getContentResolver(); 

Identification du bon « Contentprovider » grâce à son URI

–    Uri uri = android.provider.Contacts.Phones.CONTENT_URI;

–    String s = uri.toString();

–    // assert s.equals("content://contacts/phone");

–    Appel de resolver.query

•    Pour une interrogation

Parcours à l’aide d’un « Cursor »

Cursor comme ResultSet

   

Son propre ContentProvider

•     public class MonPropreProvider extends ContentProvider

•     Avec 

–    Une Uri, l’accès à mon propre « content provider » content://cnam.android.agenda/liste

•     content://….

–    Les méthodes

•     insert, update, delete et query

Et dans le fichier de configuration

<provider android:name="MonPropreProvider"              android:authorities="cnam.android.agenda" />

ContentProvider est une classe abstraite

•    Réalisation, 

implémentation des méthodes (c.f. DAO/CRUD)

•    insert, update, delete et query

Persistance Fichier ou base de données ?

Android propose SQLite

– Un exemple de fournisseur

•   Coordonnées d’un bar servant une bière pression particulière en latitude, longitude Où puis je trouver une Leffe pression, en fonction de ma position ? Itinéraire …

•   Persistance à l’aide ds SQLite CREATE TABLE bars_pression ( 

         id integer primary key autoincrement,          bar TEXT,           biere TEXT,           latitude FLOAT,           longitude FLOAT);

BarPressionProvider, Constantes

public class BarPressionProvider extends ContentProvider {

    public static final 

        Uri CONTENT_URI = Uri.parse(";);

    public static final String DATABASE_NAME = "";     public static final int DATABASE_VERSION = 1;     public static final String TABLE_NAME    = "bars_pression"; 

    // les champs

    public static final String ID        = "id";     public static final String BAR       = "bar";     public static final String BIERE     = "biere";     public static final String LATITUDE  = "latitude";     public static final String LONGITUDE = "longitude";     

    // les indices des colonnes

    public static final int COL_ID        = 1;     public static final int COL_BAR       = 2;     public static final int COL_BIERE = 3;     public static final int COL_LATITUDE  = 4;     public static final int COL_LONGITUDE = 5;

private SQLiteDatabase db; 

BarPressionProvider, create/insert

@Override

public boolean onCreate() {   BarPressionSQLite dbHelper;

dbHelper = new

BarPressionSQLite(getContext(),DATABASE_NAME,null,DATABASE_VERSION);

= dbHelper.getWritableDatabase();   return (db==null?false:true);

}

@Override

public Uri insert(Uri arg0, ContentValues arg1) {   long rowID = db.insert(TABLE_NAME, "biere", arg1);   return arg0;

}

BarPressionSQLite est une classe interne

         •    Help !

private static class BarPressionSQLite extends SQLiteOpenHelper {

private static final String CREATE_TABLE

"create table " + TABLE_NAME + " ( " +

ID + " integer primary key autoincrement, " +

BAR + " TEXT, "  +

BIERE + " TEXT, "  +

LATITUDE  + " FLOAT, " +

LONGITUDE + " FLOAT);";

public BarPressionSQLite(Context context, String name,                           CursorFactory cursor, int version){        super(context, name, cursor, version);

}

 @Override

public void onCreate(SQLiteDatabase db){   db.execSQL(CREATE_TABLE);

}

Le Client + LogCat

ContentResolver resolver = getContentResolver();

Uri uri = cnam.android.provider.BarPressionProvider.CONTENT_URI

ContentValues cv = new ContentValues(); (BarPressionProvider.BAR, "Le Bastille"); (BarPressionProvider.BIERE, "Leffe"); (BarPressionProvider.LATITUDE, 48.853668); (BarPressionProvider.LONGITUDE, 2.370319);

Uri uri2 = resolver.insert(uri, cv);

 

Publication du Provider par :

Fichier , dans <application

<provider android:name=".BarPressionProvider" android:authorities="" /> 

BarPressionProvider, query, update • En exercice !

Sqlite3, un outil d’interrogation de la bdd

   



9