102 votes

Filtre d'intention Android: associer une application à une extension de fichier

J'ai un type de fichier personnalisé/extension que je veux associer mon application.

Autant que je sache, l'élément de données est faite pour cela, mais je ne peux pas le faire fonctionner. http://developer.android.com/guide/topics/manifest/data-element.html Selon les docs, et beaucoup de posts sur le forum, il devrait fonctionner comme ceci:

<intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:mimeType="application/pdf" />
</intent-filter>

Eh bien, il ne fonctionne pas. Qu'ai-je fait de mal? Je veux simplement déclarer mon propre type de fichier.

119voto

Phyrum Tea Points 1206

Vous avez besoin de plusieurs filtres d'intention pour traiter les différentes situations que vous souhaitez gérer.

Exemple 1, gérer les requêtes http sans types MIME:

   <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="http" />
    <data android:host="*" />
    <data android:pathPattern=".*\\.pdf" />
  </intent-filter>
 

Manipulez avec les types MIME où le suffixe est sans importance:

   <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.BROWSABLE" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="http" />
    <data android:host="*" />
    <data android:mimeType="application/pdf" />
  </intent-filter>
 

Gérer l'intention depuis une application de navigateur de fichiers:

   <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="file" />
    <data android:host="*" />
    <data android:pathPattern=".*\\.pdf" />
  </intent-filter>
 

53voto

Emmanuel Touzery Points 1677

Les autres solutions ne fonctionnaient pas de manière fiable pour moi jusqu'à ce que j'ajoute:

 android:mimeType="*/*" 
 

Avant cela, cela fonctionnait dans certaines applications, dans d'autres pas ...

solution complète pour moi:

 <intent-filter>
  <action android:name="android.intent.action.VIEW" />
  <category android:name="android.intent.category.DEFAULT" />
  <data android:scheme="file"  android:host="*" android:pathPattern=".*\\.EXT" android:mimeType="*/*"  />
</intent-filter>
 

22voto

LFOR Points 11

Mes conclusions:

Vous avez besoin de plusieurs filtres pour gérer les différentes façons de récupérer un fichier. c'est à dire, en pièces jointes gmail, par l'explorateur de fichiers, par HTTP, FTP... Ils envoient très différentes intentions.

Et vous avez besoin de filtrer l'intention de déclencher votre activité dans votre code d'activité.

Pour l'exemple ci-dessous, j'ai créé un faux fichier de type nouveau.mrz. Et j'ai récupéré à partir de pièces jointes gmail et l'explorateur de fichiers.

L'activité code ajouté dans le onCreate():

        Intent intent = getIntent();
        String action = intent.getAction();

        if (action.compareTo(Intent.ACTION_VIEW) == 0) {
            String scheme = intent.getScheme();
            ContentResolver resolver = getContentResolver();

            if (scheme.compareTo(ContentResolver.SCHEME_CONTENT) == 0) {
                Uri uri = intent.getData();
                String name = getContentName(resolver, uri);

                Log.v("tag" , "Content intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
                InputStream input = resolver.openInputStream(uri);
                String importfilepath = "/sdcard/My Documents/" + name; 
                InputStreamToFile(input, importfilepath);
            }
            else if (scheme.compareTo(ContentResolver.SCHEME_FILE) == 0) {
                Uri uri = intent.getData();
                String name = uri.getLastPathSegment();

                Log.v("tag" , "File intent detected: " + action + " : " + intent.getDataString() + " : " + intent.getType() + " : " + name);
                InputStream input = resolver.openInputStream(uri);
                String importfilepath = "/sdcard/My Documents/" + name; 
                InputStreamToFile(input, importfilepath);
            }
            else if (scheme.compareTo("http") == 0) {
                // TODO Import from HTTP!
            }
            else if (scheme.compareTo("ftp") == 0) {
                // TODO Import from FTP!
            }
        }

Gmail attachement filtre:

        <intent-filter android:label="@string/app_name">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="content" />
            <data android:mimeType="application/octet-stream" />
        </intent-filter>
  • JOURNAL: le Contenu de l'intention détecté: android.l'intention.d'action.VUE : content://gmail-ls/l.foul@gmail.com/messages/2950/attachments/0.1/BEST/false : application/octet-stream : nouveau.mrz

L'explorateur de fichiers de filtre:

        <intent-filter android:label="@string/app_name">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="file" />
            <data android:pathPattern=".*\\.mrz" />
        </intent-filter>
  • LOG: Fichier intention détecté: android.l'intention.d'action.VUE : file:///storage/sdcard0/Mes%20Documents/nouveau.zla : null : nouveau.mrz

Filtre HTTP:

        <intent-filter android:label="@string/rbook_viewer">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="http" />
            <data android:pathPattern=".*\\.mrz" />
        </intent-filter>

Privé des fonctions utilisées ci-dessus:

private String getContentName(ContentResolver resolver, Uri uri){
    Cursor cursor = resolver.query(uri, null, null, null, null);
    cursor.moveToFirst();
    int nameIndex = cursor.getColumnIndex(MediaStore.MediaColumns.DISPLAY_NAME);
    if (nameIndex >= 0) {
        return cursor.getString(nameIndex);
    } else {
        return null;
    }
}

private void InputStreamToFile(InputStream in, String file) {
    try {
        OutputStream out = new FileOutputStream(new File(file));

        int size = 0;
        byte[] buffer = new byte[1024];

        while ((size = in.read(buffer)) != -1) {
            out.write(buffer, 0, size);
        }

        out.close();
    }
    catch (Exception e) {
        Log.e("MainActivity", "InputStreamToFile exception: " + e.getMessage());
    }
}

18voto

yuku Points 15705

Le pathPattern

 <data android:pathPattern=".*\\.pdf" />
 

ne fonctionne pas si le chemin du fichier contient un ou plusieurs points avant ".pdf".

Cela fonctionnera:

 <data android:pathPattern=".*\\.pdf" />
<data android:pathPattern=".*\\..*\\.pdf" />
<data android:pathPattern=".*\\..*\\..*\\.pdf" />
<data android:pathPattern=".*\\..*\\..*\\..*\\.pdf" />
 

Ajoutez plus si vous voulez supporter plus de points.

2voto

magaio Points 599

Essayez d'ajouter

 <action android:name="android.intent.action.VIEW"/>
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X