Intégrer une page WEB dans une application ANDROID
didacticiel réalisé par Sitelec.org pour la société
Table des matières
Références...2
Installation d'Android Studio...2
Intégrer une WebView à l'application...2
Permissions...3
Effacer le cache de la WebView...3
Ouvrir le lien dans la WebView...3
Générer les icônes...4
Test sur simulateur logiciel...4
Test sur smartphone...4
Générer l'application...4
Ajouter des actions à l'ActionBar...5
Vue des pages de l'application...5
Fichiers de l'application...6
Application Android pour Modulo-AELSYS...7
Fichiers de l'application Modulo-AELSYS...8
Fichiers commentés de l'application Modulo-AELSYS...11
Mini serveur WEB...15
Références
https://developer.android.com/guide/webapps/webview.html http://tutos-android-france.com
https://openclassrooms.com/courses/developpez-une-application-pour-android
Installation d'Android Studio
Télécharger Android Studio (1,6 Go)
https://developer.android.com/studio/index.html
Installer Android Studio Démarrer Android Studio
Choisir le type de setup STANDARD
Cocher Android Virtual Device Next Finish Attendre la fin du téléchargement...
Configurer Configure | Project Defaults | Project Structure | SDKs Donner le chemin du dossier SDK (exemple: C:\Android\sdk)
Commencer un nouveau projet (Start a new Android Studio project) Configurer le projet (Configure your new project)
Application name: parking Company name: artaud
Next
Cocher Phone and Tablet
Next
Choisir Empty Activity et donner un nom à l'activité: Parking
Finish
Intégrer une WebView à l'application
La WebView permet le rendu visuel de la page Web à afficher
Pour ajouter une WebView à l'application, il suffit d'inclure l'élément <WebView> dans le fichier de disposition des éléments (layout) qui se trouve dans: app > res > layout
> activity_parking.xml (onglet Text en bas)
Effacer le contenu de ce fichier et le remplacer par le code suivant, qui permet de dimensionner la WebView à l'écran:
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
Pour ouvrir une page dans la WebView au démarrage de l'application Ouvrir le fichier app > java > artaud.parking > Parking.java
Ajouter sous la ligne:
package artaud.parking;
la ligne:
import android.webkit.WebView;
Ajouter à la fin de la méthode onCreate (avant l’accolade fermante):
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.loadUrl("http://sitelec.org/android/test_smartphone.htm");
Permissions
L'application a besoin d'accéder au réseau, il faut donc lui donner cette permission dans le fichier AndroidManifest.xml
app > manifests > AndroidManifest.xml
et ajouter à la fin, juste avant la balise </manifest> la ligne suivante:
<uses-permission android:name="android.permission.INTERNET" />
Pour autoriser le JavaScript, insérer dans le fichier Parking.java les 2 lignes en surbrillance
WebView myWebView = (WebView) findViewById(R.id.webview);
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.loadUrl("http://sitelec.org/android/test_smartphone.htm");
Ajouter sous la ligne:
package artaud.parking;
la ligne:
import android.webkit.WebSettings;
Effacer le cache de la WebView
Pour effacer le cache de la WebView, insérer la ligne en surbrillance webSettings.setJavaScriptEnabled(true);
myWebView.clearCache(true);
myWebView.loadUrl("http://sitelec.org/android/test_smartphone.htm");
Ouvrir le lien dans la WebView
Par défaut, les liens de la page contenue dans la WebView s'ouvrent dans le navigateur. Pour ouvrir les liens dans la WebView, insérer la ligne en surbrillance
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());
WebSettings webSettings = myWebView.getSettings();
Ajouter aussi au package:
import android.webkit.WebViewClient;
Générer les icônes
Utiliser le générateur d’icônes pour Android
https://romannurik.github.io/AndroidAssetStudio/icons-launcher.html
Ce générateur fournit un fichier ZIP contenant les icônes de différentes dimensions Remplacer les dossiers mipmap-xx du dossier \app\src\main\res
par les dossiers du même nom présents dans le ZIP
Test sur simulateur logiciel
Build > Make Project puis Run > Run 'app'
La première fois, il faut ajouter un simulateur logiciel avec le bouton Create New Virtual Device
Choisir :
Category: Phone Name: Nexus 5
Next
Release name: par défaut (Nougat)
Finish
De retour dans la première fenêtre ouverte par le menu Run 'app' OK
Patienter pendant le démarrage du simulateur jusqu'au lancement automatique de l'application...
Test sur smartphone
Sur le smartphone, activer le mode débogage USB (option pour les développeurs) Connecter le smartphone à l'ordinateur par le câble USB
Le driver nécessaire peut s'installer automatiquement...
Dans le cas contraire, il faut le rechercher manuellement
Build > Build APK > Run 'app' > choisir l'élément connecté > OK
Générer l'application
Build > Generate Signed APK Create new...(Key store path)
Indiquer le Key store path avec le nom du fichier, par exemple:
C:\Users\Patrick ABATI\AndroidStudioProjects\parking\app\parking.jks et donner un mot de passe
puis un alias (exemple: sitelec) avec mot de passe
puis un champ Certificate (exemple: Organization sitelec.org)
Next
Finish
L'application se trouve dans le dossier app et se nomme app-release.apk
Ajouter des actions à l'ActionBar
http://tutos-android-france.com/menu-ajouter-des-actions-a-lactionbar/
L'ActionBar placée en haut de l'écran, permet d'afficher le titre de l'activité (parking) Elle permet aussi d'ajouter des actions
Créer un fichier res/menu/menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_IP"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/action_IP"
app:showAsAction="ifRoom" />
</menu>
Afin d’utiliser menu.xml en tant qu’icône de l'ActionBar, il faut l’indiquer au menuInflater lors du onCreateOptionsMenu (voir fichier Parking.java) L'actionBar sera utilisée pour configurer l'adresse réseau du Modulo
Vue des pages de l'application
http://sitelec.org/android/test_smartphone.htm http://sitelec.org/android/test_smartphone2.htm
Fichiers de l'application
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="artaud.parking">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".Parking">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Parking.java
package artaud.parking;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebViewClient;
public class Parking extends AppCompatActivity { @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parking);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.clearCache(true);
myWebView.loadUrl("http://sitelec.org/android/test_smartphone.htm");
}
//ajoute le menu à l'ActionBar @Override
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
}
Application Android pour Modulo-AELSYS
L'application finale gère la définition de l'adresse réseau du Modulo Aelsys. Elle peut être téléchargée à l'adresse:
http://sitelec.org/android/ parking .apk La page Web du Modulo se trouve ici:
http://sitelec.org/android/parking.html
avec sa feuille de style http://sitelec.org/android/style.css Il faut la mettre dans le dossier \FlashDisk\WWW du Modulo
Le dossier source est disponible ici : http://sitelec.org/android/parking.zip
Il doit être décompressé et mis dans le répertoire C:\Users\...\AndroidStudioProjects Pour un fonctionnement sur le réseau local, le smartphone doit être mis sur WiFi et le Modulo doit se trouver sur le même réseau avec une adresse du type http://192...
Page de configuration d'adresse Page parking.html
accessible par implantée dans le modulo Attention !
L'adresse doit être de la forme http://...
Fichiers de l'application Modulo-AELSYS
activity_parking.xml
<?xml version="1.0" encoding="utf-8"?>
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/webview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
popup.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/popup_1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10sp" >
<TextView
android:id="@+id/txtView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="30sp"
android:text="@string/modulo_address" />
<EditText
android:id="@+id/adress_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textSize="16sp"
android:inputType="text"/>
<Button
android:id="@+id/sauve"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/save"/>
</LinearLayout>
menu.xml
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_IP"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/action_IP"
app:showAsAction="ifRoom" />
</menu>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="artaud.parking">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity android:name=".Parking">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
Parking.java
package artaud.parking;
import android.content.Context;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class Parking extends AppCompatActivity { public void initializeWebView() {
setContentView(R.layout.activity_parking);
WebView myWebView = (WebView) findViewById(R.id.webview);
myWebView.setWebViewClient(new WebViewClient());
WebSettings webSettings = myWebView.getSettings();
webSettings.setJavaScriptEnabled(true);
myWebView.clearCache(true);
myWebView.loadUrl(load_address());
}
// charge l'addresse du Modulo depuis les préférences enregistrées public String load_address() {
SharedPreferences sharedPref = Parking.this.getPreferences(Context.MODE_PRIVATE);
return sharedPref.getString("address_modulo",null);
}
// sauve l'addresse du Modulo
public void save_address(String address_modulo) {
SharedPreferences sharedPref = Parking.this.getPreferences(Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPref.edit();
editor.putString("address_modulo", address_modulo);
editor.apply();
}
//affiche la WebView @Override
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
this.initializeWebView();
}
//ajoute le menu à l'ActionBar @Override
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu);
return true;
}
//gère le click sur une action de l'ActionBar @Override
public boolean onOptionsItemSelected(MenuItem item) { setContentView(R.layout.popup);
String address_modulo = load_address();
EditText editText;
editText = (EditText) findViewById(R.id.adress_input);
editText.setText(address_modulo);
//gère le click sur le bouton Enregistrer
final Button Enregistrer = (Button) findViewById(R.id.sauve);
Enregistrer.setOnClickListener(new View.OnClickListener() { public void onClick(View v) {
EditText editText;
editText = (EditText) findViewById(R.id.adress_input);
save_address(editText.getText().toString());
Toast.makeText(Parking.this, "Configuration...", Toast.LENGTH_SHORT).show();
Parking.this.initializeWebView();
} });
return super.onOptionsItemSelected(item);
} }
strings.xml
<resources>
<string name="app_name">parking</string>
<string name="action_IP">action_IP</string>
<string name="modulo_address">Adresse du Modulo</string>
<string name="save">Enregistrer</string>
</resources>
Fichiers commentés de l'application Modulo-AELSYS
activity_parking.xml
une activité permet d'afficher un composant à l'écran et d'interagir avec l'utilisateur
<?xml version="1.0" encoding="utf-8"?>
utf-8:norme de codage des caractères des fichiers xml
<WebView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns (namespace) crée un espace de nom unique pour éviter les conflits et pointe vers un Uri (Uniform Resource Identifier)
android:id="@+id/webview"
identifiant de la WebView
android:layout_width="fill_parent"
fixe la pleine largeur de la WebView
android:layout_height="fill_parent"
fixe la pleine hauteur de la WebView
/>
menu.xml
une ActionBar est la barre qui se trouve en haut de l'application
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns (namespace) crée un espace de nom unique pour éviter les conflits et pointe vers un Uri (Uniform Resource Identifier)
xmlns:app="http://schemas.android.com/apk/res-auto">
idem
<item
android:id="@+id/action_IP"
identifiant de l'élément (voir fichier strings.xml)
android:icon="@android:drawable/ic_menu_preferences"
ajoute une icône
android:title="@string/action_IP"
ajoute un titre action_IP (voir fichier strings.xml)
app:showAsAction="ifRoom" />
ajoute cet élément aux actions principales de l’ActionBar si une place est disponible
</menu>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
utf-8:norme de codage des caractères des fichiers xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns (namespace) crée un espace de nom unique pour éviter les conflits et pointe vers un Uri (Uniform Resource Identifier)
package="artaud.parking">
identifiant de l'application
<application
android:allowBackup="true"
détermine si les données de l'application peuvent être sauvées ou restaurées
android:icon="@mipmap/ic_launcher"
récupère l'icône de lancement de l'application présente dans le dossier mipmap
android:label="@string/app_name"
récupère le nom de l'application (parking) (voir fichier strings.xml)
android:theme="@style/AppTheme">
récupère le thème AppTheme du fihier styles.xml pour appliquer le même style à toute l'application
<activity android:name=".Parking">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
indique qu'il s'agit de l'activité principale de l'application
<category android:name="android.intent.category.LAUNCHER" />
indique que cette activité est présente dans le lanceur d'application
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.INTERNET" />
autorise l'application à se connecter à Internet
</manifest>
popup.xml
<?xml version="1.0" encoding="utf-8"?>
utf-8:norme de codage des caractères des fichiers xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
un layout est une vue qui contient d'autres vues: c'est la première vue d'une interface
LinearLayout signifie que toutes les vues qu'il contient sont alignées verticalement ou horizontalement
android:id="@+id/popup_1"
identifiant de la popup
android:layout_width="fill_parent"
fixe la pleine largeur de la popup
android:layout_height="fill_parent"
fixe la pleine hauteur de la popup
android:orientation="vertical"
spécifie que les éléments contenus dans le layout sont alignés verticalement
android:padding="10sp" >
fixe les marges de la popup en sp (sp:Scale-independent Pixel )
<TextView
création d'une zone d'affichage de texte
android:id="@+id/txtView"
identifiant de la zone de texte
android:layout_width="wrap_content"
adapte la largeur de la zone de texte à son contenu
android:layout_height="wrap_content"
adapte la hauteur de la zone de texte à son contenu
android:layout_gravity="center"
centre la zone de texte
android:textSize="30sp"
affiche le texte en taille 16sp (sp:Scale-independent Pixel )
android:text="@string/modulo_address" />
affiche le texte dans la zone Adresse du Modulo (voir fichier strings.xml)
<EditText
création d'une zone d'entrée de texte
android:id="@+id/adress_input"
identifiant de la zone de texte
android:layout_width="fill_parent"
fixe la pleine largeur de la zone de texte
android:layout_height="wrap_content"
fixe la hauteur de la zone de texte en fonction de son contenu
android:layout_gravity="center"
centre la zone de texte
android:textSize="16sp"
affiche le texte en taille 16sp (sp:Scale-independent Pixel )
android:inputType="text"/>
définit le format des données entrées (type texte)
<Button
création d'un bouton
android:id="@+id/sauve"
identifiant du bouton
android:layout_width="wrap_content"
adapte la largeur du bouton au texte qu'il contient
android:layout_height="wrap_content"
adapte la hauteur du bouton au texte qu'il contient
android:layout_gravity="center"
centre le bouton
android:text="@string/save"/>
écrit le texte du bouton Enregistrer (voir fichier strings.xml)
</LinearLayout>
strings.xml
<resources>
<string name="app_name">parking</string>
<string name="action_IP">action_IP</string>
<string name="modulo_address">Adresse du Modulo</string>
Parking.java
package artaud.parking;
import android.content.Context;
import android.content.SharedPreferences;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.webkit.WebViewClient;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
importe les différentes librairies
public class Parking extends AppCompatActivity { public void initializeWebView() {
setContentView(R.layout.activity_parking);
intègre la WebView dans l'application
WebView myWebView = (WebView) findViewById(R.id.webview);
définit la WebView (R est une classe de ressources)
myWebView.setWebViewClient(new WebViewClient());
ouvre les liens dans la WebView
WebSettings webSettings = myWebView.getSettings();
permet de changer les paramètres de la WebView
webSettings.setJavaScriptEnabled(true);
autorise le JavaScript
myWebView.clearCache(true);
efface le cache de la WebView
myWebView.loadUrl(load_address());
charge la page web du Modulo
}
// charge l'addresse du Modulo depuis les préférences enregistrées public String load_address() {
SharedPreferences sharedPref = Parking.this.getPreferences(Context.MODE_PRIVATE);
les SharedPreferences sont des espaces de stockages avec un système de clé/valeur
return sharedPref.getString("address_modulo",null);
récupère l'adresse du Modulo dans la clé "address_modulo"
}
// sauve l'addresse du Modulo
public void save_address(String address_modulo) {
SharedPreferences sharedPref = Parking.this.getPreferences(Context.MODE_PRIVATE);
les SharedPreferences sont des espaces de stockages avec un système de clé/valeur
SharedPreferences.Editor editor = sharedPref.edit();
appelle la méthode edit() de l'objet SharedPrefences
editor.putString("address_modulo", address_modulo);
insère l'adresse du Modulo dans la clé "address_modulo"
editor.apply();
enregistre la clé
} //affiche la WebView @Override
cette annotation est un marqueur utilisé par le compilateur pour vérifier la réécriture des méthodes héritées
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
initialise la WebView
this.initializeWebView();
initialise la WebView
}
//ajoute le menu à l'ActionBar @Override
cette annotation est un marqueur utilisé par le compilateur pour vérifier la réécriture des méthodes héritées
public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu, menu);
affiche le menu fichier menu.xlm
return true;
}
//gère le click sur une action de l'ActionBar @Override
cette annotation est un marqueur utilisé par le compilateur pour vérifier la réécriture des méthodes héritées
public boolean onOptionsItemSelected(MenuItem item) { setContentView(R.layout.popup);
String address_modulo = load_address();
charge l'adresse du Modulo dans la variable adress_modulo
EditText editText;
crée la variable editText
editText = (EditText) findViewById(R.id.adress_input);
affecte la variable editText à la zone de texte voir le fichier popup.xlm
editText.setText(address_modulo);
mettre l'adresse du Modulo dans la variable editText
//gère le click sur le bouton Enregistrer
final Button Enregistrer = (Button) findViewById(R.id.sauve);
déclare le bouton Enregistrer voir le fichier strings.xlm
Enregistrer.setOnClickListener(new View.OnClickListener() {
teste le bouton Enregistrer
public void onClick(View v) { EditText editText;
crée la variable editText
editText = (EditText) findViewById(R.id.adress_input);
affecter la variable editText à la zone de texte voir le fichier popup.xlm
save_address(editText.getText().toString());
sauve l'adresse du Modulo
Toast.makeText(Parking.this, "Configuration...", Toast.LENGTH_SHORT).show();
ouvre une petite popup pour afficher le message pendant une courte durée
Parking.this.initializeWebView();
initialise la WebView
} });
return super.onOptionsItemSelected(item);
appelle l'implémentation par défaut
} }
Mini serveur WEB
Il est possible de visualiser l'application à partir de l'émulateur Android (ou d'un smartphone sur WiFi) en installant sur l'ordinateur un mini serveur WEB
Télecharger MiniWeb HTTP server https://sourceforge.net/projects/miniweb/
Le ZIP contient :
- un exécutable miniweb.exe
- un dossier htdocs dans lequel se trouveront les pages html, css... nécesaires à l'application