86 votes

Plusieurs types MIME sur Android

Y a-t-il un moyen d'utiliser intent.setType() et de fournir plusieurs types larges (comme des images et des vidéos) ?

Je suis en train d'utiliser un ACTION_GET_CONTENT. Il semble fonctionner avec juste des types séparés par des virgules.

137voto

Fred Points 378

Dans Android 4.4, en utilisant le Cadre d'accès au stockage, vous pouvez utiliser le EXTRA_MIME_TYPES pour passer plusieurs types MIME.

Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String[] mimetypes = {"image/*", "video/*"};
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(intent, REQUEST_CODE_OPEN);

20voto

vchelbanster Points 420

En fait, plusieurs types de mime sont pris en charge. L'avez-vous même essayé ???

Par exemple : intent.setType("image/*,video/*") affichera des photos et des vidéos...

Pour moi, ça marche. Ça devrait fonctionner pour vous aussi...

[EDIT]: Cela fonctionne partiellement, car toutes les applications de galerie ne choisissent pas de mettre en œuvre le support pour plusieurs filtres de types de mime.

4voto

hackbod Points 55292

Désolé, cela n'est actuellement pas pris en charge. Vous avez deux options :

(1) Utilisez un type MIME de */* et acceptez qu'il puisse y avoir des choses que l'utilisateur peut choisir que vous ne pourrez pas gérer (et ayez un chemin de récupération décent pour cela); ou

(2) Implémentez votre propre sélecteur d'activité, en effectuant des appels directs sur le gestionnaire de packages pour obtenir les activités pouvant gérer les deux types MIME pour l'intention, fusionnez ces listes et affichez-les à l'utilisateur.

De plus, setType() ne fonctionne pas du tout avec des types séparés par des virgules. Il doit s'agir d'un seul et unique type MIME.

2voto

Raimundo Points 553

Pour moi, ce qui a le mieux fonctionné était :

intent.setType("*/*"); 
intent.addCategory(Intent.CATEGORY_OPENABLE); 

Vous pouvez ajouter plusieurs types MIME de cette manière

intent.setType("image/*|application/pdf|audio/*"); 

Mais le sélecteur d'intent ne affichera que les applications capables de gérer les images car c'est le premier dans la chaîne de types MIME.

Cependant, si vous avez un gestionnaire de fichiers installé (j'ai testé avec le gestionnaire de fichiers CyanogenMod), vous pouvez choisir un fichier qui est audio, pdf ou une image.

Si le type MIME audio est le premier, comme ceci :

intent.setType("audio/*|image/*|application/pdf");

Le sélecteur d'intent affichera uniquement les applications qui gèrent l'audio.
Encore une fois en utilisant le gestionnaire de fichiers, vous pouvez sélectionner une image, un pdf ou un audio.

0voto

Falchio Points 1

Avec le rappel registerForActivityResult() :

import androidx.activity.result.contract.ActivityResultContracts

class DocumentsFragment : Fragment() {

    companion object {

        // 1. Liste des types MIME
        /**@see Types MIME
         * @see IANA - Types MIME*/
        private val MIME_TYPES: Array = arrayOf(
            "image/*", "application/pdf", "application/msword",
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
            "application/vnd.oasis.opendocument.text", "text/plain", "text/markdown"
        )
    }

    //2. Enregistrer le callback pour le résultat de l'activité en tant que champ de classe
    private val getDocuments =
    registerForActivityResult(ActivityResultContracts.OpenMultipleDocuments()/*PAS OpenDocument*/) {
        Log.d("Ouvrir les documents", "uri entrante: taille = ${it.size}")
        add(it)
    }

    ...
    //3. Définir un écouteur onclick
    selectDocumentsButton.setOnClickListener { getDocuments.launch(MIME_TYPES) }
    ...

    //4. Gérer la liste d'URI entrante
    private fun add(list: List) {
        val setOfFiles = copyToAppDir(list)
        setOfFiles.forEach {
            //TODO: faire quelque chose            
        }
    }

    //5. Copier les fichiers dans le dossier de l'application pour un travail ultérieur
    private fun copyToAppDir(list: List): Set {
        val set = mutableSetOf()
        list.forEach { uri ->
            try {
                val file: File = copyUriContentToTempFile(uri)
                set.add(file)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
        return set
    }

    //6. Copier le contenu sélectionné par l'URI
    private fun copyUriContentToTempFile(uri: Uri): File {
        val inputStream = requireContext().contentResolver.openInputStream(uri)
        inputStream.use { input ->
            val tempFile: File = .. ; //TODO: créer le fichier
            tempFile.outputStream().use { output ->
                input?.copyTo(output)
            }
            return tempFile
        }
    }
}

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