443 votes

Obtenir le nom de fichier et le chemin d'accès à partir de l'URI de mediastore

J'ai un onActivityResult renvoyant une sélection d'images de mediastore dont je peux obtenir une URI pour une image en utilisant ce qui suit :

Uri selectedImage = data.getData();

En convertissant cela en une chaîne de caractères, on obtient ceci :

content://media/external/images/media/47

Ou à un chemin donne :

/external/images/media/47

Cependant, je n'arrive pas à trouver un moyen de convertir ce chemin en un chemin absolu, car je veux charger l'image dans un bitmap sans avoir à la copier quelque part. Je sais que cela peut être fait en utilisant le résolveur d'URI et de contenu, mais cela semble se briser au redémarrage du téléphone. MediaStore ne garde pas la même numérotation entre les reboots.

1 votes

0 votes

API 19 et plus, la solution est ici, stackoverflow.com/a/51227392/9815519 . J'espère que cela pourra vous aider.

642voto

PercyPercy Points 2870

Inférieur à API 19 utiliser ce code pour obtenir le chemin du fichier à partir de l'URI :

public String getRealPathFromURI(Context context, Uri contentUri) {
  Cursor cursor = null;
  try { 
    String[] proj = { MediaStore.Images.Media.DATA };
    cursor = context.getContentResolver().query(contentUri,  proj, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);
  } finally {
    if (cursor != null) {
      cursor.close();
    }
  }
}

0 votes

AWESOME ! Cela fonctionne parfaitement, merci beaucoup, cela me posait problème depuis longtemps.

0 votes

+1 son fonctionnement. :) [lien] developer.Android.com/reference/Android/content/ Qu'en est-il de getDataString() ?

0 votes

+1 J'étais à la recherche de cette recherche et je l'ai trouvé et cela fonctionne très bien donc merci :)

133voto

dextor Points 1769

Juste une simple mise à jour de la première réponse : mActivity.managedQuery() est maintenant déprécié. J'ai mis à jour le code avec la nouvelle méthode.

private String getRealPathFromURI(Uri contentUri) {
    String[] proj = { MediaStore.Images.Media.DATA };
    CursorLoader loader = new CursorLoader(mContext, contentUri, proj, null, null, null);
    Cursor cursor = loader.loadInBackground();
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    String result = cursor.getString(column_index);
    cursor.close();
    return result;
}

Source de développement Android

4 votes

@dextor : Cela n'a pas fonctionné pour moi. Cela fonctionne lorsque je clique sur un fichier dans un navigateur de fichiers, mais lorsque je clique sur une pièce jointe à un courriel, j'obtiens toujours le message suivant content://... chose. J'ai essayé toutes les suggestions ici sans succès. Vous savez pourquoi ?

0 votes

@Luis moi aussi j'ai le même problème

1 votes

@dextor vous devez fermer le curseur.

112voto

mig Points 619

N'essayez pas de trouver une uri dans le système de fichiers, c'est lent pour aller chercher des choses dans la base de données.

Vous pouvez obtenir un bitmap à partir d'une uri en donnant un flux d'entrée à la fabrique comme vous donnez un fichier à la fabrique :

InputStream is = getContentResolver().openInputStream(uri);
Bitmap bitmap = BitmapFactory.decodeStream(is);
is.close();

5 votes

En fait, c'est la seule réponse correcte. Personne ne se soucie vraiment du nom du fichier. Ce dont nous avons besoin, c'est le contenu. Le fichier réel peut se trouver dans le dossier privé de l'application, dans internet, sqlite ou être purement virtuel et généré à la volée.

24 votes

La question spécifique posée concerne le nom du fichier et le chemin d'accès. Oui, le PO cherche à dériver un bitmap du fichier, mais ce n'est pas le cas de tous ceux qui cherchent le chemin. Parfois, nous avons besoin du contenu réel du fichier.

0 votes

getContentResolver() est une méthode de Context par stackoverflow.com/questions/3750903/ donc utiliser getActivity().getContentResolver() si vous essayez d'obtenir le contenu du fichier dans un Fragment ou un Fragment imbriqué.

43voto

Voici mon exemple de récupération du nom d'un fichier, à partir d'URI comme file://... et content://.... . Cela fonctionne pour moi non seulement avec Android MediaStore mais aussi avec une application tierce comme EzExplorer.

public static String getFileNameByUri(Context context, Uri uri)
{
    String fileName="unknown";//default fileName
    Uri filePathUri = uri;
    if (uri.getScheme().toString().compareTo("content")==0)
    {      
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        if (cursor.moveToFirst())
        {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);//Instead of "MediaStore.Images.Media.DATA" can be used "_data"
            filePathUri = Uri.parse(cursor.getString(column_index));
            fileName = filePathUri.getLastPathSegment().toString();
        }
    }
    else if (uri.getScheme().compareTo("file")==0)
    {
        fileName = filePathUri.getLastPathSegment().toString();
    }
    else
    {
        fileName = fileName+"_"+filePathUri.getLastPathSegment();
    }
    return fileName;
}

4 votes

Peut-il convertir les URI file:// et content:// et vice versa ? J'ai essayé d'inclure le code dans mon projet, mais il est indiqué que ApplicationObject ne peut être résolu.

5 votes

C'est un problème avec ApplicationObject, pouvez-vous me donner un code ?

0 votes

Oh, c'est bon, ne vous inquiétez pas, j'ai trouvé un autre exemple de code qui a fonctionné, merci.

18voto

Jon O Points 3545

De bonnes réponses existantes, dont certaines m'ont servi à élaborer les miennes :

Je dois obtenir le chemin d'accès à partir des URI et obtenir l'URI à partir des chemins d'accès, et Google a du mal à faire la différence. Ainsi, si quelqu'un rencontre le même problème (par exemple, pour obtenir la vignette à partir de l'adresse de l'URI), il peut le faire à partir de l'adresse de l'URI. MediaStore d'une vidéo dont vous avez déjà l'emplacement physique). Le premier :

/**
 * Gets the corresponding path to a file from the given content:// URI
 * @param selectedVideoUri The content:// URI to find the file path from
 * @param contentResolver The content resolver to use to perform the query.
 * @return the file path as a string
 */
private String getFilePathFromContentUri(Uri selectedVideoUri,
        ContentResolver contentResolver) {
    String filePath;
    String[] filePathColumn = {MediaColumns.DATA};

    Cursor cursor = contentResolver.query(selectedVideoUri, filePathColumn, null, null, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
    filePath = cursor.getString(columnIndex);
    cursor.close();
    return filePath;
}

Cette dernière (que je fais pour les vidéos, mais qui peut aussi être utilisée pour les fichiers audio ou les fichiers ou d'autres types de contenu stocké en substituant MediaStore.Audio (etc) à MediaStore.Video) :

/**
 * Gets the MediaStore video ID of a given file on external storage
 * @param filePath The path (on external storage) of the file to resolve the ID of
 * @param contentResolver The content resolver to use to perform the query.
 * @return the video ID as a long
 */
private long getVideoIdFromFilePath(String filePath,
        ContentResolver contentResolver) {

    long videoId;
    Log.d(TAG,"Loading file " + filePath);

            // This returns us content://media/external/videos/media (or something like that)
            // I pass in "external" because that's the MediaStore's name for the external
            // storage on my device (the other possibility is "internal")
    Uri videosUri = MediaStore.Video.Media.getContentUri("external");

    Log.d(TAG,"videosUri = " + videosUri.toString());

    String[] projection = {MediaStore.Video.VideoColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = contentResolver.query(videosUri, projection, MediaStore.Video.VideoColumns.DATA + " LIKE ?", new String[] { filePath }, null);
    cursor.moveToFirst();

    int columnIndex = cursor.getColumnIndex(projection[0]);
    videoId = cursor.getLong(columnIndex);

    Log.d(TAG,"Video ID is " + videoId);
    cursor.close();
    return videoId;
}

En gros, le DATA colonne de MediaStore (ou n'importe quelle sous-section de celui-ci que vous interrogez) stocke le chemin d'accès au fichier, donc vous pouvez soit utiliser ce que vous savez pour chercher ce fichier DATA ou utilisez le champ pour rechercher ce que vous voulez.

J'utilise ensuite le Scheme comme ci-dessus pour savoir quoi faire avec mes données :

 private boolean  getSelectedVideo(Intent imageReturnedIntent, boolean fromData) {

    Uri selectedVideoUri;

    //Selected image returned from another activity
            // A parameter I pass myself to know whether or not I'm being "shared via" or
            // whether I'm working internally to my app (fromData = working internally)
    if(fromData){
        selectedVideoUri = imageReturnedIntent.getData();
    } else {
        //Selected image returned from SEND intent 
                    // which I register to receive in my manifest
                    // (so people can "share via" my app)
        selectedVideoUri = (Uri)getIntent().getExtras().get(Intent.EXTRA_STREAM);
    }

    Log.d(TAG,"SelectedVideoUri = " + selectedVideoUri);

    String filePath;

    String scheme = selectedVideoUri.getScheme(); 
    ContentResolver contentResolver = getContentResolver();
    long videoId;

    // If we are sent file://something or content://org.openintents.filemanager/mimetype/something...
    if(scheme.equals("file") || (scheme.equals("content") && selectedVideoUri.getEncodedAuthority().equals("org.openintents.filemanager"))){

        // Get the path
        filePath = selectedVideoUri.getPath();

        // Trim the path if necessary
        // openintents filemanager returns content://org.openintents.filemanager/mimetype//mnt/sdcard/xxxx.mp4
        if(filePath.startsWith("/mimetype/")){
            String trimmedFilePath = filePath.substring("/mimetype/".length());
            filePath = trimmedFilePath.substring(trimmedFilePath.indexOf("/"));
        }

        // Get the video ID from the path
        videoId = getVideoIdFromFilePath(filePath, contentResolver);

    } else if(scheme.equals("content")){

        // If we are given another content:// URI, look it up in the media provider
        videoId = Long.valueOf(selectedVideoUri.getLastPathSegment());
        filePath = getFilePathFromContentUri(selectedVideoUri, contentResolver);

    } else {
        Log.d(TAG,"Failed to load URI " + selectedVideoUri.toString());
        return false;
    }

     return true;
 }

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