155 votes

Comment extraire le nom du fichier de l'URI renvoyé par Intent.ACTION_GET_CONTENT ?

J'utilise un gestionnaire de fichiers tiers pour sélectionner un fichier (PDF dans mon cas) dans le système de fichiers.

C'est ainsi que je lance l'activité :

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.setType(getString(R.string.app_pdf_mime_type));
intent.addCategory(Intent.CATEGORY_OPENABLE);

String chooserName = getString(R.string.Browse);
Intent chooser = Intent.createChooser(intent, chooserName);

startActivityForResult(chooser, ActivityRequests.BROWSE);

Voici ce que j'ai en onActivityResult :

Uri uri = data.getData();
if (uri != null) {
    if (uri.toString().startsWith("file:")) {
        fileName = uri.getPath();
    } else { // uri.startsWith("content:")

        Cursor c = getContentResolver().query(uri, null, null, null, null);

        if (c != null && c.moveToFirst()) {

            int id = c.getColumnIndex(Images.Media.DATA);
            if (id != -1) {
                fileName = c.getString(id);
            }
        }
    }
}

L'extrait de code est emprunté à Ouvrir le gestionnaire de fichiers Intents sont disponibles ici :
http://www.openintents.org/en/node/829

L'objectif de la if-else est la compatibilité ascendante. Je me demande si c'est la meilleure façon d'obtenir le nom du fichier, car j'ai constaté que d'autres gestionnaires de fichiers renvoient toutes sortes de choses.

Par exemple, Documents ToGo renvoie quelque chose comme ce qui suit :

content://com.dataviz.dxtg.documentprovider/document/file%3A%2F%2F%2Fsdcard%2Fdropbox%2FTransfer%2Fconsent.pdf

sur lequel getContentResolver().query() retours null .

Pour rendre les choses plus intéressantes, le gestionnaire de fichiers sans nom (j'ai obtenu cet URI à partir du journal du client) a renvoyé quelque chose comme :

/./sdcard/downloads/.bin

Existe-t-il un moyen privilégié d'extraire le nom du fichier à partir de l'URI ou faut-il recourir à l'analyse des chaînes de caractères ?

1voto

pulp_fiction Points 10

Combinaison de toutes les réponses

Voici ce à quoi je suis arrivé après avoir lu toutes les réponses présentées ici ainsi que ce que certains Airgram ont fait dans leurs SDK - Un utilitaire que j'ai ouvert sur Github :

https://github.com/mankum93/UriUtilsAndroid/tree/master/app/src/main/java/com/androiduriutils

Utilisation

Il suffit d'appeler, UriUtils.getDisplayNameSize() . Il fournit à la fois le nom et la taille du contenu.

Nota: Ne fonctionne qu'avec un Uri content://

Voici un aperçu du code :

/**
 * References:
 * - https://www.programcreek.com/java-api-examples/?code=MLNO/airgram/airgram-master/TMessagesProj/src/main/java/ir/hamzad/telegram/MediaController.java
 * - https://stackoverflow.com/questions/5568874/how-to-extract-the-file-name-from-uri-returned-from-intent-action-get-content
 *
 * @author Manish@bit.ly/2HjxA0C
 * Created on: 03-07-2020
 */
public final class UriUtils {

    public static final int CONTENT_SIZE_INVALID = -1;

    /**
     * @param context context
     * @param contentUri content Uri, i.e, of the scheme <code>content://</code>
     * @return The Display name and size for content. In case of non-determination, display name
     * would be null and content size would be {@link #CONTENT_SIZE_INVALID}
     */
    @NonNull
    public static DisplayNameAndSize getDisplayNameSize(@NonNull Context context, @NonNull Uri contentUri){

        final String scheme = contentUri.getScheme();
        if(scheme == null || !scheme.equals(ContentResolver.SCHEME_CONTENT)){
            throw new RuntimeException("Only scheme content:// is accepted");
        }

        final DisplayNameAndSize displayNameAndSize = new DisplayNameAndSize();
        displayNameAndSize.size = CONTENT_SIZE_INVALID;

        String[] projection = new String[]{MediaStore.Images.Media.DATA, OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE};
        Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {

                // Try extracting content size

                int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);
                if (sizeIndex != -1) {
                    displayNameAndSize.size = cursor.getLong(sizeIndex);
                }

                // Try extracting display name
                String name = null;

                // Strategy: The column name is NOT guaranteed to be indexed by DISPLAY_NAME
                // so, we try two methods
                int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                if (nameIndex != -1) {
                    name = cursor.getString(nameIndex);
                }

                if (nameIndex == -1 || name == null) {
                    nameIndex = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
                    if (nameIndex != -1) {
                        name = cursor.getString(nameIndex);
                    }
                }
                displayNameAndSize.displayName = name;
            }
        }
        finally {
            if(cursor != null){
                cursor.close();
            }
        }

        // We tried querying the ContentResolver...didn't work out
        // Try extracting the last path segment
        if(displayNameAndSize.displayName == null){
            displayNameAndSize.displayName = contentUri.getLastPathSegment();
        }

        return displayNameAndSize;
    }
}

0voto

Cloud Points 1

J'ai trouvé quelques informations sur le site du développeur

J'ai obtenu quelques informations sur le site web du développeur

Obtenir le curseur

val cursor = context.contentResolver.query(fileUri, null, null, null, null)

Vous pouvez ensuite obtenir le nom et la taille du fichier

val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
val fileName = cursor.getString(nameIndex)
val size = cursor.getLong(sizeIndex)

N'oubliez pas de fermer la ressource

N'oubliez pas de fermer les ressources

Récupération d'informations sur les fichiers

0voto

kulikovman Points 113

Cela renverra le nom de fichier de l'Uri sans l'extension de fichier.

fun Uri.getFileName(): String? {
    return this.path?.let { path -> File(path).name }
}

Ici J'ai décrit un moyen d'obtenir le nom du fichier avec l'extension.

0voto

HAZEEM JOONUS Points 49

Essayez ceci,

Intent data = result.getData();
// check condition
if (data != null) {
    Uri sUri = data.getData();
    @SuppressLint("Recycle")
    Cursor returnCursor = getContentResolver().query(sUri, null, null, null, null);
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    returnCursor.moveToFirst();
    String file_name = returnCursor.getString(nameIndex);
}

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