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 ?

226voto

Stefan Haustein Points 4458

Developer.Android.com propose un exemple de code intéressant : https://developer.Android.com/guide/topics/providers/document-provider.html

Une version condensée permet d'extraire le nom du fichier (en supposant que "this" est une activité) :

public String getFileName(Uri uri) {
  String result = null;
  if (uri.getScheme().equals("content")) {
    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    try {
      if (cursor != null && cursor.moveToFirst()) {
        result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
      }
    } finally {
      cursor.close();
    }
  }
  if (result == null) {
    result = uri.getPath();
    int cut = result.lastIndexOf('/');
    if (cut != -1) {
      result = result.substring(cut + 1);
    }
  }
  return result;
}

56voto

Bhargav Points 11

Tiré de Récupération d'informations sur les fichiers | Développeurs Android

Récupération du nom d'un fichier.

private String queryName(ContentResolver resolver, Uri uri) {
    Cursor returnCursor =
            resolver.query(uri, null, null, null, null);
    assert returnCursor != null;
    int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
    returnCursor.moveToFirst();
    String name = returnCursor.getString(nameIndex);
    returnCursor.close();
    return name;
}

49voto

Ken Fehling Points 791

J'utilise quelque chose comme ceci :

String scheme = uri.getScheme();
if (scheme.equals("file")) {
    fileName = uri.getLastPathSegment();
}
else if (scheme.equals("content")) {
    String[] proj = { MediaStore.Images.Media.TITLE };
    Cursor cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
    if (cursor != null && cursor.getCount() != 0) {
        int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.TITLE);
        cursor.moveToFirst();
        fileName = cursor.getString(columnIndex);
    }
    if (cursor != null) {
        cursor.close();
    }
}

32voto

Metu Points 88

Les moyens les plus simples d'obtenir le nom d'un fichier :

val fileName = File(uri.path).name
// or
val fileName = uri.pathSegments.last()

S'ils ne vous donnent pas le nom que vous devriez utiliser :

fun Uri.getName(context: Context): String {
    val returnCursor = context.contentResolver.query(this, null, null, null, null)
    val nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
    returnCursor.moveToFirst()
    val fileName = returnCursor.getString(nameIndex)
    returnCursor.close()
    return fileName
}

30voto

Tamim Attafi Points 645

Pour Kotlin, vous pouvez utiliser quelque chose comme ceci :

fun Context.getFileName(uri: Uri): String? = when(uri.scheme) {
    ContentResolver.SCHEME_CONTENT -> getContentFileName(uri)
    else -> uri.path?.let(::File)?.name
}

private fun Context.getContentFileName(uri: Uri): String? = runCatching {
    contentResolver.query(uri, null, null, null, null)?.use { cursor ->
        cursor.moveToFirst()
        return@use cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME).let(cursor::getString)
    }
}.getOrNull()

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