Tag Archives

3 Articles
Introduction aux Intents et récupération d’un fichier

Introduction aux Intents et récupération d’un fichier

Il se peut que vous ayez à implémenter une action redondante au système Android pour pouvoir réaliser une action. Afficher la galerie, lancer une vidéo, récupérer un fichier, … Autant de choses disponibles grâces à des applications systèmes et/ou tierces que vous aimeriez utiliser. C’est pourquoi, le système d’Intent existe. En fonction de l’action demandée, vous allez pouvoir réutiliser, en toute transparence, les fonctionnalités des autres applications au sein de la votre. Attention par contre, il se peut que l’action à appeler n’existe pas sur certains smartphones (un apperçu d’image sur certaines ROM constructeur).

Introduction

Il faut savoir que quand vous lancez une Activity ou un Service au sein de votre application, vous utilisez les Intents. En fonction de leur déclaration dans votre Manifest, vos Activities répondront à certaines actions d’intent demandées au sein de l’environnement Android. Pensez-y lors de votre développement. Mais, ne nous attardons pas trop, ici, nous allons voir comment appeler un Intent externe et non une Activity/Service interne. Sachez que les Intents (lors de l’appel d’action) sont composés de deux pièces principales :

  • l’action : l’action à appeler(ACTION_VIEW, ACTION_MAIN, …)
  • la data : un numéro de téléphone, un email, le chemin complet vers un fichier, … Lors de l’appel à une Activity ou un Service interne à votre application, ces deux éléments sont rarement nécessaires car vous savez quel Intent appeler. Les Intents ont aussi d’autres options qui sont, elles, optionnelles :
  • la catégorie : Donne des informations supplémentaires sur l’action à exécuter. Par exemple, CATEGORY_LAUNCHER signifie qu’il doit apparaître dans le Lanceur comme une application de haut niveau.
  • le type : Ici il s’agit du MIME-TYPE. Le plus souvent indiquée quaond on cherche par exemple un fichier d’un format spécial (ex : application/pdf)
  • le composant : Spécifie un nom explicite d’une classe de composants à utiliser pour l’intent.
  • les extras : Passés grâce à un Bundle, les extras sont des données qui transitent entre les intents (souvent utilisés pour passer des informations entre les activities d’une même application).

Je ne traiterai pas plus en détail la composition des intents. Google l’a très bien fait dans la documentation sur les intents. Mais je finirai quand meme par la liste des principales actions disponibles pour les Intents :

  • ACTION_VIEW : En fonction des informations passées dans les datas, ouvrira soit la galerie, la feuille d’un contact, …
  • ACTION_DIAL : Affichera le clavier téléphonique avec le numéro passé en data.
  • ACTION_EDIT : En fonction des données passées dans data, affichera le formulaire d’édition d’un évènement de l’agenda, d’un contact, …

Cas Pratique :

Récupération d’un fichier Maintenant que nous avons vu comment lancer un Intent pour effectuer une action redondante dans notre application, nous allons voir comment récupérer un fichier PDF au sein de notre téléphone. Sachez que pour réaliser ceci, nous allons utiliser l’action

ACTION_GET_CONTENT. Je pense que le nom est assez explicite pour tous. Dans le cas contraire, ça veut dire que nous cherchons les Intents pouvant nous permettre de récupérer du contenu. Voici le code nécessaire à l’utilisation d’un tel Intent :

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
startActivity(intent);

Bien évidemment, lancer l’intent avec un startActivity() lancera bien l’action désirée mais nous n’auront aucun retour. Pour pouvoir avoir un retour, nous devrons utiliser startActivityForResult() :

private static final int PICK_FILE_RESULT_CODE = 1;

//...

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
try {
    startActivityForResult(intent,PICK_FILE_RESULT_CODE);
} catch (Exception e) {
    e.printStackTrace();
}

L’utilisation du Try/Catch ici est nécessaire et prévient les erreurs si jamais aucun Intent pour l’action demandée n’existe. La variable PICK_FILE_RESULT_CODE va nous servire pour vérifier le retour de l’intent dans notre onActivityResult().

Bien entendu, vous pouvez utiliser un autre code retour. Ici il n’a que valeur d’exemple. Bien entendu, notre code est incomplet. Lancé tel quel, vous récupérerez du PDF comme du MP3 en passant par les images. Pour pouvoir récupérer uniquement du PDF, il faudra indiquer le mime-type dans la fonction setType(). De plus, même avec ceci, Android listera aussi les fichiers ne pouvant être ouvert.

Pour pouvoir les masquer, il faudra rajouter la catégorie CATEGORY_OPENABLE à notre Intent. Pour finir, avec le code actuel, Android ne vous permettra pas de choisir entre plusieurs Intent celui que vous préférez pour effectuer l’action. Pour pouvoir le faire, il faudra créer un nouvel Intent grâce au premier grâce à la méthode statique createChooser().

Le code final devrait donc ressembler à ceci :

private static final int PICK_FILE_RESULT_CODE = 1;

//...

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType("application/pdf");
intent.addCategory(Intent.CATEGORY_OPENABLE);
Intent i = Intent.createChooser(intent, "File");
try {
    startActivityForResult(i,PICK_FILE_RESULT_CODE);
} catch (Exception e) {
    e.printStackTrace();
}

Attention : Il n’est pas possible de sélectionner différents Mime-Type en même temps autrement qu’avec les opérateurs ‘*’ (ex : application/*). Si vous voulez certains types de fichier il faudra effectuer les tests dans le onActivityResult().

Pour pouvoir récupérer le résultat de l’Intent et, par la même occasion, votre fichier, il vous suffira d’implémenter la fonction onActivityResult() comme ceci :

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    switch (requestCode) {
         case PICK_FILE_RESULT_CODE: {
             if (resultCode == Activity.RESULT_OK && 
                 data!=null && data.getData()!=null) 
             {
                 String theFilePath = data.getData().getPath();
             }
             break;
          }
    }
} 

Attention : Si vous lancez l’Intent dans un Fragment avec getActivity().startActivityForResult(), il faudra implémenter onActivityResult() dans l’Activity du Fragment. Si vous lancez l’intent sans le getActivity(), vous devrez implémenter le onActivityResult() dans le Fragment.

Conclusion

Maintenant vous savez utiliser en partie les Intent pour effectuer des action déjà existantes au sein de l’écosystème Android. Sachez que vous pouvez changer facilement le type d’applications lazncées dans l’exemple juste en changeant le Mime-Type. Essayez de récupérer une image pour voir.

Bref, pour en revenir à une vrai conclusion, l’une des forces majeures d’Android reste son système d’Intent. Vous pouvez facilement récupérer des données systèmes et utiliser des applications tierces grâce àcette méthode et grâce aux droits associés. (Essayez de lancer un appel téléphonique sans l’autorisation nécessaire et c’est le drame). Toutefois, n’en abusez pas trop et, vérifiez avant leur utilisation si vous êtes certains que telle ou telle action est disponible sur tous les Devices.

Selon certaines ROM de constructeurs (oui, toi SAMSUNG, et toi Orange), certains Intent systèmes ont été tout bonnement et simplement supprimés et non remplacés.

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 !