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 ?

16voto

Samuel Points 4472

Si vous voulez qu'il soit court, cela devrait fonctionner.

Uri uri= data.getData();
File file= new File(uri.getPath());
file.getName();

14voto

artdeell Points 101

La version la plus condensée :

public String getNameFromURI(Uri uri) {
    Cursor c = getContentResolver().query(uri, null, null, null, null);
    c.moveToFirst();
    return c.getString(c.getColumnIndex(OpenableColumns.DISPLAY_NAME));
}

11voto

Vasanth Points 4071

J'utilise le code ci-dessous pour obtenir le nom et la taille du fichier à partir de l'Uri dans mon projet.

/**
 * Used to get file detail from uri.
 * <p>
 * 1. Used to get file detail (name & size) from uri.
 * 2. Getting file details from uri is different for different uri scheme,
 * 2.a. For "File Uri Scheme" - We will get file from uri & then get its details.
 * 2.b. For "Content Uri Scheme" - We will get the file details by querying content resolver.
 *
 * @param uri Uri.
 * @return file detail.
 */
public static FileDetail getFileDetailFromUri(final Context context, final Uri uri) {
    FileDetail fileDetail = null;
    if (uri != null) {
        fileDetail = new FileDetail();
        // File Scheme.
        if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
            File file = new File(uri.getPath());
            fileDetail.fileName = file.getName();
            fileDetail.fileSize = file.length();
        }
        // Content Scheme.
        else if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) {
            Cursor returnCursor =
                    context.getContentResolver().query(uri, null, null, null, null);
            if (returnCursor != null && returnCursor.moveToFirst()) {
                int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
                fileDetail.fileName = returnCursor.getString(nameIndex);
                fileDetail.fileSize = returnCursor.getLong(sizeIndex);
                returnCursor.close();
            }
        }
    }
    return fileDetail;
}

/**
 * File Detail.
 * <p>
 * 1. Model used to hold file details.
 */
public static class FileDetail {

    // fileSize.
    public String fileName;

    // fileSize in bytes.
    public long fileSize;

    /**
     * Constructor.
     */
    public FileDetail() {

    }
}

7voto

save_jeff Points 169

Si vous souhaitez obtenir le nom du fichier avec son extension, j'utilise cette fonction pour l'obtenir. Cette fonction fonctionne également avec les fichiers de google drive.

public static String getFileName(Uri uri) {
    String result;

    //if uri is content
    if (uri.getScheme() != null && uri.getScheme().equals("content")) {
        Cursor cursor = global.getInstance().context.getContentResolver().query(uri, null, null, null, null);
        try {
            if (cursor != null && cursor.moveToFirst()) {
                //local filesystem
                int index = cursor.getColumnIndex("_data");
                if(index == -1)
                    //google drive
                    index = cursor.getColumnIndex("_display_name");
                result = cursor.getString(index);
                if(result != null)
                    uri = Uri.parse(result);
                else
                    return null;
            }
        } finally {
            cursor.close();
        }
    }

    result = uri.getPath();

    //get filename + ext of path
    int cut = result.lastIndexOf('/');
    if (cut != -1)
        result = result.substring(cut + 1);
    return result;
}

6voto

UdaraWanasinghe Points 945

Ma réponse serait excessive, mais voici comment vous pouvez obtenir un nom de fichier à partir de 4 types d'uri différents dans Android.

  1. Uri du fournisseur de contenu [content://com.example.app/sample.png]
  2. Fichier uri [file://data/user/0/com.example.app/cache/sample.png]
  3. Ressource uri [android.resource://com.example.app/1234567890] o [android.resource://com.example.app/raw/sample]
  4. Http uri [https://example.com/sample.png]

    fun Uri.name(context: Context): String { when (scheme) { ContentResolver.SCHEME_FILE -> { return toFile().nameWithoutExtension } ContentResolver.SCHEME_CONTENT -> { val cursor = context.contentResolver.query( this, arrayOf(OpenableColumns.DISPLAY_NAME), null, null, null ) ?: throw Exception("Failed to obtain cursor from the content resolver") cursor.moveToFirst() if (cursor.count == 0) { throw Exception("The given Uri doesn't represent any file") } val displayNameColumnIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME) val displayName = cursor.getString(displayNameColumnIndex) cursor.close() return displayName.substringBeforeLast(".") } ContentResolver.SCHEME_ANDROID_RESOURCE -> { // for uris like [android.resource://com.example.app/1234567890] var resourceId = lastPathSegment?.toIntOrNull() if (resourceId != null) { return context.resources.getResourceName(resourceId) } // for uris like [android.resource://com.example.app/raw/sample] val packageName = authority val resourceType = if (pathSegments.size >= 1) { pathSegments[0] } else { throw Exception("Resource type could not be found") } val resourceEntryName = if (pathSegments.size >= 2) { pathSegments[1] } else { throw Exception("Resource entry name could not be found") } resourceId = context.resources.getIdentifier( resourceEntryName, resourceType, packageName ) return context.resources.getResourceName(resourceId) } else -> { // probably a http uri return toString().substringBeforeLast(".").substringAfterLast("/") } } }

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