applications java - Ivan Madjarov

publicité
APPLICATIONS
JAVA
Android
Partie IV
Ivan MADJAROV - 2014
Applications Java sous Android
IvMad, 2011-2014
4. Application réseaux,
Bluetooth, Wi-Fi, TCP,
Géolocalisation
Android
L'objectif principal de ce cours est de découvrir la programmation sous
Android, sa plate-forme de développement et les spécificités du développement
embarqué sur téléphone mobile. Le cours s’inspire, reprend, modifie et enrichi
des supports disponibles sur Internet.
2
Applications Java sous Android
IvMad, 2011-2014
3
Android : LogCat view
• Le développement pose toujours le problème de tester l'application
avant sa mise en "service". La View de l'application est en mode
graphique. Les logs permettent l'affichage en mode texte dans la
fenêtre du LogCat.
• Pour afficher les opérateurs 'log' dans Eclipse il faut activer le LogCat
view:
• Window->Show View->Other...->LogCat.
• Pour écrire un opérateur 'Log' il faut importer la classe android.util.Log
qui propose les méthodes Log.i() "Info", Log.d() "Debug", Log.w()
"Warning", Log.e() "Error" .
• Exemple:
• Log.i("NameActivity", "Bonjour, ça marche!");
Applications Java sous Android
IvMad, 2011-2014
4
Android : Bluetooth (1)
• Bluetooth est un protocole d'interconnexion à de courtes distances, de
type "peer-to-peer" avec une bande passante faible. La communication est
cryptée entre les périphériques appariés. L'API Bluetooth permet de
scanner et de lier les appareils entre eux et de transférer des données.
• Les connexions Bluetooth sont gérées par les classes suivantes :
• BluetoothAdapter : est l'unité locale où l'application Bluetooth est lancée.
• BluetoothDevice : est le périphérique distant avec lequel on cherche à
communiquer.
• BluetoothSocket : fait une demande de connexion au périphérique distant par
l'appel de la méthode createRfcommSocketToServiceRecord.
• BluetoothServerSocket : installe un Socket Bluetooth serveur pour écouter les
demandes de connexion entrantes en utilisant la méthode
listenUsingRfcommWithServiceRecord.
Applications Java sous Android
IvMad, 2011-2014
5
Android : Bluetooth (2)
• Pour s'assurer que le périphérique possède le Bluetooth on procéder à
une vérification rapide en instanciant la classe BluetoothAdapter. Le
retour de son objet va indiquer la présence ou non de cette option.
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null)
Toast.makeText(BluetoothActivity.this, "Pas de Bluetooth!", Toast.LENGTH_SHORT).show();
else
Toast.makeText(BluetoothActivity.this,"Le Bluetooth est disponible", Toast.LENGTH_SHORT).show();
• Pour autoriser l'opération, il faut ajouter la permission d'accéder aux
API Bluetooth en ajoutant la ligne suivante dans le fichier
AndroidManifest.xml :
<uses‐permission android:name="android.permission.BLUETOOTH"/>
Applications Java sous Android
IvMad, 2011-2014
6
Android : Bluetooth (3)
• Le Bluetooth peut être disponible sur l'appareil mais non activé. On peut
demander l'autorisation à l'utilisateur d'activer cette option. Pour cela,
on appelle la méthode startActivityForResult avec un paramètre d'Intent
BluetoothAdapter.ACTION_REQUEST_ENABLE. On vérifie que le
Bluetooth n'est pas activé et on demande son activation :
private final static int BLUETOOTH_ACTIVATION = 1;
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
........................................
if (!bluetoothAdapter.isEnabled() {
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), BLUETOOTH_ACTIVATION);
}
• Un dialog-box incitera l'utilisateur d'accepter ou non l'activation du
Bluetooth sur son appareil. Le résultat de sa décision est récupérable par
la méthode onActivityResult.
Applications Java sous Android
IvMad, 2011-2014
7
Android : Bluetooth (4)
• On surcharge la méthode onActivityResult pour savoir si le Bluetooth est
activé ou non. La méthode est appelée à la sortie de la boite de dialogue
@Override
protected void onActivityResult(int requestCode,int resultCode,Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == BLUETOOTH_ACTIVATION) {
if (resultCode == RESULT_OK) {
Toast.makeText(BluetoothActivity.this, "Bluetooth est activé", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(BluetoothActivity.this, "Bluetooth non activé", Toast.LENGTH_SHORT).show();
} }
}
Applications Java sous Android
IvMad, 2011-2014
Android : Bluetooth (5)
• Si on rend l'appareil Bluetooth détectable cela permet à d'autres appareils
de le découvrir et de se connecter par la suite. Pour cela, on utilise la
méthode startActivityForResult avec le paramètre Intent approprié :
startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE),
BLUETOOTH_SCAN);
• On obtient la liste des appareils déjà liés avec getBoundedDevices.
Set<BluetoothDevice> knownDevices = bluetoothAdapter.getBoundedDevices();
for (BluetoothDevice device : knownDevices) {
Log.v("BluetoothActivity", "appareil = " + devices.getName());
}
• Set : interface de collection pour des objets qui n'autorisent pas des
doublons dans l'ensemble, existe au moins un nul (un tableau d'objets).
• for-each : boucle qui accède à chaque élément d'une collection d'objets
comme dans un tableau (eg, ArrayList).
8
Applications Java sous Android
IvMad, 2011-2014
9
Android : Bluetooth (6)
• Le code complet (étudiez les instructions 'Set' et 'for') :
public class BluetoothDeviceListActivity extends Activity {
private final static int BLUETOOTH_SCAN = 1;
String s = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
startActivityForResult(new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE),BLUETOOTH_SCAN);
Set<BluetoothDevice> knownDevices =
bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : knownDevices) {
s += "appareil = " + device.getName();
}
Toast.makeText(BluetoothDeviceListActivity.this,"Les Bluetooth liés:
"+s,Toast.LENGTH_SHORT).show();
} }
Applications Java sous Android
IvMad, 2011-2014
10
Android : Bluetooth (7)
• La recherche d'appareils inconnus est un traitement asynchrone et
gourmant en energie effectué par le Broadcast Receiver.
• Android permet de créer une classe qui implémente BroadcastReceiver pour recevoir
des Intents et appliquer des comportements spécifiques au code.
• L’interface BroadcastReceiver possède une seule méthode onReceive() qu'on doit
implémenter.
BroadcastReceiver bluetoothReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Toast.makeText(BluetoothActivity.this, "New Device = " + device.getName(), Toast.LENGTH_SHORT).show();
}
} };
Applications Java sous Android
IvMad, 2011-2014
11
Android : BT (8) Mettre tout ensemble
Ajouter les
permissions dans le
fichier manifest.xml
Applications Java sous Android
IvMad, 2011-2014
12
Android : Wi-Fi (1)
• Sous Android le Wi-Fi est géré par un WifiManager. Le WifiManager
représente un Android Wi-Fi Connectivity Service. Il est capable de
configurer une connexion Wi-Fi, de gérer une connexion en cours, de
scanner pour des points d'accès et d'enregistrer tout changement dans
une connexion Wi-Fi.
• Le Wi-FiManager utilise la méthode getSystemService en précisant le type
de service en constante: Context.WIFI_SERVICE
String service = Context.WIFI_SERVICE;
WifiManager wifi = (WifiManager)getSystemService(service);
• Pour autoriser l'utilisation du Wi-FiManager les paramètres des
permissions pour accès et modification doivent être réglés dans le
fichier manifest du projet.
<uses‐permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses‐permission android:name="android.permission.CHANGE_WIFI_STATE"/>
Applications Java sous Android
IvMad, 2011-2014
13
Android : Wi-Fi (2)
• Avec le Wi-FiManager on peut notamment activer ou désactiver la
fonction Wi-Fi dans l'appareil par la méthode setWifiEnabled, obtenir le
statut actuel du Wi-Fi par la méthode getWifiState ou vérifier si le Wi-Fi
est activé avec la méthode isWifiEnabled.
if (!wifi.isWifiEnabled())
if (wifi.getWifiState() != WifiManager.WIFI_STATE_ENABLING)
wifi.setWifiEnabled(true);
• La méthode getWifiState() retourne un entier entre 0 et 4 pour indiquer
la situation en cours du WiFi de l'appareil :
0
1
2
3
4
‐
‐
‐
‐
‐
WIFI_STATE_DISABLING
WIFI_STATE_DISABLED
WIFI_STATE_ENABLING
WIFI_STATE_ENABLED
WIFI_STATE_UNKNOWN
Applications Java sous Android
IvMad, 2011-2014
14
Android : Wi-Fi (3)
• Si on met tout ensemble on peut vérifier l'état de notre appareil :
public class WiFiStateActivity extends Activity {
String[] wifiState = {"WIFI_STATE_DISABLING", "WIFI_STATE_DISABLED", "WIFI_STATE_ENABLING", "WIFI_STATE_ENABLED", "WIFI_STATE_UNKNOWN"};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String service = Context.WIFI_SERVICE;
WifiManager wifi = (WifiManager)getSystemService(service);
Toast.makeText(this, "Wi‐Fi : " + wifiState[wifi.getWifiState()], Toast.LENGTH_LONG).show();
}
}
Applications Java sous Android
IvMad, 2011-2014
15
Android : Wi-Fi (4)
• Pour obtenir des informations détaillées sur une connexion il faut se
référer à la méthode getConnectionInfo de la classe WifiInfo.
• Cette classe offre un certain nombre de méthodes qui apportent des
informations importantes sur les paramètres du réseau Wi-Fi:
• getSSID : Retourne l'identificateur du réseau 802.11 en cours;
• getBSSID() : Retourne l'identificateur de base de ce réseau;
• getMacAddress() : Retourne l'adresse MAC de l'appareil;
• getIpAddress() : Retourne l'adresse IP de l'appareil en format 'int'. Une
conversion en format 'String' est alors nécessaire.
• getLinkSpeed() : Retourne le débit en Mbps
• getRssi() : Retourne le niveau de puissance reçu du réseau 802.11 connecté.
Applications Java sous Android
IvMad, 2011-2014
Android : Wi-Fi (5)
• Afficher les éléments d'une connexion Wi-Fi en ajoutant les
composants dans un StringBuilder par la méthode append()
16
Applications Java sous Android
IvMad, 2011-2014
17
Android : Wi-Fi (6)
•
•
•
•
•
Avec le Wi-FiManager on peut procéder à la recherche des hotspot
(bornes Wi-Fi) dans le voisinage par la méthode startScan.
Pour effectuer cette opération il faut utiliser un Broadcasr Receiver avec
un Intent SCAN_RESULTS_AVAILABLE_ACTION passé en
paramètre. Cela assure un traitement asynchrone et la prise du résultat
quand le scan a terminé.
On appelle la méthode getScanResults pour obtenir les résultats sous la
forme d'une liste d'objets ScanResult.
Chaque objet du type ScanResult comporte les détails de la connexion
repérée.
Le résultat du Scan est récupéré dans un objet de type List<E>. C'est
une collection d'éléments indexés à partir de zéro.
List<ScanResult> results = wifi.getScanResults();
Applications Java sous Android
IvMad, 2011-2014
Android : Wi-Fi (7)
• Retourne le nombre de hotspot détectés et le SSID avec le plus fort
signale à proximité
18
Applications Java sous Android
IvMad, 2011-2014
19
Java Android : Géolocalisation (1)
• En général une unité mobile Android propose des moyens de
déterminer sa géolocalisation:
• Par le module GPS (Global Positioning System),
• Par triangulation des cellules mobiles (3G),
• Par le réseau Wifi.
• Pour une géolocalisation on implémente l'interface LocationListener.
• On s'adresse ensuite à l’objet LocationManager pour gérer l'abonnement
aux mises à jour des coordonnées GPS.
• Dans l'Activité (View) on surcharge 4 méthodes :
• onProviderEnabled est appelée quand une source de localisation est activée;
• onProviderDisabled est appelée quand une source de localisation est désactivée;
• onStatusChanged est appelée quand le statuts d’une source change;
• onLocationChanged est appelée quand les coordonnées GPS changent.
Applications Java sous Android
IvMad, 2011-2014
20
Java Android : Géolocalisation (2)
• Pour s’abonner à la mise à jour des coordonnées GPS, il faut utiliser la
méthode requestLocationUpdates(String, long, float, LocationListener) qui
possède 4 arguments :
• Le provider utiliser pour recevoir les mises à jour des coordonnées
utilisateurs (GPS / NETWORK …)
• L'intervalle minimum entre deux notifications (en millisecondes)
• L'intervalle minimum entre deux notifications (en mètre)
• L’instance du LocationListener
• Il est conseillé de s’abonner aux mises à jour des coordonnées GPS
dans la méthode onResume et de se désabonner dans la méthode onStop
afin de stopper l’utilisateur des ressources de localisation alors que
l’application n’en a plus l’utilité, sinon le processus de mise à jour
continu est la consommation de la batterie est importante.
Applications Java sous Android
IvMad, 2011-2014
21
Java Android : Géolocalisation (3)
• Pour trouver sa position il faut activer le service et le Manager qui le
gère :
String serviceString = Context.LOCATION_SERVICE;
LocationManager locationManager = (LocationManager)getSystemService(serviceString);
• Le fichier AndroidManifest.xml doit être enrichi avec les permissions
requises pour accéder aux services de localisation, Internet et au GPS:
<uses‐permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses‐permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses‐permission android:name="android.permission.INTERNET" />
Applications Java sous Android
IvMad, 2011-2014
22
Java Android : Géolocalisation (4)
L'activité teste les
'Providers' disponibles
Applications Java sous Android
IvMad, 2011-2014
23
Java Android : Géolocalisation (5)
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.Toast;
public class SimpleGeoLocalisationActivity extends Activity {
private LocationManager locationManager;
private LocationListener locationListener;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple_geo_localisation);
// On s'adresse à la classe LocationManager pour obtenir localisation GPS
locationManager =
(LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
// Géolocalisation par GPS
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
0, 0, locationListener);
Applications Java sous Android
IvMad, 2011-2014
Java Android : Géolocalisation (6)
// Géolocalisation par les cellules du réseau GSM, précision 500m
// locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
0, 0, locationListener);
}
public void onLocationChanged(Location loc) {
if (loc != null) {
Toast.makeText(getBaseContext(),
"Localisation actuelle Lat: " +
loc.getLatitude() + " Lng: " +
loc.getLongitude() + " Alt: " +
loc.getAltitude() + " Prec: " +
loc.getAccuracy(),
Toast.LENGTH_LONG).show();
}
}
public void onProviderDisabled(String provider) {
}
public void onProviderEnabled(String provider) { }
public void onStatusChanged(String provider, int status,Bundle extras) { }
}
}
24
Applications Java sous Android
IvMad, 2011-2014
25
Java Android : Géolocalisation (7)
Votre position en:
Latitude,
Longitude,
Altitude
Applications Java sous Android
IvMad, 2011-2014
26
Android : StrictMode
• Dans une application Android, on doit éviter d'effectuer des opérations
lentes sur le thread de l'interface utilisateur (GUI).
• Les opérations lecture et écriture de fichiers et l'accès au réseau sont considérées
comme lentes, car le temps d'aboutir est indéfini, voir imprévisible.
• StrictMode est configuré pour une sécurité accrue, c.à.d. pour éviter de
faire des choses incorrectes. L'exception NetworkOnMainThreadException
est provoqué si l'accès réseau est effectué de l'interface utilisateur (le
thread principal de l'application).
• A partir de l'Android 3.0 on peut désactiver cette option pour faire des
tests plus facilement sur l'accès réseau en plaçant dans la méthode
onCreate() le code:
StrictMode.ThreadPolicy policy = new StrictMode.
ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
Applications Java sous Android
IvMad, 2011-2014
27
Android : client-side TCP socket
package ivmad.TCP.Client;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import android.app.Activity;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout; import android.widget.TextView;
public class ClientTCPAndroidActivity extends Activity {
LinearLayout layout; EditText textOut; TextView textIn; Button buttonSend;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
textIn = new TextView(this);
textIn.setText("Message à soumettre");
textOut = new EditText(this);
buttonSend = new Button(this);
buttonSend.setText("Envoyer");
buttonSend.setOnClickListener(buttonSendOnClickListener);
layout.addView(textIn);
layout.addView(textOut);
layout.addView(buttonSend);
setContentView(layout);
}
Applications Java sous Android
IvMad, 2011-2014
Android : client-side TCP socket
Button.OnClickListener buttonSendOnClickListener = new Button.OnClickListener() {
public void onClick(View v) {
Socket socket = null;
DataOutputStream dataOutputStream = null;
DataInputStream dataInputStream = null;
InetAddress serverAddr;
String serverIpAddress = "192.168.0.141";
// Définir les droits d'accès au ressources réseaux
StrictMode.ThreadPolicy policy = new
StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
try {
serverAddr = InetAddress.getByName(serverIpAddress);
socket = new Socket(serverAddr, 1234);
dataOutputStream = new DataOutputStream(socket.getOutputStream());
dataInputStream = new DataInputStream(socket.getInputStream());
dataOutputStream.writeUTF(textOut.getText().toString());
textIn.setText(dataInputStream.readUTF());
} catch (UnknownHostException e) { e.printStackTrace();
} catch (IOException e) { e.printStackTrace(); }
finally {
if (socket != null && dataOutputStream != null && dataInputStream != null) {
try {
socket.close(); dataOutputStream.close(); dataInputStream.close();
} catch (IOException e) { e.printStackTrace(); } } } } }; }
28
Applications Java sous Android
IvMad, 2011-2014
29
Android : client-side TCP socket
• Le fichier AndroidManifest.xml contient la description des ressources et
les autorisations d'accès au réseau Internet
L'autorisation
d'accéder au réseau
et configurée dans le
Manifest de
l'application
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ivmad.TCP.Client"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk android:minSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
<activity
android:name=".ClientTCPAndroidActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Applications Java sous Android
IvMad, 2011-2014
30
Android : client-side TCP socket
Le serveur TCP reçoit le message
du client Android
Le client TCP basé Android envoie
un message au Serveur basé TCP
Applications Java sous Android
IvMad, 2011-2014
31
Android : client HTTP
• Avant de procéder à une connexion réseau, il faut s'assurer que cette
connexion est disponible. Un téléphone portable, un Smartphone ou
une tablette peut être hors réseau ou connexion Wifi désactivée.
• Cette disponibilité est testée avec les méthodes getActiveNetworkInfo() et
isConnected().
• La classe ConnectivityManager détecte les connexions Wifi, GPRS,
UMTS, etc.
public boolean isNetworkAvailable() {
ConnectivityManager cm = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = cm.getActiveNetworkInfo();
// Si le réseau est indisponible networkInfo = null et la
// méthode retourne false, sinon true.
if (networkInfo != null && networkInfo.isConnected()) {
return true;
}
return false;
}
Applications Java sous Android
IvMad, 2011-2014
32
Android : HTTP connection
• HttpURLConnection avec URL sont des classes disponibles depuis Java
2.0 standard.
• C'est un client léger d'usage général basé HTTP et approprié pour la
plupart des applications Android.
try {
URL url = new URL("http://ivmad.free.fr/ic4");
HttpURLConnection con = (HttpURLConnection) url.openConnection();
// méthode qui lit un contenu sur le Stream d'entrée
readStream(con.getInputStream());
} catch (Exception e) {
e.printStackTrace();
}
Applications Java sous Android
IvMad, 2011-2014
33
Android : HTTP connection
• Lecture du Stream d'entrée dont la connexion est effectuée par
HttpURLConnection et URL.
private void readStream(InputStream in) {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(in));
String line = "", str = "";
while ((line = reader.readLine()) != null) {
str += line;
}
Toast.makeText(getApplicationContext(),str,Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
reader.close();
}
}
}
Téléchargement