Dans le dernier article, nous exposions tout le confort gagné à avoir son propre site, aujourd’hui nous allons découvrir comment doter son blog d’une application Android bien à lui!
Nous parlons ici d’un développement android visant à pouvoir consulter son site ou son blog depuis une application mobile. Concrètement le site HTML sera affiché par l’application mobiledédiée.
Télécharger l’application Android Geek01
NB: Pour installer l’appli qui ne provient pas du play store (market android), il faudra autoriser les applications « Sources inconnues » dans les paramètres de votre smartphone ou de votre tablette.
Voici le but du développement:
L’application permettra la visualisation et la navigation sur le site comme dans un navigateur internet.
Un menu donnera accès à la page d’accueil, à un formulaire de contact et à la fermeture de l’application.
D’aucuns diront, mais c’est trop facile, et ils n’auront pas tort quoique… D’autres se sont déjà enfuis en courant et ils ne devraient pas, car à tout problème une solution.
Les pré-requis pour ce développement Android
- le site Html (blog wordpress par exemple) doit être conçu pour s’adapter à une consultation sur mobile. C’est le cas de Geek01.com car le thème wordpress weaverII a bien une version mobile.
- il nous faut un environnement de développement: un PC (sous linux ou windows, voire même un Mac mais sans moi!) avec:
- le SDK Android installé et à jour
- l’IDE Eclipse installé
- le plugin ADT pour eclipse
si vous êtes perdu voici un tutoriel pour installer l’environnement de développement Android - Enfin des connaissances en Java ne sont pas superflues
IMPORTANT: Vous pouvez
télécharger le code source de ce qui suit.
C’est bien entendu open source.
Dans un but didactique et de simplification, les fonctionnalités de l’application ont toutes été regroupées au sein de la même activité.
Je n’évoquerai dans ce qui suit que les points bloquants car mal documentés ailleurs, voire parfois complètement faux sur le site Android developer
AndroidManifest.xml: permission, orientation, icône
- Il convient en premier lieu de permettre à l’application Geek01 d’accéder à internet, sans cette permission spécifique l’appli ne pourrait afficher le site HTML cible, pour cela on ajoute la ligne
- si rien n’est prévu pour la gestion de l’orientation de l’écran, alors la procédure Oncreate de l’activité sera appelée à chaque fois que l’utilisateur tournera son mobile (ça c’est la théorie car ici l’appli se ferme carrément!) pour éviter ce plantage on ajoute l’attribut android:configChanges dans la balise activity
android:configChanges="orientation"
- Comment donner une icône à l’application?
Dans le répertoire /res nous allons placer les icônes geek01.png en diverses tailles (pour s’adapter aux diverses tailles d’écran des mobiles et tablettes )
dans ./res/drawable-ldpi l’image geek01.png en 36×36 , ./res/drawable-mdpi en 48×48, ./res/drawable-hdpi en 72×72
Ensuite nous ajoutons dans la balise application l’attribut android:iconandroid:icon="@drawable/geek01"
Afficher un site web http dans une application Android
- Dans le layout principal (main.xml), nous positionnons un webview webkit:
- Dans le code source Java (fichier Geek01Activity.java) nous créons une procédure qui initialisera le contenu du WebView et chargera le site. La fonction loadUrl(monurl) charge l’url du site, nous aurions pu mettre loadUrl(« http://geek01.com »), mais nous avons préféré définir l’url en dur dans le fichier de ressources strings.xml plutôt que dans le code JAVA.(voir plus bas)
//procédure d'affichage et de chargement du site Geek01 public void ChargerLeSite(){ stgModeActuel="web"; //affichage du layout principal (celui qui contient le webview) setContentView(R.layout.main);//gestion du webview qui affichera le site WebView myWebView = (WebView) findViewById(R.id.webview1); myWebView.getSettings().setJavaScriptEnabled(true); //chargement du site http dans le webview //on utilise la methode getString de la variable de contexte pour récupérer l'url car R.string.url_geek01 est un entier référence... myWebView.loadUrl(s_appContext.getString(R.string.url_geek01)); //NB on pourrait aussi charger un fichier local ainsi:myWebView.loadUrl("file://sdcard/"); myWebView.setWebViewClient(new WebViewClient()); //permet d'ouvrir les liens url dans le webview et non dans le navigateur myWebView.setInitialScale(1); // facteur de zoom initial myWebView.getSettings().setBuiltInZoomControls(false); // ne pas afficher le contrôle de zoom myWebView.getSettings().setUseWideViewPort(true); // activer le double-tap pour zoomer } - Création de l’activité principale
/** Appelé lors de la 1ère création de l'activité */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //initialisation de la variable de contexte //cette variable permettra la récupération directe du contenu des chaînes de caractères de strings.xml //(car R.string.x renvoie un entier et non la chaîne x s_appContext = this.getApplicationContext(); ChargerLeSite(); } - Gestion du bouton Retour (back)
Le bouton back est un vrai problème dans notre application:
lorsqu’on est sur le webview (c’est à dire sur le site HTML encapsulé dans l’application), le bouton retour doit faire un back de navigation (retour à la page précédente), mais si on est sur le formulaire de contact mail, le bouton back doit alors renvoyer sur le webview. Pour s’en sortir on crée une fonction personnalisée onBackPressed qui surcharge la fonction de gestion normale
//gestion du bouton back
//il faut que le back entraine un retour dans la navigation du site dans le webform
//si on ne fait rien le back sortirait de l'application!
@Override
public void onBackPressed() {
if (stgModeActuel=="web"){
//on est dans le webview
WebView myWebView = (WebView) findViewById(R.id.webview1);
//si le back est possible dans la navigation, il faut le faire
if (myWebView.canGoBack()) {
myWebView.goBack();
}
else
{
//fonctionnement habituel du back car on ne peut faire de retour web
moveTaskToBack(true);
}
return;
}
else
//on est sur une page secondaire, le back doit recharger la page Accueil de l'appli, c'est à dire le site
{
ChargerLeSite();
return;
}
}
Ajouter un Menu à l’application
- Dans la classe de l’activité principale, nous déclarons chaque élément du menu comme un nombre entier
//variables du menu public static final int intMenu_Geek01 = Menu.FIRST; public static final int intMenu_Contact = 2; public static final int intMenu_Exit = 3;
- Pour créer chaque bouton du menu, on remplace la fonction onCreateOptionsMenu par une fonction personnalisée. menu.add permet l’ajout des éléments du menu
//Construction du Menu @Override public boolean onCreateOptionsMenu(Menu menu) { // TODO Auto-generated method stub boolean result = super.onCreateOptionsMenu(menu); //option menu Geek01 menu.add(0, intMenu_Geek01, 0, R.string.menu_geek01); //option menu: Contact menu.add(0, intMenu_Contact, 1, R.string.menu_contact); //option menu: Sortie menu.add(0, intMenu_Exit, 2, R.string.menu_exit); return result; } - Pour gérer le comportement du menu, on utilise la fonction onOptionsItemSelected (voir plus bas)
Gérer un formulaire de contact mail
- Les ressources textuelles, les couleurs utilisées dans l’application ne sont pas contenues dans le code java, ni dans les layers, mais dans le fichier res/values/strings.xml
<!--?xml version="1.0" encoding="utf-8"?--> Geek01.com Contacter l\'auteur! Message Objet Envoi Geek01 version 0.1 - code source disponible sur http://geek01.com Exit Cont@ct Geek01 http://geek01.com toto@turlututu.com Envoi du message via: #333333 - Attention le code java pour récupérer un élément de strings.xml est: R.string.nomdelachaine, MAIS la valeur renvoyée n’est pas la chaîne de caractère elle-même mais un entier référence la représentant. Pour accéder à la chaîne on utilisera ici une variable de contexte
s_appContext = this.getApplicationContext(); ... ... String stgMailTo = s_appContext.getString(R.string.email_geek01);
- les éléments graphiques (textview, edittext, etc) sont créés dans un layout à part (contact_layer.xml) différent du principal(main.xml). Ce layout sera affiché par la commande Java suivante:
setContentView(R.layout.contact_layer);
- Le comportement du formulaire de contact est géré dans la fonction de gestion du menu onOptionsItemSelected.
IL est intéressant de noter que l’envoi de mail est en fait un simple passage d’info au client mail que choisira l’utilisateur suite à l’appel final startActivity(Intent.createChooser). D’aucuns diront qu’il serait plus élégant d’envoyer directement le mail par programmation en sollicitant un serveur SMTP, certes mais si Android permettait un tel usage, il serait alors très facile de transformer un mobile en zombie, capable d’envoyer des spams à la terre entière…//gestion du menu @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch (item.getItemId()) { //clic sur le menu contact case intMenu_Contact: //changement de layer (on sort de main pour aller dans le contact layer) setContentView(R.layout.contact_layer); stgModeActuel="contact"; //-----------------Gestion Envoi Mail------------- send=(Button) findViewById(R.id.emailsendbutton); txtSubject=(EditText) findViewById(R.id.emailObjet); emailtext=(EditText) findViewById(R.id.emailtext); //gestion du clic sur le bouton d'envoi du message send.setOnClickListener(new OnClickListener() { public void onClick(View v) { String stgMailTo = s_appContext.getString(R.string.email_geek01); // création d'un intent pour envoyer l'email via l'application messagerie du mobile final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); //emailIntent.setType("text/plain"); //propose une liste d'appli dont certaines n'ont rien à voir emailIntent.setType("message/rfc822");//selectionne uniquement les appli mails, s'il n'y a que gmail il s'ouvre directement, sinon liste de choix d'appli (k9, gmail...) //passage de l'adresse destinataire emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[]{stgMailTo}); //sujet du message //attention EXTRA_SUBJECT attend une string >> tostring emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,txtSubject.getText().toString()); //corps du message //EXTRA_TEXT attend une charsequence qu'on récupère directement dans emailtext par la métode getText emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, emailtext.getText()); //Rock'n'roll! Geek01Activity.this.startActivity(Intent.createChooser(emailIntent, s_appContext.getString(R.string.email_txtEnvoi))); } }); //-----------------fin Gestion email--------------- return true; //clic sur menu sortie case intMenu_Geek01: ChargerLeSite(); return true; //clic sur menu sortie case intMenu_Exit: finish(); return true; } return super.onOptionsItemSelected(item); }
Comment fermer complètement l’application android?
- Dans le menu nous avons positionné un bouton exit, ce bouton déclenche l’appel à la fonction finish()
- Pour fermer et sortir de notre applicationproprement et complètement , en tuant tous ses processus, et fermant ses ressources, nous alons personnaliser onDestroy
//onDestroy est appelé lorsque finish est invoqué sur l'activité @Override public void onDestroy() { super.onDestroy(); //demande au système de fermer tout objet de l'application de sorte que l'appli puisse être tuée sans risque //true implique que le processus ne sera tué que quand tous les threads auront été fermés System.runFinalizersOnExit(true); //force l'application à se fermer complètement et à ne passer en arrière-plan System.exit(0); }



Pingback: Meilleures applications Android, mon market à moi! | Geek01
Ouh le vilain System.exit(0)
((
Ca ne se fait pas ce genre de chose
Normalement, il me semble qu’il suffit d’un « finish() » et on laisse l’OS géré ça tranquillement.
En fait c’est voulu! System.finish ne tue pas le processus, il ferme l’activité et bascule le processus en arrière-plan. Personnellement je trouve plus propre de tuer complètement le processus, puisque l’appli n’a pas vocation à rester en arrière plan…
Bonjour,
Compilé sous eclipse et testé sur un Galaxy SII, l’application affiche une page noire puis se ferme.
Dommage
Impossible de l’importer dans eclipse et de générer un apk sans avoir une seule erreur…