Fiche Android : Encapsuler le web dans une application Android

Objet de la fiche :

État de la fiche


Plan de la fiche :

Avant propos

Créer une application android pour encapsuler votre page web dans une application android semble quelque chose de trés simple de prime abord. Lorsque l'on y regarde d'un peu plus prés c'est une autre affaire : par exemple si votre page web comporte des autorisations d'accés, des boites de dialogue javascript, du multimédia à démarrage automatique (par exemple un fond sonore), ou propose des fichiers à télécharger. D'autre part pour obtenir une application conviviale il faudra prévoir des menus spécifiques, des affichages personnalisés, un système de notification etc. Donc pas si simple.

Pré-requis (outils de développement)

Plateforme de développement Android Studio

Etapes pour créer l'application Android avec une webview


Outils de test

Ces outils consistent en une page web de test, et une application Android comportant tous les composants nécessaires pour supporter l'exploitation d'une page web dans une webview de façon la plus transparente possible.

Un site Web dans une application Android

Créer une application android pour encapsuler votre page web dans une application android semble quelque chose de trés simple de prime abord. Lorsque l'on y regarde d'un peu plus prés c'est une autre affaire : par exemple si votre page web comporte des autorisations d'accés, des boites de dialogue javascript, du multimédia à démarrage automatique (par exemple un fond sonore), ou propose des fichiers à télécharger. D'autre part pour obtenir une application conviviale il faudra prévoir des menus spécifiques, des affichages personnalisés, un système de notification etc. Donc pas si simple.

Pourquoi ce document ?

J'ai voulu un jour encapsuler mes pages pages Web dans une application Android. Pour le fun et pour améliorer mes connaissances sur les applications Android. Au cours de mes recherches j'ai vu que l'on pouvez encapsuler des pages web dans une application en utilisant l'objet WebView qui n'est rien d'autre que le navigateur chrome embarqué à cet effet et sur lequel on ajoute une couche utilisateur en java. Les avantages de ce type de montages sont interressant :

  • Réalisation d'une application Android très légère mais performante.
  • Mise à jour et modifications des informations pratiques par simple modification de la page web et immédiatement disponibles sur l'application.
  • Plus besoin d'accéder aux pages via un navigateur.
  • Design agréable et moderne.

Pour cela j'ai installé Android Studio et je me suis lancé dans la réalisation d'une application personnelle (Agenda) basé sur le principe de la webview Android à partir de la partie web que j'utilisai déjà de façon classique.

Au fur et à mesure de mes développements Android j'ai renconté pas mal de difficultés, et je me suis aperçu que la partie utilisateur n'était pas si simple que cela à adapter. Les informations internet donnent de bonnes idées mais rarement des exemples qui fonctionnent au premier coup.

C'est pour éviter aux nouveaux utilisateurs Android de tourner en round que j'ai fait ce document.

Accédez à la page de tests ?

La page donnant accés à tous les tests est disponible à l'adresse http://monwebfacile.free.fr/TestAndroid/testAndroid.htm

Cette page comporte des liens pour tester les différentes configurations que vous pourrez rencontrées lors de l'adaptation de votre application android avec webview.

Comment tester ?

Vous avez déja une application Android webview

  • Avec Android studio modifiez la pour pouvoir la connecter sur la page test : http://monwebfacile.free.fr/TestAndroid/testAndroid.htm
  • Régénérez un fichier apk d'installation et copiez le sur votre appareil.
  • Installez et démarrez l'application.

Vous n'avez pas d'application Android webview

  • Vous pouvez télécharger directement la dernière version de l'application Android de test qui vous est proposée ici : Application et l'installer sur votre appareil.
  • Ou vous pouvez télécharger les fichiers source de l'application de test proposés ici : Sources application y accéder avec Android studio, la consulter, faire des modifications, la recompiler et l'installer sur votre appareil.

Code Android

Boites de dialogue

Par défaut, Webview ne met pas en oeuvre les dialogues d'alerte Javascript, c'est à dire que alert() ou confirm() ou prompt() ne feront rien. Pour ce faire, on doit, dans l'application Android, d'abord activer Javascript sur la WebView (webView.getSettings().setJavaScriptEnabled(true);, et définir sur la WebView un Webchromeclient pour gérer entres autres mais pas exclusivement les demandes de dialogues d'alerte émises à partir de la page Web (webview).

Pour chacune de ces boites il faut appeler la super implémentation correspondante.

  • Pour la boite alert la super implémentation (@Override) onJsAlert(WebView view, String url, String message, final JsResult result)
  • Pour la boite confirm la super implémentation (@Override) onJsConfirm(WebView view, String url, String message, final JsResult result)
  • Pour la boite prompt la super implémentation (@Override) onJsPrompt(WebView view, String url, String message, String defaultValue, final JsPromptResult result)

Ces super implémentations sont appelées chaque fois qu'une alerte est émise par la page web. A chaque développeur Android de développer et personnaliser suivant ses goûts et ses besoins la forme et le style de chacune des boites.

Fenêtres pop-up et iframes

Les Pop-up

Les Webviews d'Android sont assez faciles à utiliser à l'exception notable de la Webchromeclient onCreateWindow. Il est appelé lorsque la webview souhaite que l'application hôte crée une nouvelle fenêtre. Et new est la clé. Si on ne cré pas une nouvelle webview, l'appel à onCreateWindow échoue, et celà sans exceptions ni erreurs !!.

Aprés avoir essayer pas mal de choses différentes qui toutes fonctionnaient de façon bancale, il m'a semblé que pour obtenir un résultat acceptable au fonctionnement de onCreateWindow, il faut créér un layout spécifique. Dans le layout de l'activité principale (webview) on rajoute à la vue Web principale une mise en page relative qui tiendra lieu de vue Web enfant une fois qu'elle est créée.

onCreateWindow est déclenché à chaque fois que l'utilisateur ouvre une fenêtre de type Popup si on autorise l'ouverture dans la webView : setJavaScriptCanOpenWindowsAutomatically(true);. Dans un navigateur, cela provoque l'ouverture du lien de destination dans une nouvelle fenêtre ou un nouvel onglet, mais dans une vue Web, il n'y a aucun moyen de le faire sans l'aide de l'application parent, d'ou l'appel à onCreateWindow et son comportement de lancer le navigateur si l'appel échoue.

C'est le travail de la méthode onCreateWindow. dans un premier temps la méthode supprime toutes les fenêtres enfants qui peuvent encore être attachés à browserLayout, ensuite, il rend l'ensemble enfantLayout visible qui par défaut est défini invisible. Ensuite, il faut créer une nouvelle webview et lui donner quelques paramètres pour la faire fonctionner correctement. Il s'agit alors d'informer la nouvelle webview qu'elle sera utilisée pour afficher le nouveau lien.

Ensuite, il faut définir le client webview pour avoir accès à la méthode onPageFinished qui permet,outre, de lire le titre de la vue, et de définir ce texte dans mainTitleText Textview.

Pour informer le système que la nouvelle webview sera utilisée pour la page du lien, on convertit les resultatsMsg.obj en Webviewtransport, et on appelle setWebView avec une référence à la nouvelle webview.

Les i-Frame

Pas de problème particulier. Les i-Frame sont chargées avec la page demandée.

ATTENTION

Le comportement des Pop-Up et I-Frame constitue une nouvelle classe de vulnérabilités WebView Android appelées vulnérabilités de contexte différentiel ou VCD.

En effet un iframe/popup web non fiable à l’intérieur de WebView peut être dangereux en pouvant lancer des attaques sur les solutions de défense existantes, et obtenir des privilèges tels que briser l’intégrité de la messagerie web, accéder furtivement à des fonctionnalités mobiles sensibles et effectuer des attaques d’hameçonnage.

Princialement en raison de l’absence de la barre d’adresse il est difficile pour les utilisateurs de savoir quel type de contenu web est chargé.

Les formulaires

  • Les formulaires classiques

    L'accés des formulaires ne présente normalement aucun problème, et est transparente pour la webview. Il convient toutefois de faire un test pour le confirmer.

  • Les formulaires avec requêtes AJAX

    L'utilisation de requêtes AJAX ne présente normalement aucun problème, et est transparent pour la webview. Il convient toutefois de faire un test pour le confirmer.

  • Le tag "select"

    De base le tag SELECT affiche ses options en utilisant la boite de dialogue native d'Android. En fait en l'état actuel, il est trés mal géré par le système de web view Android.

    Normalement après appui sur le tag select l'affichage des options devrait ressembler à ceci :

    mais en fait il ressemble à celà :
    ou l'on peut constater que les styles sont complètement perdus.

    Donc si l'on désire maitriser les styles du tag html select dans une webview Android, la seule solution pour le moment est de créer un équivalent en div du tag HTML.

    Pour celà on se réfèrera à la fiche http://monwebfacile.free.fr/Tutoriaux/JVS/JVS_Formulaires.php#personnalisationselectDiv"

  • Le tag "input type file"

    Par défaut, Webview ne met pas en oeuvre la sélection de fichiers à partir du tag select de type file. La boite est affichée mais ne fait rien. Pour ce faire, on doit définir dans l'application Android, sur la WebView un Webchromeclient qui est normalement présent pour gérer entres autres mais pas exclusivement les demandes de dialogues d'alerte émises à partir de la page Web (webview).

    Pour ce type de tag il faut appeler une super implémentation relative à ce cas (@Override) onShowFileChooser(WebView webView, ValueCallback filePathCallback,WebChromeClient.FileChooserParams fileChooserParams) {}.

    Cette super implémentation est appelée chaque fois que l'on clique sur la boite de sélection de fichiers affichée par la webview.

    La plus simple des solutions est de traiter l'appel dans onShowFileChooser par un Intent qui va appeler le sélecteur de fichier installer sur l'appareil et retourner le résultat dans la procédure onActivityResult


    En temps normal l'affichage de la boite de sélection de fichier s'affiche de la façon suivante dans la webview :

Méthode par Intent

Remarque : AndroidManifest.xml
onActivityResult n'est pas activée en fin d'activité secondaire filechooser ou d'autres activités si dans le manifest et pour l'activité principale android:noHistory est à true.
La valeur true signifie que l'activité ne laissera pas de trace de son historique. Il n'y aura aucune information de retour sur la pile. Ainsi un utilisateur ne pourra revenir sur l'activité d'origine.

Les Notifications

La classe NotificationManager :

Les notifications sont basées sur cette classe pour informer l’utilisateur des événements qui se produisent. C'est une manière de l'informer que quelque chose s’est passé en arrière-plan.

Les notifications peuvent prendre différentes formes :

  • Une icône persistante qui va dans la barre d’état et est accessible par le lanceur. lorsque l’utilisateur la sélectionne, une action dédiée (intention) peut être lancée,
  • Allumer ou clignoter des LED sur l’appareil,
  • Alerter l’utilisateur en faisant clignoter le rétro-éclairage, en jouant un son ou en vibrant.

La classe NotificationChannel (type public final) :

À partir d’Android 8.0 (API niveau 26), toutes les notifications doivent être attribuées à un canal sinon elles ne seront pas affichées.
En catégorisant les notifications en canaux, les utilisateurs peuvent maintenant désactiver certains canaux de notification pour une application individualisée (au lieu de désactiver toutes les notifications), et contrôler les options visuelles et auditives pour chaque canal, à partir des paramètres du système Android.
Les utilisateurs peuvent également en appuyant longuement sur une notification, modifier les comportements du canal associé (Arrêter les notifications/ Continuer d'afficher les notifications).

Ainsi une application peut avoir plusieurs canaux de notification – un canal distinct pour chaque type de notification, et aussi créer des canaux de notification en réponse aux choix faits par les utilisateurs de votre application. Par exemple, vous pouvez configurer des canaux de notification distincts pour chaque groupe de conversation créé par un utilisateur dans une application de messagerie.
On peut spécifier le niveau d’importance des notifications de l'application, afin que toutes les notifications postées sur le même canal de notification aient le même comportement.

Bug avec channel.setSound()

En théorie .setSound() permet de jouer le son que l'on a défini dans le canal, mais en fait uniquement celui que l'on a défini la première fois que l'on a créé le canal, sauf si on supprime le canal et en rajoute un nouveau. Cette information est enregistrée dans les paramètres Android de l'appareil.
Cela permet à l’utilisateur de l'appareil de modifier le son du canal (et tous les autres paramètres) via les paramètres Android. Donc, en principe il n’y a aucun besoin ou avantage pour le développeur à ajouter le canal chaque fois qu'il désire envoyer un push de notification car le fait qu’il s’exécute une fois sur l’installation de l’application est suffisant.

En fait, il y a un bug :

La raison pour cela est que lorsque vous créez un canal avec NotificationManager.IMPORTANCE_DEFAULT l'enregistrement Android sera fait en tant que NotificationManager.IMPORTANCE_HIGH (joue son par défaut).

La solution est d'utiliser NotificationManager.IMPORTANCE_LOW et de créer un nouveau canal. Une fois qu'un canal est créé, on ne peut plus modifier l'importance (bon on peut toujours tenter de le faire, mais l'importance nouvelle est ignoré). Ces informations semblent avoir été stockées de façon permanente par le système et le canal créé ne peut être supprimé que par une désinstallation de l'application ou par programmation : suppression via .deleteNotificationChannel(nChannel.getId()); puis recréation avec .createNotificationChannel(nChannel);. Attention dans ce dernier cas il y a une limite : on ne peut pas créer un canal avec le même id de la suppression et s'attendre à être en mesure d'appliquer des paramètres différents pour le nouveau canal.

La classe NotificationCompat

Cette classe fournit une interface utilisateur permettant de régler les préférences de notification pour l'application qui la contient.

Action builder de la classe de construction pour les objets NotificationCompat, permet un contrôle plus facile de tous les flags, et aide à construire les mises en page typiques des notifications.

Les Mails

Procédures utilitaires utilisées dans le projet

 Application au projet de site web


Respectons la propriété intellectuelle