Rechercher un fichier ou un dossier dans la carte SD.

Bonjour à tous,

Aujourd’hui je vais vous partager mon deuxième fichier « util« , qui me sert a récupérer certains fichier dans ma carte sd.

C’est d’une simplicité enfantine, on donne le nom d’un dossier, ou le nom d’un fichier en paramètre et il nous renvoie soit le fichier, soit null.

import java.io.File;
import java.io.IOException;
import android.os.Environment;

/**
 * Class utilitaire pour chercher un fichier avec son nom. Try catch si
 * nullpointer = pas trouve de fichier
 * 
 * @author Laurent
 * 
 */
public class FileSearch {

    /**
     * Methode qui va rechercher dans la sdcard le fichier avec le nom.
     * 
     * @param fileName le nom du fichier
     * @return le fichier en lui meme
     */
    public static File chercherFichier(String fileName) throws NullPointerException {
        File root = Environment.getExternalStorageDirectory();
        File out = null;
        out = chercherFichierRec(root, fileName);
        return out;
    }

    private static File chercherFichierRec(File dossier, String fileName) throws NullPointerException {
        File out = null;
        File[] contenuDossier;
        contenuDossier = dossier.listFiles();
        for (File f : contenuDossier) {
            if (f.isFile() && f.getName().equals(fileName))
                /** Log.d("fichier ? ", f.getPath()); */
                return f;
        }

        for (File f : contenuDossier) {
            if (f.isDirectory()) {
                out = chercherFichierRec(f, fileName);
                if (out != null) {
                    return out;
                }
            }
        }
        return out;
    }

    /***
     * cherche le dossier par le nom
     * 
     * @param fileName
     * @return
     */
    public static File chercherDossier(String fileName) throws NullPointerException {
        File root = Environment.getExternalStorageDirectory();
        File out = null;
        out = chercherDossierRec(root, fileName);
        return out;
    }

    private static File chercherDossierRec(File dossier, String fileName) throws NullPointerException {
        File out = null;
        File[] contenuDossier;
        contenuDossier = dossier.listFiles();
        for (File f : contenuDossier) {
            /** Log.d("dossier ? ", f.getPath()); */
            if (f.isDirectory() && f.getName().equals(fileName))
                return f;
        }

        for (File f : contenuDossier) {
            if (f.isDirectory()) {
                out = chercherDossierRec(f, fileName);
                if (out != null) {
                    return out;
                }
            }
        }
       return out;
   }

   /**
    * supprime tous les fichiers et dossier dans ce dossier.
    * supprime le dossier en tant que tel, si true.
    * @param root
    * @throws IOException 
    */
   public static void deleteAllFileFolder(File root, boolean delete) throws IOException {
      for (String path : root.list()) {
          File temp = new File(root.getPath() + File.separator + path);
          if (temp.isFile()) {
              temp.getCanonicalFile().delete();
          } else if (temp.isDirectory()) {
              if (temp.list().length == 0) {
                  temp.getCanonicalFile().delete();
              } else {
                  deleteAllFileFolder(temp, true);
                  temp.getCanonicalFile().delete();
              }
          }
      }
      if (delete) {
          root.getCanonicalFile().delete();
      }
   }
}

Et la dernière méthode supprime totalement un dossier avec ses dossiers enfants et fichiers enfants. (Cela m’aide pour mes tests quand j’ai la flemme de supprimer non-stop les fichiers que j’ai créé) Sur ce les amis, je vous souhaite une bonne semaine, à bientôt !

Demande d’activation GPS à l’utilisateur.

Demande d’activation GPS à l’utilisateur.

Bonjour à tous,

Certaines applications ont besoin de la localisation GPS pour pouvoir fonctionner, hors l’utilisateur ne l’a pas forcément activé, alors j’ai créé une simple classe, qui lui demande l’activation, avant de lancer mon activity « main » qui étends le LocationListener (qui gère donc la localisation).

Voici la classe en elle même:

/**
 * classe qui demande la permission au gps
 * 
 * @author l.hellofs
 * 
 */
public class PermissionGps extends Activity {
    private void createGpsDisabledAlert() {
        AlertDialog.Builder localBuilder = new AlertDialog.Builder(this);
        localBuilder
            .setMessage("Le GPS est inactif, voulez-vous l'activer ?")
            .setCancelable(false)
            .setPositiveButton("Activer GPS ",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                        PermissionGps.this.showGpsOptions();
                    }
                }
            );
        localBuilder.setNegativeButton("Ne pas l'activer ",
            new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface paramDialogInterface, int paramInt) {
                    paramDialogInterface.cancel();
                    PermissionGps.this.finish();
                }
            }
        );
        localBuilder.create().show();
    }

    private void showGpsOptions() {
        startActivity(new Intent("android.settings.LOCATION_SOURCE_SETTINGS"));
        finish();
    }

    protected void onCreate(Bundle paramBundle) {
        super.onCreate(paramBundle);
        createGpsDisabledAlert();
    }
}

Je la lance avec startActivity(), mais on pourrait faire une startActivityForResult() pour récupérer s’il a accepté ou non.

/** Récupère le locationManager qui gère la localisation */
LocationManager locManager;
locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
/** Test si le gps est activé ou non */
if (!locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    /** on lance notre activity (qui est une dialog) */
    Intent localIntent = new Intent(this, PermissionGps.class);
    localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    startActivity(localIntent);
}

/** Ensuite on demande a ecouter la localisation (dans la classe qui implémente le LocationListener*/
if (locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
    locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, this.minute, this.metre * 100, this);
} else {
    locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, this.minute, this.metre * 100, this);
}

Par la suite, je peux faire le test si le gps est activé ou non et écouté soit par le gps, soit par le network (wifi/3G).

Voilà, j’espère que cette petite astuce vous aidera. PS: n’oubliez pas de défnir la permission GPS et Wifi/Cell-ID pour gérer la localisation dans votre application (et l’activity PermissionGps)

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

Bonne journée !

Android Form Validator Preview
Les bulles sont disponibles en natif sur Android

Android Form Validator Preview

Voici une Library de ma composition servant à gérer, comme sous le Framework Zend PHP, la validation des formulaires. Les classes ont été calquées pour s’utiliser comme sous Zend et, de plus, elle permet facilement de créer de nouveaux validateurs.

La library est encore en phase de développement. Pour les impatients, vous la trouverez ici. Aucun JAR n’est disponible pour l’instant car j’utilise les fichiers ressource Android.

Utilisez donc mon projet comme un « Library Project » ou importez directement les sources dedans tant que vous indiquez la provenance. Dans les sources, vous trouverez une Activity d’exemple vous montrant comment vous servir des différents validateurs disponibles pour l’instant à savoir :

  • ConfirmValidator : Permet de vérifier si le champ de confirmation est valide (ex : confirmation mot de passe)
  • EmailValidator : Permet de vérifier si l’email saisit est valide.
  • NotEmptyValidator : Permet de savoir si un champ a bien été saisit
  • OrTwoFieldsEmptyValidator : Permet de vérifier si, entre deux champs, au moins l’un des deux a été saisit.
  • UrlValidator : Permet de savoir si un champ URL a été correctement saisit.

Chaque Validator est rattaché à un objet Validate propre. Ce champ validate permet de créer des chaines de validation en sachant que le premier Validator entré sera le premier testé.

EditText field1;

// Création du Validate pour notre champ1 :
Validate valField1 = new Validate(field1);

// Ajout de nos différents validateurs du premier à tester au dernier
valField1.addValidator(new EmailValidator(mContext));
valField1.addValidator(new NotEmptyValidator(mContext));

Certains Validators sont particuliers et s’utilisent sur deux champs en même temps (pour le ConfirmValidator et le OrTwoFieldsEmptyValidator).

EditText password;
EditText confirmPassword;

ConfirmValidator confirmFields = new ConfirmValidator(password, confirmPassword);

Tous les Objets Validates créés sont rajoutés à un Form. Et c’est ce Form qui permettra de vérifier si votre formulaire est valide.

Form form = new Form();
form.addValidates(valField1);
form.addValidates(confirmFields);

Pour vérifier si votre formulaire est valide. Il suffit juste de faire un if tout simple :

if(form.validate())
{
    // Traitement de votre formulaire
}

Et, en cas d’erreur, des bulles apparaissent sur les champs invalides comme ceci :

]1 Les bulles sont disponibles en natif sur Android

Comme vous le voyez, son utilisation reste très simple. Ensuite, sachez que vous pouvez créer facilement de nouveaux Validators pour vos formulaires. Pour ce faire, vous avez juste à créer une classe d’héritant de Validator :

/**
 * Classe servant à créer de nouveaux Validators
 * @author throrin19
 *
 */
public abstract class Validator {

    protected Context mContext;

    public Validator(Context c){
        mContext = c;
    }

    /**
     * Permet de vérifier si la valeur passée en paramètre est valide ou non.
     * @param value
     *         {@link Object} : la valeur à valider
     * @return
     *         boolean : true si valide, false sinon.
     */
    public abstract boolean isValid(Object value);

    /**
     * Permet de récupérer le message d'erreur correspondant au validateur.
     * @return
     *         String : le message d'erreur
     */
    public abstract String getMessage();
} 

Pour les intéressés par cette library, elle est déjà disponible sur mon Github en suivant ce lien.

Premier BeMyApp Belge !

Premier BeMyApp Belge !

Bonjour à tous !

Je vais vous raconter un peu mon aventure de ce weekend, je suis donc allez au BeMyApp Belge !

Qu’est ce que BeMyApp ?

C’est simple, plusieurs personnes présentent leurs idées/projets en une minute à tous les développeurs, graphistes, jury et nous votons pour notre préférence. Il y avait une petite trentaine de propositions, et seulement cinq ont été votées. (Par manque de développeurs).

Le choix.

J’ai donc choisi Firstsight.

 Le concept de firsight est très simple, on se promène dans la rue, on croise une belle demoiselle (ou un beau mec) mais on est trop timide pour l’aborder. Alors on sort notre smartphone, et on « flash » à l’endroit où nous sommes, on décrit notre « rencontre », comment était la personne que nous avons croisé, et nous uploadons sur le serveur de Firsight les données (géolocalisation, date, et donnée insérés.),  la personne qui nous a croisé, a fait pareil pour créer un « match ».

Si elle/il n’avait pas « flashé(e) », nous la/le reverrions plus… Mais elle/il l’a fait(e), les serveurs vont donc récupérer les informations uploadées par les deux personnes, et il va y avoir concordance dans la géolocalisation, l’heure et surtout les préférences pré-inscrite à l’inscription (quand vous lancez pour la première fois l’application). Et va notifié les deux personnes, et leurs dire qu’ils ont une concordance à l’endroit où ils ont flashé sur quelqu’un, et qu’il est possible de la retrouvé !

Ainsi, nous n’avons plus qu’a confirmer si c’est bien la personne que nous avons croiser, dans une liste et avec les informations (très réduite) de la personne. Si elle a accepté et vous aussi, vous pouvez alors chatter directement, tout en restant dans l’anonymat. Il reste plus qu’a lui proposer un rendez-vous, ou vous partagez vos informations personnels.

Comment ça c’est déroulé ?

L’idée est très simple, basique, mais puissante. 48h de code, 2développeurs iOS, 2développeurs Android (dont moi-même), un dev web et un graphiste étaient de la partie, sans oublier les deux fondateurs. Nous nous sommes tout de suite accordés, les modèles et les interfaces ont été très vite mise sur papier et nous avons pu commencer a développer réellement les applications (iphone/android) dès minuit ! Après une longue nuit d’interfaces sans repos et un petit déjeuner, il est midi, le temps d’un topo.

Bilan premier jour.

Vraiment simpliste non?

Ensuite, nous avons continuer dans une excellente ambiance, nous avons dû, le soir, dire où nous en étions, aux autres team et nous avons continué a coder pour nous avancer. Nous avons ajouté pas mal de fonctionnalités, comme la géolocalisation sur map, et surtout un chat en temps réel et fonctionnel.

Le tchat est multi plateforme

Les deux applications iphone/android, communiquaient déjà ensemble ! Nous avons vraiment bien avancer, on aurait voulu gérer l’inscription, mais seul les interfaces de iOS étaient dessinées, c’était la seule différence.

Bilan deuxième jour.

Voici quelques screen; 

 

Pour terminer

Nous avons dû faire une présentation de 10minutes, devant des jurys (liens et descriptions sur le blog du site) et après une bonne part de pizza, les jurys ont délibérés et nous avons gagné ! \o/ Il reste a gagner le vrai concours, l’international !!!

Et oui, la Belgique est en compétition avec 4 pays (USA, Tunisie, Maroc, Brésil) désormais, alors votez pour nous !!!

http://worldcup.bemyapp.com/

Quelques cadeaux comme des heures de consultances d’une boîte spécialisées dans le mobile, des smartphone et une chance de se qualifier à un concours très important à Londres, pour les fondateurs du projet, pour suivre une formation d’entre partenariat pendant 6 mois, tout frais payés.

Une grande aventure, super organisation, je vous invite fortement à allez voir sur le site encore une fois; BeMyApp

Une super expérience, un réseau d’amis qui se créé, des possibilités dans l’avenir peut-être et surtout un bon repos !

J’espère que ça vous aura plu, j’ai essayé d’allez à l’essentiel, sur le site, beaucoup d’infos et des vidéos sur youtube, si on cherche bien, y a même les lives des présentations. Bonne semaine à tous !

Preview Android Jelly Bean

Preview Android Jelly Bean

Bonsoir, c’est un peu à chaud que je vais aborder avec vous, rapidement, les principales nouveautés d’Android Jelly Bean (version 4 .1). Sachez quand même que je n’ai pas pu voir la keynote de ce soir donc j’ai regardé tout aussi rapidement les nouveautés via Twitter et via le SDK déjà disponible au téléchargement.

Je vais vous présenter d’abord les nouveautés pour l’utilisateur puis ensuite celles pour les développeurs. La plupart des images que vous verrez sont prises à partir de l’émulateur et vu qu’elle est encore au stade de beta, d’autres nouveautés ne sont pas encore connues.

Note aux développeurs :

Pour utiliser l’émulateur, lorsque vous arrivez sur le home et que vous avez un fond noir (100% des cas). Faites les étapes suivantes :

  • Ouvrez la barre de notification
  • Cliquez sur le bouton paramètres
  • Appuyez sur le bouton Home
  • Et voilà

Nouveautés d’Android 4.1 :

Dans les nouveautés, je vais vous parler très brièvement de la partie home car elle n’a pas réellement changée. La seule « grosse » nouveauté concerne les widgets. Quand vous voulez les placer et, si un raccourci de l’application gène, Android va le décaler sur le côté pour laisser la place au Widget. Très utile pour les placer plus rapidement et éviter le message « Oups, plus assez de place ».

Voici la nouvelle Home.. Euh en fait non

La barre de notification quant à elle est devenue très sobre. Finie la transparence pour voir derrière la home. Tout est noir. En tout cas, ça rend très bien avec les notifications.

Mais qui est cette Dianne?

On notera aussi une évolution du clavier qui n’est pas sans rappeler celui d’HTC à ses débuts sur Sence. ou celui fournit avec Android 2.3 Mais il a la particularité d’être enfin prédictif et ce très efficacement. Je pense que SwiftKey et autres claviers prédictifs n’ont qu’à bien se tenir d’ici là.

Rien à redire.

Maintenant nous arrivons sur Google Maps. Je n’ai pas pu tout voir car l’émulateur est assez capricieux. Sachez juste que sur la version installée, il est enfin possible de télécharger simplement une portion de la map pour avoir par exemple le GPS en offline. (Oui je sais, avant on pouvait le faire via le labs).

Mais trop bien!!!

On notera aussi la présence d’un nouvel Easter Egg pour Jelly Bean mais ça, je vous laisse le découvrir.

L’une des nouveautés qui fera plaisir aux utilisateurs avec un petit forfait data est que lors d’une mise à jour de l’application, ce n’est plus toute l’application mise à jour qui est téléchargée mais juste les fichiers impactés. Fini les 3Mo de téléchargement pour juste un petit Fix Bug.

Vous pouvez aussi dès maintenant, et ce pour toutes les versions d’Android, supprimer et mettre à jour, directement depuis le play Store Web, vos applications. 

Et si je mettais à jour chrome??

Dans les autres nouveautés que je n’ai pas pu tester on notera aussi :

  • Nouvelle version de Google+
  • Nouvelle version de Youtube
  • Meilleure fluidité globale du système
  • L’ajout d’une secrétaire : Google Now
  • Possibilité de coller plusieurs photos ensemble directement à partir de l’appareil Photo.
  • Et pleins d’autres que je n’ai pas encore vu.
 

Côté Développeurs

De ce côté-ci, il y en a à la pelle donc je vais juste indiquer les quelques-unes qui m’ont marquées :

Le service de push C2DM sort de la phase de Beta et devient GCM pour Google Cloud Message. Plus de formulaire à remplir mais  une clé API à générer pour chacune de vos applications et une library externe à rajouter à votre projet. De plus, Google annonce qu’il n’y aura plus de limite de taille (limitée à 200 caractères environs avant) ni de limite d’envoi de push. Ce n’est pas une bonne nouvelle ? Et cerise sur le gâteau, GCM est compatible Android 2.2+ (tout comme son aïeux C2DM). 

Maintenant, on peut passer simplement des options à nos activitées comme le fait de rajouter des animations pour le lancement et la fermeture.

On peut indiquer directement dans le Manifest l’Activity parente d’une autre activité pour un retour rapide grâce au bouton retour.

Les notifications ont deux tailles disponibles : BIG et NORMAL. De plus, on peut les mettre à jour facilement et en fonction du cas, rediriger sur le bon Intent. On peut aussi faire des notifications que image, que texte ou texte + image. Et pour finir les notifications en beauté. Si vous avez un appel ou un sms dans les notifications, vous pouvez répondre/rappeler directement si vous le souhaitez.

Inclusion  d’une nouvelle déclaration dans le Manifest pour les appareils qui sont dédiés à l’affichage de l’interface utilisateur sur un écran de télévision: FEATURE_TELEVISION.

On peut Maintenant rattacher un ClipDataObject (Copier/Coller) directement à un intent via la méthode setClipData().

Ajout de la méthode isActiveNetworkMetered() qui indique si oui ou non on a un réseau disponible et qui plus est fonctionnel.  

Et pleins d’autres nouveautés que je n’ai pas encore eu le temps de voir.

Conclusion

Bref, ce petit aperçu de Jelly Bean m’a vraiment mis l’eau à la bouche. L’api se complète enfin avec des méthodes simples qui évitent de faire une méthode bancale (test du réseau par exemple). De plus l’OS en lui-même se bonifie avec le temps en proposant toujours plus de fonctionnalités utiles et pratiques et qui permettent à l’utilisateur final de se simplifier la vie.

Google prouve qu’Android n’est plus réservé aux Geeks mais qu’il peut être utilisé par le grand public avec une grande facilité. Il l’avait déjà prouvé avec l’ancienne version mais avec la nouvelle, c’est encore mieux. Il ne reste plus qu’à prier pour que les constructeurs suivent le pas et ne fassent pas la même erreur que pour les anciennes versions non arrivées.