Open data, les calendriers

android

Dans cet article nous verrons comment récupérer les données d’un google agenda afin de le rendre exploitable par une application android ou java. Je l’utilise moi même pour le système d’intelligence artificiel qui contrôle ma maison. Je peux ainsi prévoir mes prochains rendez vous et connaitre mes rendez vous de la journée lorsque je me lève. Afin de réaliser le parsing des données, j’utilise la librairie iCal4j qui est assez bien documenté et pour lequel le net regorge d’exemple.

Le format iCalendar

Le format est iCal est un format qui permet de représenter les agendas. Il s’agit d’un format normalisé. La page Wikipedia à ce sujet est assez bien réalisée et je vous laisse le soin de la visualiser.

Google propose d’exporter vos agendas dans ce format. Vous ne devriez pas rencontrez de difficulté si vous suivez les instructions des services de google à cette adresse. Attention à bien lire jusqu’au bout et à partager votre agenda (le rendre public) pour pouvoir accèder aux données.

Vous devez maintenant avoir un lien iCal qui ressemble à celui ci : « https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics »

Quelques exemples

Si vous avez pris le temps de lire la page Wikipedia, vous connaissez maintenant les différents composants que l’ont peux récupérer. Si vous ne l’avez pas encore fait je vous invite à le faire, c’est très rapide et ceci vous permettra de comprendre comment fonctionne le standard.

J’aimerai récupérer mon prochain rendez vous afin de l’afficher par exemple. Si celui ci a lieu dans plus de 7 jours, alors je n’en prends pas compte et indique à l’utilisateur qu’il n’a pas de rendez vous prévu dans les 7 prochains jours.

Pour cela il est nécessaire de :

  1. Récupérer un flux vers l’url de mon google agenda au format iCal
  2. Parser ce flux de données
  3. Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
  4. Afficher le premier VEVENT ou bien un message si il n’y a pas de rendez vous dans les 7 prochains jours

ce qui donne le code correspondant :

//1 Récupérer le flux de icalendar à partir de mon google agenda
URL googleCalendar = new URL("https://www.google.com/calendar/ical/mon.compte%40gmail.com/public/basic.ics");
BufferedReader in = new BufferedReader(new InputStreamReader(googleCalendar.openStream()));
 
//2 Parser le flux de données
CalendarBuilder builder = new CalendarBuilder();
Calendar calendar = builder.build(in);
 
//3 Filtrer les données pour récupérer les VEVENTs qui ont lieu dans les 7 prochains jours
Period period = new Period(new DateTime(today.getTime()), new Dur(7, 0, 0, 0));
Filter filter = new Filter(new PeriodRule(period));
Collection<?> eventsToday = filter.filter(calendar.getComponents(Component.VEVENT));
 
//4 Afficher le premier VEVENT ou bien un message si il n'y a pas de rendez vous dans les 7 prochains jours
Iterator<?> i = eventsToday.iterator();
if (!i.hasNext()) {
   System.out.println("Pas de rendez vous dans les 7 prochains jours");
} else {
   Component component = (Component) i.next();
 
   DateTime dateStart = new DateTime(component.getProperty("DTSTART").getValue());
   //DateTime dateEnd = new DateTime(component.getProperty("DTEND").getValue());
   String description = component.getProperty("DESCRIPTION").getValue();
   String location = component.getProperty("LOCATION").getValue();
   String name = component.getProperty("SUMMARY").getValue();
DateFormat formater = new SimpleDateFormat("dd MMMM yyyy 'à' hh 'heure et' mm 'minutes'",new Locale("FR", "fr"));
 
sentence = "Vous avez rendez-vous " + name + " le " + formater.format(dateStart) + ".";
if(null != location && !location.isEmpty()) {
   sentence = sentence + " Il se tiendra à " + location + ".";
}
 
if(null != description && !description.isEmpty()) {
   sentence = sentence + " La description asocié est " + description + ".";
}
 
System.out.println(sentence);

Afin d’obtenir d’avantage d’exemples, je vous invite à parcourir la page du wiki de iCal4j : http://wiki.modularity.net.au/ical4j/index.php?title=Examples
Vous y trouverez des exemples pour ajouter / récupérer des VEVENT, VCARD, générer un iCal etc…

Open data, parsing XML

android

On entend beaucoup parler de l’open data. Ce concept qui veut ouvrir les données afin que tout le monde puisse les réutiliser est en théorie une grande idée qui permet au plus créatif de réaliser l’application de leur rêve.

On voit fleurir un peu partout des hackathons qui proposent d’utiliser ces données et lorsqu’il s’agit de s’en servir, les développeurs déchantent assez rapidement. Le principe de l’open data consiste bien souvent à balancer les données dans un format difficile à utiliser.

Pour cet article, nous allons réaliser un convertisseur de devises à l’aide de données accessibles publiquement. Vous pouvez trouver le convertisseur sur le playstore à cette adresse
Vous pouvez aussi accèder directement aux sources sur github

Trouver les données

Sur internet les sites qui proposent les taux de change en temps réels sont assez nombreux. Il s’agit même d’un véritable business utilisé par les traders. Pour notre convertisseur, nous souhaitons avoir une source fiable et gratuite. Le format est aussi asez important, il faut si possible utiliser un format courant comme le XML ou le json. Afin de s’assurer de la fiabilité des données, il n’y a je pense qu’une seule chose à faire, avoir une source de confiance. Afin de trouver des données publiques, je commence toujours par lister l’ensemble des organismes publiques qui me viennent à l’idée et qui pourraient mettre cette donnée en ligne.

Dans notre cas nous cherchons les taux de change, j’ai donc choisi d’orienter mes recherches vers :

  • Les banques centrales
  • Les banques d’état
  • Tout les services de l’état qui pourraient avoir à faire de prés ou de loin à de la monnaie (ministère des affaires étrangères, etc)

A cette liste, je conseille d’ajouter systèmatiquement les organismes de normalisation tel que l’ISO ou l’ANSI. Ces organismes regorgent de données publiques qui sont dans des formats très faciles à gérer (xml ou csv).

Utiliser la donnée

Après ces recherches je suis rapidement tombé sur le site de la banque centrale européenne qui offre un accès en XML aux taux de changede la journée.

La source est fiable et offre en plus de cela des exemples pour les développeurs en php. Je souhaite réaliser une application android, mais les exemples sont souvent un gage de qualité (ou laisse penser que les données on au moins étaient testé).

Voici le fichier XML proposé :

<gesmes:Envelope>
<gesmes:subject>Reference rates</gesmes:subject>
<gesmes:Sender><gesmes:name>European Central Bank</gesmes:name></gesmes:Sender>
<Cube>
<Cube time="2014-08-07">
<Cube currency="USD" rate="1.3368"/>
<Cube currency="JPY" rate="136.76"/>
<Cube currency="BGN" rate="1.9558"/>
<Cube currency="CZK" rate="27.853"/>
...
</Cube>
</Cube>
</gesmes:Envelope>

La banque centrale européenne propose les taux de change par rapport à l’Euro. Afin d’obtenir les autres taux de change, nous réalisons une simple règle de trois.

Pour parser le xml, j’utilise la librairie jdom. Le code proposé sur le github est assez parlant, si vous rencontrez des problèmes n’hésitez pas à poster un commentaire. Le problème suivant est que nous souhaiterions avoir le nom de la monnaie plutôt que le symbole. Pour cela nous retournons à l’étape précèdente et récupérons une autre source.

La source proviens de l’iso (http://www.currency-iso.org/dam/downloads/table_a1.xml), de cette manière je récupére les données suivantes :

<ISO_4217 Pblshd="2014-03-28">
<CcyTbl>
<CcyNtry>
<CtryNm>AFGHANISTAN</CtryNm>
<CcyNm>Afghani</CcyNm>
<Ccy>AFN</Ccy>
<CcyNbr>971</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>ÅLAND ISLANDS</CtryNm>
<CcyNm>Euro</CcyNm>
<Ccy>EUR</Ccy>
<CcyNbr>978</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
<CcyNtry>
<CtryNm>ALBANIA</CtryNm>
<CcyNm>Lek</CcyNm>
<Ccy>ALL</Ccy>
<CcyNbr>008</CcyNbr>
<CcyMnrUnts>2</CcyMnrUnts>
</CcyNtry>
...

Afin de réaliser l’application j’aurai souhaité avoir un fichier xml comme celui ci :

<?xml version="1.0" encoding="UTF-8"?>
<CurrenciesCode>
...
  <Currency code="CNY">Yuan Renminbi</Currency>
  <Currency code="JPY">Yen</Currency>
  <Currency code="XBD">Bond Markets Unit European Unit of Account 17 (E.U.A.-17)</Currency>
  <Currency code="UGX">Uganda Shilling</Currency>
  <Currency code="RON">New Romanian Leu</Currency>
  <Currency code="UYI">Uruguay Peso en Unidades Indexadas (URUIURUI)</Currency>
  <Currency code="TTD">Trinidad and Tobago Dollar</Currency>
  <Currency code="SHP">Saint Helena Pound</Currency>
  <Currency code="MOP">Pataca</Currency>
...

Pour ce faire, j’ai donc choisi de réaliser une conversion des données et d’inclure directement le fichier dans mon projet android. Je ne pense pas que les devises changent en permanence de nom et dans le cas de l’apparition d’une nouvelle devise, il suffira de mettre à jour l’application avec un fichier mis à jour. Si vous souhaitez récupérer ce fichier, il est présent dans les sources github dans le fichier assets.

Conclusion

Cet article reprend les grand principes pour travailler avec des données publiques. La méthodologie est celle que j’utilise, le choix des données est très important, je vous recommande de toujours choisir des grands organismes qui souhaitent garder à jour les données (et qui on un interêt à le faire).
N’hésitez pas lorsque cela est nécessaire à retraiter la donnée. Ce traitement permet d’alléger votre application mais ne peut se faire que sur les données statiques.

It’s oversimple isn’t it?

Le stockage des mots de passes

android

Il y a quelques jours, je regardai le projet lancé par hackaday de faire un password keeper qui soit offline : Mooltipass

Je me suis dis que c’était quand même bien pratique et que j’en aurai bien besoin sur mon téléphone mobile. Comme ça faisait pas mal de temps que je n’avais pas développé sur Android, c’était l’occasion de réfléchir au plus gros problème que l’on retrouve sur les mobiles, ils ne disposent pas d’un espace sécurisé.

Vous pouvez récupérer l’application sur google play directement à cette adresse : Téléchargement

Le mécanisme de protection

Afin de réaliser ce projet, j’ai supposé que le mobile n’était pas vérolé à priori et qu’aucun touchlogger n’était présent sur celui ci.

En plus de cela, j’ai supposé que l’utilisateur été suffisamment doué pour choisir un mot de passe solide dont on peut sauvegarder le hash sans qu’il soit casser rapidement.

L’idée est donc de chiffrer l’ensemble des mots de passe de l’utilisateur en utilisant un secret que seul l’utilisateur connait.

Pour cela nous allons utiliser les API java cryptographiques et utiliser l’algorithme AES.

Afin de générer le secret pré partagé, nous allons utiliser une phrase secrete. Ce secret consiste en une phrase que seul l’utilisateur connait. Nous utiliserons alors une fonction de hashage pour générer la clé de chiffrement à partir de la phrase secrète de l’utilisateur. A cela nous ajoutons un salt, ceci permet de diversifier le secret pré partagé en fonction de son usage.

La fonction de diversification a été codé comme suis :

private byte[] diversify(String password, String salt) {
	password = password + salt;
	byte[] key = new byte[16];
	MessageDigest sha1 = null;
	try {
		sha1 = MessageDigest.getInstance("SHA");
	} catch (NoSuchAlgorithmException e) {
		e.printStackTrace();
	}
	sha1.update(password.getBytes());
	byte[] hash = sha1.digest();
	System.arraycopy(hash, 0, key, 0, 16);
	return key;
}

Le stockage des données

Afin de stocker les données, nous allons transporter la clé dérivée pour la session courante et utiliser une base de données Android pour stocker les mots de passe. L’ensemble du contenu de la base de données est bien entendu chiffré avant insertion.

Chaque entrée est identifiée par les champs suivants :

public class PasswordReference {
 
	private int id;
	private String description;
	private String login;
	private String password;

L’id est stocké en clair, pour les autres champs, nous utilisons un salt différents pour chacun.

Attaques possibles

La première attaque possible est de regarder par dessus l’épaule. Ainsi l’utilisateur récupère le secret pré partagé.
Une seconde attaque serait d’utiliser un key logguer. Afin de palier à ce genre d’attaque, il faudrait ajouter un deuxième paramètre dans la génération du secret pré partagé. Ce deuxième paramètre serait un code pin avec clavier dynamique. Ainsi un touchlogger deviendrait inefficace pour récupérer le code pin.

Cependant cette technique n’empêcherait pas de bruteforcer les solutions restantes et avec un code pin à 4 chiffres, ça ne fait que 10 000 essais.
L’attaque par bruteforce reste la dernière possible et celle ci peut être évitée à condition de choisir un mot de passe sure et de le changer régulièrement.

Sources

L’ensemble des sources de ce petit programme peut être télécharger sur github à l’adresse suivante : https://github.com/julien14/secretKeeper
Bien sur le programme est libre et sous licence GPL. Enjoy !

La réalité augmentée c’est facile avec Android

android

La réalité augmentée c’est à la mode et ça parait super compliqué. Dans les faits, réaliser une librairie de réalité augmentée, c’est placé correctement des points sur une image en fonction de la position de l’utilisateur. La dite image est retranscrite à partir du capteur CCD du téléphone mobile (comprenais la caméra quoi).

Nous n’allons pas réaliser la librairie mais plutôt réutiliser l’excellent travail de aka pishman3579. Vous pouvez trouver son projet sur gihub ici.

Réaliser la librairie

Avant de commencer, nous allons utiliser son application afin de générer une librairie android. Pour cela commencer par cloner le dépôt github.

git clone https://github.com/phishman3579/android-augment-reality-framework.git

Ensuite dans les propriétés Android, coché isLibrary :

isLibrary

Enfin, vous allez devoir supprimer le fichier Demo.java qui apparaît maintenant avec des erreurs. Ceci est normal, nous le réimplémenterons dans votre application.

Voilà, vous venez maintenant de créer votre librairie de réalité augmentée.

Utiliser la librairie

Commencer par créer un nouveau projet Android et par linker la librairie de réalité augmentée à ce projet :

addLib

Une fois que ceci est fait, ajouter les permissions suivantes à votre manifest :

    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <uses-permission android:name="android.permission.WAKE_LOCK"/>

Créer maintenant un activitée en réutilisant le fichier Demo.java que vous avez supprimé. Vous pouvez le copier coller ici.

Modifier votre fichier manifest.xml afin de préciser que cette activity se lance sans tilte bar et en mode landscape:

<activity android:name=".activity.MainActivity"
    android:label="@string/app_name"
    android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
    android:screenOrientation="landscape">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>            
</activity>

Conclusion

Si vous compilez vous pouvez observer autour de vous les données récupérées depuis wikipédia. Il est très facile de modifier ce fichier afin d’y ajouter votre propre set d’event récupéré depuis un serveur web ou bien localement. Je vous laisse regarder les fichiers ainsi que le fichier de démo qui est assez explicite. Quoi qu’il en soit si vous avez des questions n’hésitez pas à nous laisser un petit commentaire, nous nous ferons un plaisir de vous répondre.

Google MAP avec un fragment dynamique

android
Pour avoir Google Map dans son application, 4 étapes sont nécessaires :

  • Obtenir une clé pour utiliser l’API
  • Récupérer le Google Map service
  • Ajouter les informations nécessaires dans Google MAP
  • Implémenter le fragment dans l’application

Obtenir une clé pour utiliser l’API

Tout d’abord, il faut se connecter sur le site de Google API Console . Puis dans le menu gauche, il faut cliquer sur API Access et cliquer sur « Create New Android Key… ».

Nous avons besoin de récupérer l’empreinte de notre clé grâce au SHA1, pour cela il faut se placer dans le répertoire cd ~/.android/. C’est ici que se trouve votre clé debug.keystore.

keytool -list -v -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android

Grâce a cette commande, on peut récupérer une empreinte du certificat. En l’occurrence, la ligne qui nous intéresse est celle avec clé SHA1.

Copier cette ligne sur le site de google API et ajouter à la fin un ; + le nom du package.

Cela va générer une API clé qu’il faudra utiliser dans votre manifest.

Note: : Pour définir le nom du package, il faut regarder dans votre manifest le package définit. En ce qui me concerne, j’ai choisi : fr.oversimple.applicationdemo

Récupérer le Google Map service

Afin d’utiliser Google Map, il faut télécharger la librairie : Google Play services via le Android SDK Manager
Google Play Services

Une fois le téléchargement effectué il faut l’ajouter comme librairie dans l’environnement de développement. Le répertoire se trouve dans extra/google/google_play_services . Pour Eclipse, il faut le déclarer comme une librairie (Clic droit sur le projet -> Properties -> Android -> Is Library) Puis pour le projet, au lieu de le déclarer comme librairie, il faut l’ajouter comme librairie.

En ce qui concerne Android studio (ou Intellij), il faut l’importer comme module.

Ajouter les informations nécessaires dans Google MAP

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="fr.oversimple.applicationdemo"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="19" />
 
    <permission
            android:name="fr.oversimple.applicationdemo.permission.MAPS_RECEIVE"
            android:protectionLevel="signature" />
 
    <uses-feature
            android:glEsVersion="0x00020000"
            android:required="true"/>
 
    <!-- Google map -->
    <uses-permission android:name="fr.oversimple.applicationdemo.permission.MAPS_RECEIVE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
    <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" />
 
 
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/Theme.OrangeNoActionBar" >
        <activity android:name=".activities.MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 
        <!-- https://code.google.com/apis/console/ -->
        <meta-data
                android:name="com.google.android.gms.version"
                android:value="@integer/google_play_services_version" />
        <meta-data
                android:name="com.google.android.maps.v2.API_KEY"
                android:value="Votre API KEY" />
    </application>
 
</manifest>

Implémenter le fragment dans l’application

Le XML correspondant map_main_activity.xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    <com.google.android.gms.maps.MapView
            android:id="@+id/mapView"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"/>
</RelativeLayout>

Le code correspondant pour la map :

public class MapsFragment extends Fragment {
 
    private MapView map;
 
    public MapsFragment() {
    }
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
 
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.map_main_activity, container, false);
 
        if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(getActivity().getApplicationContext()) == ConnectionResult.SUCCESS) {
 
            //Initialze mapview
            MapsInitializer.initialize(getActivity());
 
            map = (MapView) view.findViewById(R.id.mapView);
            map.onCreate(savedInstanceState);
 
            GoogleMap gMap = map.getMap();
            gMap.addMarker(new MarkerOptions().title("title").snippet("description").position(new LatLng(49.5594950, -1.8414880))).showInfoWindow();
 
        } else {
            Toast.makeText(getActivity(), "Please install google play services", Toast.LENGTH_LONG).show();
        }
        return view;
    }
 
    @Override
    public void onResume() {
        super.onResume();
        map.onResume();
    }
 
    @Override
    public void onPause() {
        super.onPause();
        map.onPause();
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
        map.onDestroy();
    }
 
    @Override
    public void onLowMemory() {
        super.onLowMemory();
        map.onLowMemory();
    }
}

Pour appeler le fragment, l’id content frame correspond à mon cœur d’application. En l’occurrence, je l’ai utilisé avec le navigation drawer d’Android afin d’avoir un menu sur la gauche.

mapFragment = new MapsFragment();
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, mapFragment).commit();

Ce fragment de Google Map peut être remplacé facilement par un autre fragment.

It’s oversimple, isn’t it?

Un peu de Volley sous Android!

android
Pour ceux qui ne connaisse pas Volley, c’est LE Framekwork de communication réseau.

Pour commencer, voici une trés bonne vidéo de présentation réalisée par Ficus Kirkpatrick .

L’article ci-dessous permet de faire une introduction à l’utilisation Volley.

Si vous n’avez pas regardé la vidéo, vous allez me dire, il existe déjà plusieurs framework réseau sous Android, pourquoi utiliser un autre framework?

A ma connaissance, il existe 2 possibilités de framework sous Android, afin de faire du HTTP. Le premier est Apache HTTP Client, c’est celui-ci que j’utilisais avant de découvrir Volley. Mais comme vous le savez sans doute, Apache HTTP Client possède des bugs et celui-ci n’est pas forcement maintenu par l’équipe Android.
La seconde API est HttpURLConnection que je n’ai jamais utilisé mais celle-ci possède des bugs.

Pour chacun de ces 2 frameworks, il faut rédefinir des Thread afin de ne pas rester dans le main thread. Cela impliquait l’utilisation des Asynctask.

Volley permet de s’abstenir de toute cette couche. C’est facile, puissant et rapide! De plus, celui-ci possède un cache mémoire ou disque.

C’est bien beau, mais comment ça fonctionne?

Son fonctionnement est aussi simple, il possède une queue que l’on doit initialiser UNE fois  (cette initialisation est assez coûteuse en performance). Ensuite, on ajoute dans cette queue les REQUETES que l’on doit effectuer. Le reste est géré par Volley.

Et comment on l’utilise?

Tout d’abord, il faut penser à mettre le user permission Internet dans le manifest d’Android :

<uses-permission android:name="android.permission.INTERNET" />

Puis, il faut récupérer le JAR ou le projet:

git clone https://android.googlesource.com/platform/frameworks/volley
cd volley
android list targets #Choisir l'ID pour la compilitation du JAR
android update project -p . --target ID_DE_TARGETS
ant jar

Une fois le JAR généré, il faut le placer dans le répertoire libs de votre projet. (Penser à l’ajouter au classpath en faisant clic droit add as library)

pour la création de la QUEUE,  je considère que l’on en a besoin partout dans notre Application donc on l’initialise qu’une fois. Cette initialisation est faite dans le contexte de l’application (extends Application) :

public class IntroApplication extends Application {
    private RequestQueue volleyRequestQueue;
 
    @Override
    public void onCreate() {
        super.onCreate();
        volleyRequestQueue = Volley.newRequestQueue(this);
        volleyRequestQueue.start();
    }
 
    @Override
    public void onTerminate() {
        volleyRequestQueue.stop();
        super.onTerminate();
    }
 
    public RequestQueue getVolleyRequestQueue() {
        return volleyRequestQueue;
    }
}

Vu que l’on extends Application, il faut penser à l’ajouter dans le manifest dans l’ application android:name= ».IntroApplication ».

Une fois cette initialisation faite, c’est bon, on peut travailler avec Volley. Il existe plusieurs type de Request dans Volley, String, JSONObject, JSONArray etc… (on peut bien sûr extends Request)

Un exemple avec String:

        StringRequest stringRequest = new StringRequest("url",new Response.Listener<String>() {
            @Override
            public void onResponse(String s) {
                Log.d("MainActivity","On doit traiter ici la reponse : " + s);
            }
        },new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                Log.d("MainActivity","On doit gérer ici l'erreur");
            }
        });

En ce qui concerne les deux listener(la réponse et l’erreur), il faut implémenter les interfaces : Response.Listener et Response.ErrorListener.
Une fois que notre stringRequest est géré, il faut l’ajouter dans la Queue.

IntroApplication introApplication = (IntroApplication) getApplication();
mVolleyRequestQueue = introApplication.getVolleyRequestQueue();
mVolleyRequestQueue.add(stringRequest);

Cette exemple est valable pour String mais il fonctionne tout aussi bien avec les JsonObjectRequest, JsonArrayRequest. Il faut aussi remplacer les types des listener par JSONObject ou bien JSONArray.

En ce qui concerne les images au lieu d’utiliser les ImageView, nous allons utiliser les Images pour Volley, c’est à dire NetworkImageView (com.android.volley.toolbox.NetworkImageView). Cette modification doit être effectuée au niveau du XML et ainsi au niveau des CAST pour utiliser un objet de type NetworkImageView au lieu d’un ImageView.
Il faut également ajouter dans le contexte de l’application, le chargement des images.
mVolleyImageLoader = new ImageLoader(mVolleyRequestQueue, new BitmapLruCache());
Avant le start de volley request start de préférence.

Le XML:

    <com.android.volley.toolbox.NetworkImageView
            android:id="@+id/monImage"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:src="@drawable/ic_launcher"/>

BitmapLruCache :

public class BitmapLruCache extends LruCache&lt;String, Bitmap&gt; implements ImageLoader.ImageCache {
 
    /**
     * @param maxSize for caches that do not override {@link #sizeOf}, this is
     *                the maximum number of entries in the cache. For all other caches,
     *                this is the maximum sum of the sizes of the entries in this cache.
     */
    public BitmapLruCache(int maxSize) {
        super(maxSize);
    }
 
    public BitmapLruCache() {
        this(getDefaultLruCacheSize());
    }
 
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;
        return cacheSize;
    }
 
    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }
 
    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }
 
    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

Un exemple d’utilisation, super simple:

NetworkImageView networkImageView = (NetworkImageView) findViewById(R.id.monImage);
networkImageView.setImageUrl("lienDeLimage",mVolleyImageLoader);

Et si on désire passer des paramètres? Sans problème, il faut juste extends Request et redéfinir la méthode getParams (Hasmap de String/String).
Un exemple est présent dans l’archive ci-jointe : JSONParams

HashMap<String,String> map = new HashMap<String,String>();
map.put("UnParametre","laValeurDuParametre");
JSONParams jsonParams = new JSONParams("url",map,this,this);
mVolleyRequestQueue.add(jsonParams);

Et si on souhaite annuler une requête dans la QUEUE?
Super simple, il faut sur chaque Request mettre un setTag afin de pouvoir les identifier. Une fois identifiée, il faudra juste annuler celle que l’on désire:
Par exemple, si je reprends l’exemple de stringRequest avant de l’ajouter dans la queue, j’effectue un setTag

stringRequest.setTag("identifiantDeMaStringRequest");
mVolleyRequestQueue.add(stringRequest);
mVolleyRequestQueue.cancelAll("identifiantDeMaStringRequest");

Vous pouvez télécharger l’archive ici.

It’s Oversimple, isn’t it?

Attaque sur carte sans contact

Un petit retour sur le workshop de la Nuit du Hack.

La démonstration principale de ce workshop était une attaque sur les cartes sans contact. Celles-ci proposent de payer en sans contact à une distance d’une dizaine de centimètre du lecteur. Ce paiement ne nécessite pas de saisir son code PIN. Il est cependant limité à des transactions d’un montant maximal de 20€ et à 4 transactions consécutives. Après il faut passer en mode contact pour réaliser une transaction.

Description de l’attaque

L’idée est de réaliser un proxy permettant de faire une transaction à distance.

explain

Le téléphone est un téléphone NFC qui permet de réaliser des transactions en sans contact. Celui-ci est relié par un réseau, par exemple un réseau internet, à un lecteur de carte sans contact. Ce lecteur dans le schéma est représenté à droite à coté du personnage en costume. Il est relié à un ordinateur afin de pouvoir être accessible depuis un réseau.

Nous aurions aussi pu utiliser un autre téléphone NFC à la place du couple PC – lecteur sans contact. Cependant je n’avais à ma disposition qu’un seul téléphone NFC.

L’attaque consiste à réaliser un proxy passif afin de réaliser un paiement à l’aide d’une carte qui ne se trouve pas à proximité du lecteur. Puisque la technologie est sans contact, cela peut être réalisé à l’insu de la cible.

Réalisation

Afin de réaliser cette attaque, un téléphone Nexus S a été utilisé. Ce téléphone possède une puce NFC et permet l’installation de l’application simply tap avec une cyanogen mod 9.1. Cette application permet d’avoir accès à l’antenne NFC du téléphone depuis une application android. Le but premier est de réaliser des services de paiement en cloud.

Dans notre cas, au lieu d’interroger un cloud, nous interrogeons un lecteur distant afin de dialoguer directement avec une carte sans contact.

Démonstration :


Attaque par proxy par oversimple

Comment s’en protéger

Pour s’en protéger, c’est assez simple il suffit de mettre sa carte dans un étui en fer. Il existe des portes feuilles blindés qui font très bien l’affaire.

Bibliographie

SimplyTapp NFC Payment System Debuts with CyanogenMod 9.1
emulating pki smart card with cm9.1
NFC Proxy