Introduction
Cet article s’adresse aux développeurs cherchant intégrer un système cartographique dans leur application Java. Vous trouverez ci-bas les résultats de mes recherches effectués lors de mes charges de laboratoire du cours Analyse et Conception de Logiciel l’École de Technologie Supérieure (ÉTS).
Survol des possibilités étudiées
Voici un schéma qui résume les options possibles. La légende est la suivante : en vert les options faciles, en orange difficulté moyenne, en rouge non-recommandée, et en grisées les options non explorées lors de cette recherche.
Détails
Voici un tableaux résumant les entrées et sorties pour chacune des méthodes :
Méthode | Entrées | Sorties | Autres compétences requises |
---|---|---|---|
SWT | JavaScript ou URL | HTML | |
DJ NativeSwing | JavaScript ou URL | HTML | |
QT Jambi | JavaScript ou URL | HTML | QT |
Projet Web | JavaScript ou URL | HTML | HTML, CSS, Programmation serveur (PHP,JSP,etc.) |
Static Maps API + KML | KML | Image | |
Static Maps API + HTTP | String | Image | HTTP et (XML ou JSON) |
GWT | String | HTML | Google Web Toolkit (GWT) |
Flash | String | Flash | ActionScript (AS3) |
Navigateur web embarqué
Dans cette solution, il s’agit d’utiliser un des différents contrôles Web existants et d’incorporer carrément un navigateur web dans l’application. Par la suite il suffit d’utiliser JavaScript ou d’envoyer les bons paramètres dans l’URL pour afficher les directions.
Si j’avais construire une application de bureau professionnelle, je choisirait le Maps API for Flash (via Adobe Air) si possible car la librairie est très stable ou j’explorerais les possibilités avec le Google Maps for Mobile (recommandé par Sun) ou la NASA World Wind (demos)
QT Jambi
QT est une librairie graphique (GUI framework) c++, open source et multiplateforme (windows, mac, linux, mobile), développée par Nokia. QT Jambi est un “port” de la librairie QT pour Java. Pas besoin de QT pour utiliser QT Jambi, il suffit de télécharger les bindings pour votre système et le QT Eclipse Integration for Jambi (Java) Plugin. Notez que pour l’installation du plugin Eclipse sur Windows 64 bits, il faut télécharger les 2 fichiers mentionnés ci-haut en 32 bits.
Voir mon article précédent pour voir comment utiliser QT Jambi dans Eclipse
Sortie HTML
L’avantage d’avoir une sortie HTML est qu’il est possible de ré-utiliser les widgets du site de Google Maps. Par contre, l’intégration d’un navigateur embarqué dans les applications de bureau (ie: traditionnelle) frôle le bris de la license de Google. Toutefois, cela est parfaitement légal pour la création d’un site internet.
Maps Data API
J’ai perdu plusieurs heures infructueuses avec l’API officielle de Google (Maps Data API, maintenant désuète). Les exemples officiels requièrent l’installation d’un grand nombre de librairies mal documentées – laissez-moi savoir si vous y arrivez. J’ai alors cherché pour un autre exemple qui me semblait complet (dont j’ai perdu l’adresse), mais sa compilation provoquait une erreur de signature dans l’appel d’une des classes de l’API.
Point de départ pour la solution avec Microsoft
(source) : Microsoft has a collaboration with USGS at http://terraserver-usa.com/. There is a freely available web service with a WSDL. You can use common Java WSDL binding libraries like Axis or CXF to create java object to access the service.
Static Maps API + HTTP
Voici un extrait de code pour cette solution :
/**
* Copyright (c) 2010, Maxime Caumartin, David Martineau
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the names of the developpers nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package ca.etsmtl.log210.laboratoire1.GIS;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.LinkedHashMap;
import utilities.json.JSONArray;
import utilities.json.JSONException;
import utilities.json.JSONObject;
import utilities.json.JSONTokener;
import utilities.polylineEncoder.PolylineEncoder;
import utilities.polylineEncoder.Track;
import utilities.polylineEncoder.Trackpoint;
import ca.etsmtl.log210.laboratoire1.modele.GestionnaireGIS;
public class GoogleMapProvider implements GestionnaireGIS {
private HashMap<String, String> chose = new LinkedHashMap<String, String>();
private HashMap<String, String> autreChose = new HashMap<String, String>();
private Dimension dimmensionCarte;
private URL polyencodedMap;
// [...]
@Override
public Image getImage() throws IOException, InvalidLocalisationException {
StringBuffer b = new StringBuffer(50);
Image img;
for (String s : chose.keySet())
b.append(s).append('\n');
if ((img = cache.get(b.toString())) == null)
{
JSONTokener token = null;
URL u;
URLConnection c;
try
{
Track t = new Track();
for(int i = 0; i < getLieux().length-1; i++){
u = new URL("http://maps.google.com/maps/nav?q=from:"+URLEncoder.encode(getLieux()[i], "UTF-8")+"%20to:"+URLEncoder.encode(getLieux()[i+1], "UTF-8"));
c = u.openConnection();
// Je suis un navigateur web et mon nom est Firefox 3.6
c.setRequestProperty("User-Agent", "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100122 Fedora/3.6.1-1.fc13 Firefox/3.6");
c.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
c.setRequestProperty("Accept-Language", "fr-ca,en;q=0.5");
InputStreamReader ob = new InputStreamReader (c.getInputStream());
token = new JSONTokener(ob);
JSONObject o = new JSONObject(token);
// Dans le protocole HTTP, 200 signifie que notre requete a ete executee avec succes
if (o.getJSONObject("Status").getInt("code") != 200)
throw new InvalidLocalisationException();
JSONArray arrDep = o.getJSONArray("Placemark");
JSONObject o1 = (JSONObject) arrDep.get(0);
t.addTrackpoint(getTractPointFromJSON(o1));
JSONArray dir = o.getJSONObject("Directions").getJSONArray("Routes")
.getJSONObject(0).getJSONArray("Steps");
for (int j = 0 ; j < dir.length(); j++)
t.addTrackpoint(getTractPointFromJSON((JSONObject)dir.get(j)));
t.addTrackpoint(getTractPointFromJSON((JSONObject)arrDep.get(1)));
}
HashMap<?, ?> hm = PolylineEncoder.createEncodings(t, 10, 1);
polyencodedMap = new URL(generatePolyencodedMapURL(hm));
}
catch (JSONException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
img = Toolkit.getDefaultToolkit().createImage(polyencodedMap);
cache.put(b.toString(), img);
}
return img;
}
public String generatePolyencodedMapURL(HashMap<?, ?> hm) throws UnsupportedEncodingException{
String polyEncURL;
//"http://maps.google.com/maps/api/staticmap?sensor=false&size=800x800&markers=color:blue |label:D|H3C+1K3 &markers=color:blue |label:F|<Destination!> &maptype=roadmap&format=png32&path=weight:5 |color:blue |enc"+hm.keySet().iterator().next().toString()
polyEncURL = "http://maps.google.com/maps/api/staticmap?sensor=false&size=1280x1024&"+generatePolylineMarkers()+"maptype=roadmap&format=png32&path=weight:"+getLargeurChemin()+"|color:"+getCouleurChemin()+"|enc:" + hm.values().iterator().next().toString();
return polyEncURL;
}
public String generatePolylineMarkers() throws UnsupportedEncodingException{
String polyMarkers = "";
for(int i = 0; i < getLieux().length; i++){
polyMarkers = polyMarkers + "markers=color:"+getCouleurMarqueur()+"|label:"+this.chose.get(getLieux()[i])+"|"+URLEncoder.encode(getLieux()[i], "UTF-8")+"&";
}
return polyMarkers;
}
private static Trackpoint getTractPointFromJSON(JSONObject o1) throws JSONException
{
JSONObject o2 = o1.getJSONObject("Point");
JSONArray coor1 = o2.getJSONArray("coordinates");
return new Trackpoint(coor1.getDouble(1), coor1.getDouble(0), coor1.getDouble(2));
}
@Override
public String[] getLieux() {
int i = 0;
String [] tmpStringArray = new String[chose.keySet().size()];
for (String s : chose.keySet())
tmpStringArray[i++] = s;
return tmpStringArray;
}
// [...]
}
Références
- Google Maps Parameters (quoi passer dans l’URL)
- Google Maps JavaScript API v3
- Google Directions API
- Google Static Maps API V2
- Google Maps API Web Services
- Service de conversion d’une adresse en KML
- SWT Code Snippets
- QT Jambi 4.5.2 Reference Documentation
- QT Jambi 4.5.2 API
- QT 4.7.1 Reference Documentation
- QT 4.7.1 API
- Tutorial: Google Maps with Java, GWT and Eclipse
- DJ NativeSwing
- Google Maps API for Flash
- Google Maps for Mobile
- NASA World Wind
- MapQuest Developer Network
- Microsoft Bing Maps Developer Resources
Crédits
Merci à Maxime de Caumartin pour la contribution de son code Java pour le GoogleMapProvider, et aux autres étudiants pour leurs contributions.