Démarrer un projet

  1. Ouvrir Android studio et créer un nouveau projet « Start a new Android Studio project ».
  2. Choisir :
    • un nom pour l’application et un nom de domaine (qui donne le nom du package … à l’envers).
    • un répertoire de travail sur votre ordinateur … donc  U:\Documents  au lycée !
  3. Choisir la cible « Phone and tablets » et une version minimale d’Android (exemple : « API 15: Android 4.0.3 »), c’est la version avec laquelle sera compilée l’application.
    Quelle version d’Android minimale (minimum SDK) dois-je prendre ?
    Si vous choisissez une version minimale récente, alors vous disposerez de toutes les librairies (barre de menu, widget … c’est un avantage pour le développeur) mais en contrepartie, votre application ne sera disponible qu’aux clients ayant au moins cette version d’Android, donc :

    Plus la version du SDK minimal est récente, moins il y a de clients potentiels !

    An_Start3

  4. Ensuite, on peut demander à Android Studio de créer une Activity pré-programmée (Login, GoogleMap … ) ou nous laisser page blanche (Basic Activity) pour qu’on fasse tout nous-même !
  5. Dernière étape : choisir un nom à cette activité (« MainActivity » (activité principale) convient parfaitement .. puisqu’on en a qu’une seule !)
  6. attendre jusqu’à obtenir le téléphone virtuel :
     … puis enfin : 

Créer un AVD (un téléphone virtuel)

Pour tester les (futures) lignes de codes, il faut construire un téléphone virtuel, appelé AVD (Android Virtual Device) ou utiliser un vrai téléphone !
Pour construire un AVD :

  1. étape 1 : menu Tools > Android > AVD Manager.
  2. étape 2 : Il y a 2 possibilités :
    • La plus simple : Soit vous utilisez le Nexus qui est sous la toute nouvelle version d’Android et vous allez directement à l’étape 3.
    • La plus compliqué : Soit vous créez un autre téléphone un peu plus ancien : un Android 4 (KitKat) … MAIS IL VA FALLOIR TÉLÉCHARGER LA LIBRAIRIE ANDROID 4.4 Kit Kat (1,2 Go) :
      1. Créer un nouvel AVD :
      2. Choisir un type de téléphone pour les tests de l’appli.
      3. Choisir une version d’Android pour ce téléphone de test (l’AVD) (le choix est limité aux versions installées dans votre SDK Manager à moins de les télécharger).
      4. Accepter la licence :
      5. Puis le téléchargement d’Android Kit Kat (1,2 Go) commence …  Attendre !
      6. Une fois le téléchargement terminé, créer l’AVD Kit Kat et donner un nom à ce téléphone virtuel.
            
  3. étape 3 : Démarrer l’AVD (c’est long …. c’est la raison pour laquelle on le garde ouvert pendant tout le temps de la programmation pour éviter de perdre trop de temps) :
    An_Avd7    An_Avd8
    Vous pouvez déverrouiller l’écran du téléphone virtuel et ajuster les paramètres : l’heure système ….
  4. étape 4 : De retour dans Android Studio : exécuter l’application … un Hello world devrait apparaitre.
    En fait, une Basic Activity contient un TextView « Hello World » (on pourra l’enlever par la suite).
    An_Avd9     An_Avd10

Un conseil : Ne pas fermer l’AVD tant que vous travaillez sur l’appli car l’AVD est très long à l’allumage !!!

GUI (Layout)

Présentation

Android studio a l’avantage de montrer en direct les placements (Layout) … un gain de temps !
Dans l’arborescence du projet (à gauche), ouvrir le fichier XML (double-clic) : app > res > layout > content_main.xml

An_Layout1

Au centre :  2 onglets : Text et Design.
A droite : un téléphone sur lequel on peut changer l’orientation portrait/paysage, la taille … pour voir tous les visuels possibles ! … et quelques boutons utiles : rafraîchir l’affichage, screenshot.

content_main.xml et activity_main.xml

En réalité, vous trouverez certainement 2 fichiers xml :

  • content_main.xml : il contient le contenu d’une vue (l’intérieur de la page)
  • activity_main.xml : il contient la vue dans toute sa globalité (extérieur + intérieur) :
    • une barre de menu (bleue foncé) : toolbar
    • le bouton flottant rose (Floating Action Button) : fab
    • une instruction pour inclure le fichier précédent content_main.xml :  <include layout="@layout/content_main" />

=> On utilise activity_main.xml pour modifier la coque extérieur de l’application (barre de menu)
=> On utilise content_main.xml pour modifier le contenu de l’application (champs de saisie, bouton)

Vue Android ou Project

An_vueAndroidProject

Layout : Construction de la GUI

On utilisera la longue liste des propriétés (tout à droite) ou les propriétés avancées  .

RelativeLayout

Pour construire la GUI, il n’y a pas de « absolute layout » (placement en coordonnées) mais un RelativeLayout qui ressemble un peu.

RelativeLayout : les éléments sont placés à une certaine distance les uns des autres. L’inconvénient est qu’on obtiendra sûrement un déséquilibre sur un écran plus grand.

LinearLayout

Un développeur utilise plutôt une succession de LinearLayout verticaux et horizontaux pour garder une certaine homogénéité sur le rendu …
NB : on peut insérer des LinearLayout verticaux à l’intérieur de LinearLayout horizontaux et vice-versa … (il en est de même pour tout type de layout), c’est un travail d’emboîtement !

dimensions (layout_width ,  layout_height ) :

  • une taille fixe : exemple 50px ou sp ou dp (donc … quelque soit la taille de l’écran ! ).
  • match_parent ( = fill_parent) : le composant occupe tout l’espace disponible après le placement des autres widgets.
  • wrap_content : le composant occupe une taille naturelle. Si le TextView est trop gros, Android coupera le texte.

alignement (gravity) :

layout_gravity est accessible dans les propriétés avancées .

  • left, center_horizontalright : alignement horizontal du widget. Exemple : dans un LinearLayout vertical, les widgets peuvent ainsi être placés sur la gauche, au centre ou à droite.
  • top, center_vertical, bottom : alignement vertical du widget. Dans un horizontal LinearLayout, les widgets peuvent donc être placés en haut, au centre ou en bas.

poids (layout_weight) :

layout_weight est accessible dans les propriétés avancées .

  • Si on met un poids 1 à un bouton et un poids 2 à un textView alors le textView occupera 2 fois plus d’espace que le bouton.
  • Si on met le même poids alors les composant se partagent équitablement l’espace disponible.
  • Par défaut, le poids est 0.

marge interne (padding) :

paddingTop, paddingBottom, paddingRight, paddingLeft sont accessibles dans les propriétés avancées .

  • c’est l’espace entre le contour de l’élément et son contenu
  • Exemple : pour un bouton c’est l’espace entre le contour du bouton et son texte.

marge externe (layout_margin)

layout_marginTop, … sont accessibles dans les propriétés avancées .
C’est l’espace entre le contour de l’élément et le contour de l’élément suivant.

Les références

Référence de Text

Parce qu’une application Android peut être multilingue, alors on n’écrit pas de texte mais des références de texte !

Exemple : un bouton aura pour texte une référence, puis cette référence donnera « Valider » en Français ou « Validate » en Anglais !

  • le Button est dessiné dans : app > res > layout > content_main.xml
  • le texte de la référence est dans : app > res > values > strings.xml

Référence de Layout

Parce qu’une application peut être multi-screen (téléphone / tablette) en orientation portrait ou paysage alors on peut prévoir plusieurs style de dispositions (Layout). Idem, on utilise des références de Layout.

TextView : Afficher un texte

Il y a 2 façons d’écrire un texte dans un TextView :

En dur

Le texte est mis directement dans le TextView. On peut y accéder soit par l’onglet Design ou par l’onglet Text

Exemple : le TextView « Hello World » présent par défaut est en dur.

  •  — OU BIEN —
    <TextView
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:text="Hello World!" />

En passant par une référence de Text

Le TextView ne contient qu’une référence de texte et on renseigne le texte contenu dans cette référence dans un autre fichier String.xml  (cela permet de faire une appli multilingue : une même référence donne « Hello » en anglais et « Bonjour » en françai) :

  • le TextView est dessiné dans : app > res > layout > content_main.xml
  • le texte de la référence est dans : app > res > values > strings.xml

P

  1. Créer une référence dans strings.xml en ajoutant <string name="bonjour">Bonjour tout le monde</string>
  2. Créer un « Plain TextView » dans content_main.xml sur l’onglet Design par drag and drop
    An_Layout2
  3. Ouvrir les ressources puis sélectionner la ressource « bonjour » créée précédemment.

Le texte « Bonjour tout le monde » s’affiche dans le visuel.An_Layout4
Le TextView a pour contenu  android:text="@string/bonjour" (car la référence est @string/bonjour).

 

EditText : champs de saisie

L’EditText sert à récupérer un texte saisie au clavier, grâce à la méthode getText()

inputType :

  • textMultiLine
  • phone
  • lines : nombre de lignes
  • gravity : top
  • background : une fenêtre pop-up s’ouvre > aller dans la section Drawable > choisir par exemple un encadrement : editbox_background_normal

 

 

 

Tuto Envoi SMS

Pour envoyer un SMS, il y a 2 méthodes possibles :

  • l’API SmsManager :
    SmsManager smsManager = SmsManager.getDefault();
    smsManager.sendTextMessage("phoneNo", null, "sms message", null, null);
  • l’application SMS intégrée au téléphone  Built-in SMS  (la plus simple car vous laissez le périphérique gérer) :
    Intent sendIntent = new Intent(Intent.ACTION_VIEW);
    sendIntent.putExtra("sms_body", "default content");
    sendIntent.setType("vnd.android-dir/mms-sms");
    startActivity(sendIntent);

Mais bien sûr, ces 2 méthodes ont besoin de l’autorisation d’envoyer un SMS appelée   » SEND_SMS « .

Ajouter une permission

Cela se fait manuellement avec l’auto-complétion, en tapant avant <application   le symbole   <  .
NB : Le raccourci clavier de l’auto-complétion est  CTRL+ESPACE.
    et valider.

Puis fermer la balise auto-fermante, on obtient :

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

Layout

  1. Enlever le « hello world » présent par défaut, mais garder le RelativeLayout.
  2. Faire glisser votre Layout dans le Component Tree ou dans le Design.
  3. Ajouter les éléments un par un, dans le Component Tree, en choisissant un identifiant intelligent pour chacun.
  4. Résultat final :
      

Java

Lorsqu’on clique sur le bouton btnEnvoyer , son Listener doit :

  1. Récupérer le contenu des EditText : editNumero et editMessage.
  2. Envoyer le SMS.

Pour accéder aux EditText, on peut déclarer des variables et initialiser ces variables aux identifiants editNumero et editMessage (définies précédemment dans la GUI content_main.xml).

Facultatif : enlever le bouton flottant et la barre de menu

Si l’application n’a pas besoin de barre de menu et de bouton flottant alors on peut les enlever :

  • Dans activity_main.xml, on peut enlever (si on ne compte pas s’en servir) :
    • la barre de menu : toolbar
    • le bouton flottant rose (Floating Action Button) : fab
  • Dans MainActivity.java : enlever les 2 méthodes onCreateOptionsMenu() et onOptionsItemSelected() :
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
    
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
    
        return super.onOptionsItemSelected(item);
    }
  • Et encore dans MainActivity.java, dans la méthode onCreate(), supprimer ces lignes :
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    
    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });
  • Et toujours dans MainActivity.java, supprimer les imports gris car ils sont désormais inutiles.

Déclarer les variables EditText et Button

Dans MainActivity.java  :

  1. Dans les variables générales de la classe MainActivity : on déclare les 2 EditText et le Button. Puis faire Alt+Entrer pour importer les librairies.
  2. Dans la méthode onCreate(), on initialise ces variables aux identifiants des widgets editNumero et editMessage (c’est une recherche par identifiants dans le fichier des Ressources content_main.xml). De plus, il faut absolument faire un transtypage car Java ne peut pas vérifier que ces widgets sont de type Button et EditText.

Coder le Listener

Un Listener de Button doit absolument avoir un paramètre de type View, et ce paramètre doit être unique.

On peut donc écrire cette méthode (comme Listener de btnEnvoyer)  :

void envoiMessage(View view) {
    textNumero = editNumero.getText().toString();
    textMessage = editMessage.getText().toString();

    SmsManager sms = SmsManager.getDefault();
    sms.sendTextMessage(textNumero, null, textMessage, null, null);
}

Puis importer la classe de SmsManager (Alt+Entrer) :  import android.telephony.SmsManager;

  

Puis il y a 2 méthodes pour définir méthode envoiMessage comme Listener de btnEnvoyer :

1ère méthode : Par la GUI  :

Dans content_main.xml : dans les propriétés avancées du bouton btnEnvoyer > rubrique onClick > écrire le nom de la méthode donc envoiMessage

2e méthode : Par Java :

Dans MainActivity.java  , dans la méthode onCreate(), on ajoute un Listener sur le bouton  :

btnEnvoyer.setOnClickListener(new View.OnClickListener() {
    public void onClick(View v) {
       envoiMessage(v);
    }
});

NB : Dans cette 2e méthode, on peut supprimer le paramètre de type View dans la méthode envoiMessage() (dans ce cas, il faut le faire dans la déclaration de la méthode et aussi lors de son appel depuis le Listener).

Tester l’application

Pour tester l’envoi d’un sms, on a besoin de 2 téléphones virtuels appelés AVD (Android Virtual Device).

  1. Ouvrir l’AVD Manager  : menu Tools > Android > AVD Manager
  2. Démarrer un AVD :
  3. Pour démarrer un 2ème AVD, il faut créer un nouvel AVD dans l’AVD Manager : « Create Virtual Device »

  4. Lancer l’application et sélectionner l’AVD qui va recevoir cette application … puis patienter (le temps de compilation peut être long).
  5. Envoyer un SMS à l’autre AVD en mettant son numéro de téléphone en destinataire.
    NB : Régler les AVD sur la langue Française pour accéder aux lettres accentuées.

 

Variante : avec un rapport de réception

Cette variante affiche un Toast (un petit message pop up) précisant si le sms a été envoyé et s’il a bien été reçu.

void envoiMessage(View view) {
  textNumero = editNumero.getText().toString();
  textMessage = editMessage.getText().toString();

  PendingIntent sentPI = PendingIntent.getBroadcast(this, 0, new Intent("SMS_SENT"), 0);
  PendingIntent deliveredPI = PendingIntent.getBroadcast(this, 0, new Intent("SMS_DELIVERED"), 0);

  // ---when the SMS has been sent---
  registerReceiver(new BroadcastReceiver() {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
      switch (getResultCode()) {
          case Activity.RESULT_OK:
              Toast.makeText(getBaseContext(), "SMS sent",Toast.LENGTH_SHORT).show();
              break;
          case SmsManager.RESULT_ERROR_GENERIC_FAILURE:
              Toast.makeText(getBaseContext(), "Generic failure",Toast.LENGTH_SHORT).show();
              break;
          case SmsManager.RESULT_ERROR_NO_SERVICE:
              Toast.makeText(getBaseContext(), "No service",Toast.LENGTH_SHORT).show();
              break;
          case SmsManager.RESULT_ERROR_NULL_PDU:
              Toast.makeText(getBaseContext(), "Null PDU",Toast.LENGTH_SHORT).show();
              break;
          case SmsManager.RESULT_ERROR_RADIO_OFF:
              Toast.makeText(getBaseContext(), "Radio off",Toast.LENGTH_SHORT).show();
              break;
      }
    }
  }, new IntentFilter("SMS_SENT"));

  // ---when the SMS has been delivered---
  registerReceiver(new BroadcastReceiver() {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
      switch (getResultCode()) {
          case Activity.RESULT_OK:
              Toast.makeText(getBaseContext(), "SMS delivered",Toast.LENGTH_SHORT).show();
              break;
          case Activity.RESULT_CANCELED:
              Toast.makeText(getBaseContext(), "SMS not delivered",Toast.LENGTH_SHORT).show();
              break;
      }
    }
  }, new IntentFilter("SMS_DELIVERED"));

  SmsManager sms = SmsManager.getDefault();
  sms.sendTextMessage(textNumero, null, textMessage, sentPI, deliveredPI);
}

NB : L’accusé-réception deliveredPI (BroadcastReceiver) ne peut pas fonctionner pas sur des AVD !