Obtenir le nom de fichier et le chemin depuis l'URI de mediastore


390

J'ai un onActivityResultretour d'une sélection d'image de médiastore que je peux obtenir un URI pour une image en utilisant ce qui suit:

Uri selectedImage = data.getData();

La conversion de ceci en chaîne donne 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 cela 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 l'URI et le résolveur de contenu, mais cela semble rompre au redémarrage du téléphone, je suppose MediaStoreque sa numérotation ne reste pas la même entre les redémarrages.



L'API 19 et au-dessus de la solution est ici, stackoverflow.com/a/51227392/9815519 . J'espère que cela peut vous aider.
Hasib Akter

Réponses:


609

Ci-dessous, l'API 19 utilise ce code pour obtenir le chemin de 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();
    }
  }
}

65
Au lieu de managedQuery (.........) (obsolète), vous pouvez utiliser getContentResolver (). Query (.....) avec les mêmes paramètres. Beau travail
Pablo Johnson

44
Dans la dernière version d'Android (KitKat), cela donne une erreur: le chemin String est nul.
Christopher Masser

17
comme le souligne Christopher - cela n'est pas pris en charge dans la version 4.4+ Voir cette question pour plus d'informations: stackoverflow.com/questions/20067508/…
ılǝ

13
Ne marche pas. le curseur est nul. Et je ne suis pas sur Android 4.4+, je suis sur 4.1.2.
matteo

11
Testé sur 5 appareils. Donne null sur tous sauf pour Android 4.1.2. Sur tous les androïdes plus récents retourne null.
Tina

127

Juste une simple mise à jour sur la première réponse: mActivity.managedQuery()est désormais obsolète. 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


3
@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 e-mail, je reçois toujours la content://...chose. J'ai essayé toutes les suggestions ici sans chance. Une idée pourquoi?
Luis A. Florit

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

1
@dextor vous devez fermer le curseur.
etherton

Pouvez-vous aider dans ce domaine: stackoverflow.com/questions/27103529/…
Chlebta

@dextor J'ai essayé cette solution qui n'a pas fonctionné, probablement quelque chose a changé entre-temps. La solution de Paul Burke à partir de cette question stackoverflow.com/questions/20067508/… a cependant fonctionné.
AndyZ

111

Pour Oreo

Uri uri = data.getData(); 
File file = new File(uri.getPath());//create path from uri
final String[] split = file.getPath().split(":");//split the path.
filePath = split[1];//assign it to a string(your choice).

Pour toutes les versions ci-dessous Oreo, j'ai fait cette méthode qui obtient un vrai chemin depuis uri

 @SuppressLint("NewApi")
    public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
        String selection = null;
        String[] selectionArgs = null;
        // Uri is different in versions after KITKAT (Android 4.4), we need to
        if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            } else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                uri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            } else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("image".equals(type)) {
                    uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                selection = "_id=?";
                selectionArgs = new String[]{
                        split[1]
                };
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


          if (isGooglePhotosUri(uri)) {
              return uri.getLastPathSegment();
           }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

  public static boolean isGooglePhotosUri(Uri uri) {
    return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}

7
c'est la seule version fonctionnant de manière transparente sur chaque type d'Uri - devrait être la meilleure réponse ..
Matthew Fisher

6
Ce code fonctionne si l'utilisateur n'a pas sélectionné de fichier sur la carte SD. Si l'utilisateur a sélectionné un fichier sur la carte SD, le chemin renvoyé est par exemple / storage / emulated / 0 / filePath même si le fichier se trouve sur / storage / sdCard / filePath
adi9090

existe-t-il une solution pour résoudre ce problème @ adi9090. je suis coincé sur ce problème depuis près de 2 jours :(
Ali Nawaz

2
Eh bien, vous pouvez essayer une bibliothèque comme sélecteur de matériaux pour l'url Android: github.com/nbsp-team/MaterialFilePicker cela peut vous rapprocher de la solution, je suis toujours là-dessus si vous obtenez une solution, veuillez l'afficher ci-dessous ..
Ali Nawaz

4
Ne fonctionne pas non plus: java.lang.UnsupportedOperationException: contenu Uri non pris en charge: //com.android.externalstorage.documents/tree/primary%3ADCIM%2FCamera...pourquoi l'équipe Android a rendu la vie si difficile
Leon

97

N'essayez pas de trouver un uri dans le système de fichiers, il est lent d'aller chercher dans la base de données.

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

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

5
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 du contenu. Le fichier réel peut être dans le dossier privé de l'application, sur Internet, sqlite ou être purement virtuel et généré à la volée.
durilka

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

3
@durilka, un exemple: si le fichier est une vidéo et que vous voulez une vignette, la fonction "ThumbnailUtils.createVideoThumbnail" peut simplement être appelée avec un chemin de type String, n'accepte aucun morceau de inputStreams.
ElYeante

1
Je voudrais d'abord vérifier si le fournisseur de contenu pour les vidéos fournit des miniatures avec des métadonnées. Android consiste à "ne pas l'implémenter vous-même si quelqu'un l'a déjà fait". Cela me fait vraiment peur de voir comment chaque application ambitieuse essaie de créer sa propre capture de photos.
durilka

4
Vous venez d'introduire un chemin qui mène au bug
OutOfMemory

39

Voici mon exemple pour obtenir le nom de 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
Cela peut-il convertir entre les URI file: // et content: // et vice versa? J'ai essayé d'inclure le code dans mon projet, mais il indique que ApplicationObject ne peut pas être résolu.
user280109

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

oh, c'est ok, ne vous inquiétez pas, j'ai trouvé un autre exemple de code qui a fonctionné, cheers.
user280109

2
Cela mérite d'être la meilleure réponse, elle est plus complète et résout un problème que j'avais.
Andreas Rudolph

Pourquoi appelez-vous getLastPathSegment (). ToString () alors que getLastPathSegment () renvoie déjà une chaîne?
droid8421

15

Bonnes réponses existantes, dont j'ai l'habitude de trouver les miennes:

Je dois obtenir le chemin à partir des URI et obtenir l'URI à partir des chemins, et Google a du mal à faire la différence, donc pour quiconque a le même problème (par exemple, pour obtenir la vignette à partir MediaStored'une vidéo dont vous avez déjà l'emplacement physique) ). L'ancien:

/**
 * 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;
}

Ce dernier (ce que je fais pour les vidéos, mais peut également être utilisé pour l'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;
}

Fondamentalement, la DATAcolonne MediaStore(ou la sous-section de celle-ci que vous interrogez) stocke le chemin du fichier, vous utilisez donc ce que vous savez pour rechercher ce DATAchamp, ou utilisez le champ pour rechercher ce que vous voulez d'autre.

J'utilise ensuite le Schemecomme ci-dessus pour comprendre 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;
 }

11

Aucune de ces réponses n'a fonctionné pour moi dans tous les cas. J'ai dû aller directement à la documentation de Google https://developer.android.com/guide/topics/providers/document-provider.html sur ce sujet et j'ai trouvé cette méthode utile:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
    ParcelFileDescriptor parcelFileDescriptor =
    getContentResolver().openFileDescriptor(uri, "r");
    FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
    Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
    parcelFileDescriptor.close();
    return image;
}

Vous pouvez utiliser ce bitmap pour l'afficher dans une vue d'image.


7

API 19 et au-dessus , Image File Path d'Uri fonctionne parfaitement. Je vérifie également cette dernière API PIE 28 .

public String getImageFilePath(Uri uri) {
    String path = null, image_id = null;

    Cursor cursor = getContentResolver().query(uri, null, null, null, null);
    if (cursor != null) {
        cursor.moveToFirst();
        image_id = cursor.getString(0);
        image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
        cursor.close();
    }

    Cursor cursor = getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    if (cursor!=null) {
        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
        cursor.close();
    }
    return path;
}

3
Tout d'abord, vous avez initialisé deux fois le curseur! Deuxièmement, ce code jette CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0sur cette ligne:path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
Harshil Pansare

J'utilise Android stock Oreo et cela ne fonctionne pas pour une raison quelconque
Harshil Pansare

comment obtenir le fichier PDF Chemin de fichier à partir de l'URI pouvez-vous m'aider

@HarshilPansare, comment l'avez-vous fait fonctionner pour Android Oreo? Je suis coincé pendant 2 jours.
Kashish Malhotra

Cela ne fonctionne pas si l'élément sélectionné n'est pas une image
Mustansir

5

essayez ce chemin d'accès au fichier image à partir d'Uri

public void getImageFilePath(Context context, Uri uri) {

    Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
    cursor.moveToFirst();
    String image_id = cursor.getString(0);
    image_id = image_id.substring(image_id.lastIndexOf(":") + 1);
    cursor.close();
    cursor = context.getContentResolver().query(android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Images.Media._ID + " = ? ", new String[]{image_id}, null);
    cursor.moveToFirst();
    String path = cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
    cursor.close();
    upLoadImageOrLogo(path);
}


3

Après avoir obtenu une image de la galerie, passez simplement l'URI dans la méthode ci-dessous uniquement pour Android 4.4 (KitKat):

public String getPath(Uri contentUri) {// Will return "image:x*"

    String wholeID = DocumentsContract.getDocumentId(contentUri);

    // Split at colon, use second item in the array
    String id = wholeID.split(":")[1];

    String[] column = { MediaStore.Images.Media.DATA };

    // Where id is equal to
    String sel = MediaStore.Images.Media._ID + "=?";

    Cursor cursor = getContentResolver().query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel,
            new String[] { id }, null);

    String filePath = "";

    int columnIndex = cursor.getColumnIndex(column[0]);

    if (cursor.moveToFirst()) {
        filePath = cursor.getString(columnIndex);
    }

    cursor.close();
    return filePath;
}

C'est le seul qui a fonctionné pour moi. Je voulais quelque chose de la galerie. Avez-vous une méthode de travail pour Kitkat ci-dessous? @sharma_kunai
SIr Codealot

3

Essaye ça

Pourtant, si vous rencontrez le problème pour obtenir le vrai chemin, vous pouvez essayer mes réponses. Les réponses ci-dessus ne m'ont pas aidé.

Explication : - Cette méthode obtient l'URI, puis vérifie le niveau d'API de votre appareil Android après que, selon le niveau d'API, il générera le chemin réel. Le code pour générer la méthode du chemin réel est différent selon les niveaux d'API.

  1. méthode pour obtenir le chemin réel à partir de l'URI

    @SuppressLint("ObsoleteSdkInt")
    public String getPathFromURI(Uri uri){
        String realPath="";
    // SDK < API11
        if (Build.VERSION.SDK_INT < 11) {
            String[] proj = { MediaStore.Images.Media.DATA };
            @SuppressLint("Recycle") Cursor cursor = getContentResolver().query(uri, proj, null, null, null);
            int column_index = 0;
            String result="";
            if (cursor != null) {
                column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                realPath=cursor.getString(column_index);
            }
        }
        // SDK >= 11 && SDK < 19
        else if (Build.VERSION.SDK_INT < 19){
            String[] proj = { MediaStore.Images.Media.DATA };
            CursorLoader cursorLoader = new CursorLoader(this, uri, proj, null, null, null);
            Cursor cursor = cursorLoader.loadInBackground();
            if(cursor != null){
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                realPath = cursor.getString(column_index);
            }
        }
        // SDK > 19 (Android 4.4)
        else{
            String wholeID = DocumentsContract.getDocumentId(uri);
            // Split at colon, use second item in the array
            String id = wholeID.split(":")[1];
            String[] column = { MediaStore.Images.Media.DATA };
            // where id is equal to
            String sel = MediaStore.Images.Media._ID + "=?";
            Cursor cursor = getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, column, sel, new String[]{ id }, null);
            int columnIndex = 0;
            if (cursor != null) {
                columnIndex = cursor.getColumnIndex(column[0]);
                if (cursor.moveToFirst()) {
                    realPath = cursor.getString(columnIndex);
                }
                cursor.close();
            }
        }
        return realPath;
     }
  2. Utilisez cette méthode comme ceci

    Log.e(TAG, "getRealPathFromURI: "+getPathFromURI(your_selected_uri) );

Production:-

04-06 12: 39: 46.993 6138-6138 / com.app.qtm E / tag: getRealPathFromURI: /storage/emulated/0/Video/avengers_infinity_war_4k_8k-7680x4320.jpg


1
Mon appareil physique avec API niveau 25 renvoie FATAL EXCEPTION avec la commande String wholeID = DocumentsContract.getDocumentId(uri);que j'obtiens:java.lang.RuntimeException: Failure delivering result
Aliton Oliveira

3

J'ai fait comme ça:

    Uri queryUri = MediaStore.Files.getContentUri("external");
    String columnData = MediaStore.Files.FileColumns.DATA;
    String columnSize = MediaStore.Files.FileColumns.SIZE;

    String[] projectionData = {MediaStore.Files.FileColumns.DATA};


    String name = null;
    String size = null;

    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if ((cursor != null)&&(cursor.getCount()>0)) {
        int nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
        int sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE);

        cursor.moveToFirst();

        name = cursor.getString(nameIndex);
        size = cursor.getString(sizeIndex);

        cursor.close();
    }

    if ((name!=null)&&(size!=null)){
        String selectionNS = columnData + " LIKE '%" + name + "' AND " +columnSize + "='" + size +"'";

        Cursor cursorLike = getContentResolver().query(queryUri, projectionData, selectionNS, null, null);

        if ((cursorLike != null)&&(cursorLike.getCount()>0)) {
            cursorLike.moveToFirst();
            int indexData = cursorLike.getColumnIndex(columnData);
            if (cursorLike.getString(indexData) != null) {
                result = cursorLike.getString(indexData);
            }
            cursorLike.close();
        }
    }

    return result;

2

Étant donné que managedQuery est obsolète, vous pouvez essayer:

CursorLoader cursorLoader = new CursorLoader(context, uri, proj, null, null, null);
Cursor cursor = cursorLoader.loadInBackground();

2

Ici, je vais vous montrer comment créer un bouton BROWSE qui, lorsque vous cliquerez, ouvrira la carte SD, vous sélectionnerez un fichier et, par conséquent, vous obtiendrez le nom de fichier et le chemin d'accès du fichier sélectionné une:

Un bouton que vous frapperez

browse.setOnClickListener(new OnClickListener()
{
    public void onClick(View v)
    {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_PICK);
        Uri startDir = Uri.fromFile(new File("/sdcard"));
        startActivityForResult(intent, PICK_REQUEST_CODE);
    }
});

La fonction qui obtiendra le nom du fichier résultant et le chemin du fichier

protected void onActivityResult(int requestCode, int resultCode, Intent intent)
{
    if (requestCode == PICK_REQUEST_CODE)
    {
        if (resultCode == RESULT_OK)
        {
            Uri uri = intent.getData();

            if (uri.getScheme().toString().compareTo("content")==0)
            {
                Cursor cursor =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"
                    Uri filePathUri = Uri.parse(cursor.getString(column_index));
                    String file_name = filePathUri.getLastPathSegment().toString();
                    String file_path=filePathUri.getPath();
                    Toast.makeText(this,"File Name & PATH are:"+file_name+"\n"+file_path, Toast.LENGTH_LONG).show();
                }
            }
        }
    }
}

J'ai suivi les suggestions ici et n'ai pas fonctionné. Lorsque je clique sur une pièce jointe du client de messagerie K9, je reçois content://com.fsck.k9.attachmentprovider/34fc2cc9-aa46-45e9-9e3f-2f27f0457249/1‌​/VIEW. Après avoir appliqué les méthodes ici, j'obtiens toujours la même chaîne, pas le bon chemin, c'est-à-dire /mnt/sdcard/Android/data/com.fsck.k9/files/34fc2cc9-aa46-45e9-9e3f-2f27f0457249‌​.db_att/1. Des indices?
Luis A. Florit

2

De toute façon pour Android Q passé , quand MediaStore.Images.Media.DATA ne sera plus disponible? Ce champ est déprécié dans Android Q:

Cette constante est déconseillée au niveau de l'API 29. Les applications peuvent ne pas disposer des autorisations de système de fichiers pour accéder directement à ce chemin. Au lieu d'essayer d'ouvrir directement ce chemin, les applications doivent utiliser ContentResolver # openFileDescriptor (Uri, String) pour y accéder.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#DATA

--- Modifié

Pour autant que je sache pour les anciens Android Q, la seule façon est de relayer sur RELATIVE_PATH

Chemin relatif de cet élément multimédia dans le périphérique de stockage où il est conservé. Par exemple, un élément stocké dans /storage/0000-0000/DCIM/Vacation/IMG1024.JPG aurait un chemin d'accès DCIM / Vacation /.

https://developer.android.com/reference/android/provider/MediaStore.MediaColumns.html#RELATIVE_PATH


tous les fichiers dans Android Q ont-ils un chemin relatif ou devons-nous les ajouter, comme si le fichier est déjà présent sur l'appareil, son chemin relatif sera disponible?
1234567

1
@ 1234567 selon la description dans le lien si vous le passez comme nul, alors le système le configurera correctement. Si le fichier est déjà présent, le scanner multimédia doit ajouter le champ.
Malachiasz

vous avez besoin d'Android Q comme API cible et peut-être activer le stockage étendu
Malachiasz

1

Version légèrement modifiée de @PercyPercy - elle ne lance pas et renvoie simplement null si quelque chose se passe mal :

public String getPathFromMediaUri(Context context, Uri uri) {
    String result = null;

    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
    int col = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
    if (col >= 0 && cursor.moveToFirst())
        result = cursor.getString(col);
    cursor.close();

    return result;
}

1

Ici vous obtenez le nom du fichier

String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
                    Uri uri = data.getData();
                    String fileName = null;
                    ContentResolver cr = getActivity().getApplicationContext().getContentResolver();

                    Cursor metaCursor = cr.query(uri,
                            projection, null, null, null);
                    if (metaCursor != null) {
                        try {
                            if (metaCursor.moveToFirst()) {
                                fileName = metaCursor.getString(0);
                            }
                        } finally {
                            metaCursor.close();
                        }
                    }

Probablement pas très utile pour l'op, car il cherchait le chemin absolu (pas seulement le nom du fichier) ... mais cela m'a vraiment aidé à comprendre le processus.
cola mystique

1

Simple et facile. Vous pouvez le faire à partir de l'URI comme ci-dessous!

public void getContents(Uri uri)
{
    Cursor vidCursor = getActivity.getContentResolver().query(uri, null, null,
                                                              null, null);
    if (vidCursor.moveToFirst())
    {
        int column_index =
        vidCursor .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        Uri filePathUri = Uri.parse(vidCursor .getString(column_index));
        String video_name =  filePathUri.getLastPathSegment().toString();
        String file_path=filePathUri.getPath();
        Log.i("TAG", video_name + "\b" file_path);
    }
}

1

Cette solution fonctionne pour chaque cas:

Dans certains cas, il est trop difficile d'obtenir le chemin à partir de l'URL. Alors pourquoi avez-vous besoin du chemin? Pour copier le fichier ailleurs? Vous n'avez pas besoin du chemin.

public void SavePhotoUri (Uri imageuri, String Filename){

    File FilePath = context.getDir(Environment.DIRECTORY_PICTURES,Context.MODE_PRIVATE);
    try {
        Bitmap selectedImage = MediaStore.Images.Media.getBitmap(context.getContentResolver(), imageuri);
        String destinationImagePath = FilePath + "/" + Filename;
        FileOutputStream destination = new FileOutputStream(destinationImagePath);
        selectedImage.compress(Bitmap.CompressFormat.JPEG, 100, destination);
        destination.close();
    }
    catch (Exception e) {
        Log.e("error", e.toString());
    }
}

0

Fonctionne parfaitement pour moi le code fixe de ce post :

  public static String getRealPathImageFromUri(Uri uri) {
        String fileName =null;
        if (uri.getScheme().equals("content")) {
            try (Cursor cursor = MyApplication.getInstance().getContentResolver().query(uri, null, null, null, null)) {
                if (cursor.moveToFirst()) {
                    fileName = cursor.getString(cursor.getColumnIndexOrThrow(ediaStore.Images.Media.DATA));
                }
            } catch (IllegalArgumentException e) {
                Log.e(mTag, "Get path failed", e);
            }
        }
        return fileName;
    }

0

En tant que module complémentaire, si vous devez voir si un fichier existe avant d'essayer d'ouvrir un flux d'entrée, vous pouvez utiliser DocumentsContract.

(Code Kotlin)

var iStream = null
if(DocumentsContract.isDocumentUri(context,myUri)) {
   val pfd: ParcelFileDescriptor? = context.contentResolver.openFileDescriptor(
            myUri, "r") ?: return null
   iStream = ParcelFileDescriptor.AutoCloseInputStream(pfd)
}

0

Étant donné que les réponses ci-dessus n'ont pas fonctionné pour moi, voici la solution qui a fonctionné pour moi:

Pour les niveaux d'API> 19 et <= 19.

Cette méthode couvre tous les cas pour obtenir filePath depuis uri

/**
 * Get a file path from a Uri. This will get the the path for Storage Access
 * Framework Documents, as well as the _data field for the MediaStore and
 * other file-based ContentProviders.
 *
 * @param context The activity.
 * @param uri The Uri to query.
 * @author paulburke
 */
public static String getPath(final Context context, final Uri uri) {

    // DocumentProvider
    if ( Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
        // ExternalStorageProvider
        if (isExternalStorageDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }else{
                Toast.makeText(context, "Could not get file path. Please try again", Toast.LENGTH_SHORT).show();
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // MediaProvider
        else if (isMediaDocument(uri)) {
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            } else {
                contentUri = MediaStore.Files.getContentUri("external");
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    }
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    }
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

0

Pour obtenir n'importe quelle sorte de chemin de fichier, utilisez ceci:

/*
 * Copyright (C) 2007-2008 OpenIntents.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.yourpackage;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.util.Log;
import android.webkit.MimeTypeMap;

import java.io.File;
import java.io.FileFilter;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;

/**
 * @author Peli
 * @author paulburke (ipaulpro)
 * @version 2013-12-11
 */
public class FileUtils {
    private FileUtils() {
    } //private constructor to enforce Singleton pattern

    /**
     * TAG for log messages.
     */
    static final String TAG = "FileUtils";
    private static final boolean DEBUG = true; // Set to true to enable logging

    public static final String MIME_TYPE_AUDIO = "audio/*";
    public static final String MIME_TYPE_TEXT = "text/*";
    public static final String MIME_TYPE_IMAGE = "image/*";
    public static final String MIME_TYPE_VIDEO = "video/*";
    public static final String MIME_TYPE_APP = "application/*";

    public static final String HIDDEN_PREFIX = ".";

    /**
     * Gets the extension of a file name, like ".png" or ".jpg".
     *
     * @param uri
     * @return Extension including the dot("."); "" if there is no extension;
     * null if uri was null.
     */
    public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

    /**
     * @return Whether the URI is a local one.
     */
    public static boolean isLocal(String url) {
        if (url != null && !url.startsWith("http://") && !url.startsWith("https://")) {
            return true;
        }
        return false;
    }

    /**
     * @return True if Uri is a MediaStore Uri.
     * @author paulburke
     */
    public static boolean isMediaUri(Uri uri) {
        return "media".equalsIgnoreCase(uri.getAuthority());
    }

    /**
     * Convert File into Uri.
     *
     * @param file
     * @return uri
     */
    public static Uri getUri(File file) {
        if (file != null) {
            return Uri.fromFile(file);
        }
        return null;
    }

    /**
     * Returns the path only (without file name).
     *
     * @param file
     * @return
     */
    public static File getPathWithoutFilename(File file) {
        if (file != null) {
            if (file.isDirectory()) {
                // no file to be split off. Return everything
                return file;
            } else {
                String filename = file.getName();
                String filepath = file.getAbsolutePath();

                // Construct path without file name.
                String pathwithoutname = filepath.substring(0,
                        filepath.length() - filename.length());
                if (pathwithoutname.endsWith("/")) {
                    pathwithoutname = pathwithoutname.substring(0, pathwithoutname.length() - 1);
                }
                return new File(pathwithoutname);
            }
        }
        return null;
    }

    /**
     * @return The MIME type for the given file.
     */
    public static String getMimeType(File file) {

        String extension = getExtension(file.getName());

        if (extension.length() > 0)
            return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.substring(1));

        return "application/octet-stream";
    }

    /**
     * @return The MIME type for the give Uri.
     */
    public static String getMimeType(Context context, Uri uri) {
        File file = new File(getPath(context, uri));
        return getMimeType(file);
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is {@link LocalStorageProvider}.
     * @author paulburke
     */
    public static boolean isLocalStorageDocument(Uri uri) {
        return LocalStorageProvider.AUTHORITY.equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     * @author paulburke
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     * @author paulburke
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     * @author paulburke
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context       The context.
     * @param uri           The Uri to query.
     * @param selection     (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     * @author paulburke
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                if (DEBUG)
                    DatabaseUtils.dumpCursor(cursor);

                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * Get a file path from a Uri. This will quickGet the the path for Storage Access
     * Framework Documents, as well as the _data field for the MediaStore and
     * other file-based ContentProviders.<br>
     * <br>
     * Callers should check whether the path is local before assuming it
     * represents a local file.
     *
     * @param context The context.
     * @param uri     The Uri to query.
     * @author paulburke
     * @see #isLocal(String)
     * @see #getFile(Context, Uri)
     */
    public static String getPath(final Context context, final Uri uri) {

        if (DEBUG)
            Log.d(TAG + " File -",
                    "Authority: " + uri.getAuthority() +
                            ", Fragment: " + uri.getFragment() +
                            ", Port: " + uri.getPort() +
                            ", Query: " + uri.getQuery() +
                            ", Scheme: " + uri.getScheme() +
                            ", Host: " + uri.getHost() +
                            ", Segments: " + uri.getPathSegments().toString()
            );
        // DocumentProvider
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && DocumentsContract.isDocumentUri(context, uri)) {
            // LocalStorageProvider
            if (isLocalStorageDocument(uri)) {
                // The path is the id
                return DocumentsContract.getDocumentId(uri);
            }
            // ExternalStorageProvider
            else if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

//                if ("primary".equalsIgnoreCase(type)) {
//                    return Environment.getExternalStorageDirectory() + "/" + split[1];
//                }
                return Environment.getExternalStorageDirectory() + "/" + split[1];

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                try {
                    final String id = DocumentsContract.getDocumentId(uri);
                    Log.d(TAG, "getPath: id= " + id);
                    final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                    return getDataColumn(context, contentUri, null, null);
                }catch (Exception e){
                    e.printStackTrace();
                    List<String> segments = uri.getPathSegments();
                    if(segments.size() > 1) {
                        String rawPath = segments.get(1);
                        if(!rawPath.startsWith("/")){
                            return rawPath.substring(rawPath.indexOf("/"));
                        }else {
                            return rawPath;
                        }
                    }
                }
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Convert Uri into File, if possible.
     *
     * @return file A local file that the Uri was pointing to, or null if the
     * Uri is unsupported or pointed to a remote resource.
     * @author paulburke
     * @see #getPath(Context, Uri)
     */
    public static File getFile(Context context, Uri uri) {
        if (uri != null) {
            String path = getPath(context, uri);
            if (path != null && isLocal(path)) {
                return new File(path);
            }
        }
        return null;
    }

    /**
     * Get the file size in a human-readable string.
     *
     * @param size
     * @return
     * @author paulburke
     */
    public static String getReadableFileSize(int size) {
        final int BYTES_IN_KILOBYTES = 1024;
        final DecimalFormat dec = new DecimalFormat("###.#");
        final String KILOBYTES = " KB";
        final String MEGABYTES = " MB";
        final String GIGABYTES = " GB";
        float fileSize = 0;
        String suffix = KILOBYTES;

        if (size > BYTES_IN_KILOBYTES) {
            fileSize = size / BYTES_IN_KILOBYTES;
            if (fileSize > BYTES_IN_KILOBYTES) {
                fileSize = fileSize / BYTES_IN_KILOBYTES;
                if (fileSize > BYTES_IN_KILOBYTES) {
                    fileSize = fileSize / BYTES_IN_KILOBYTES;
                    suffix = GIGABYTES;
                } else {
                    suffix = MEGABYTES;
                }
            }
        }
        return String.valueOf(dec.format(fileSize) + suffix);
    }

    /**
     * Attempt to retrieve the thumbnail of given File from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param file
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, File file) {
        return getThumbnail(context, getUri(file), getMimeType(file));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri) {
        return getThumbnail(context, uri, getMimeType(context, uri));
    }

    /**
     * Attempt to retrieve the thumbnail of given Uri from the MediaStore. This
     * should not be called on the UI thread.
     *
     * @param context
     * @param uri
     * @param mimeType
     * @return
     * @author paulburke
     */
    public static Bitmap getThumbnail(Context context, Uri uri, String mimeType) {
        if (DEBUG)
            Log.d(TAG, "Attempting to quickGet thumbnail");

        if (!isMediaUri(uri)) {
            Log.e(TAG, "You can only retrieve thumbnails for images and videos.");
            return null;
        }

        Bitmap bm = null;
        if (uri != null) {
            final ContentResolver resolver = context.getContentResolver();
            Cursor cursor = null;
            try {
                cursor = resolver.query(uri, null, null, null, null);
                if (cursor.moveToFirst()) {
                    final int id = cursor.getInt(0);
                    if (DEBUG)
                        Log.d(TAG, "Got thumb ID: " + id);

                    if (mimeType.contains("video")) {
                        bm = MediaStore.Video.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Video.Thumbnails.MINI_KIND,
                                null);
                    } else if (mimeType.contains(FileUtils.MIME_TYPE_IMAGE)) {
                        bm = MediaStore.Images.Thumbnails.getThumbnail(
                                resolver,
                                id,
                                MediaStore.Images.Thumbnails.MINI_KIND,
                                null);
                    }
                }
            } catch (Exception e) {
                if (DEBUG)
                    Log.e(TAG, "getThumbnail", e);
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
        return bm;
    }

    /**
     * File and folder comparator. TODO Expose sorting option method
     *
     * @author paulburke
     */
    public static Comparator<File> sComparator = new Comparator<File>() {
        @Override
        public int compare(File f1, File f2) {
            // Sort alphabetically by lower case, which is much cleaner
            return f1.getName().toLowerCase().compareTo(
                    f2.getName().toLowerCase());
        }
    };

    /**
     * File (not directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sFileFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return files only (not directories) and skip hidden files
            return file.isFile() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Folder (directories) filter.
     *
     * @author paulburke
     */
    public static FileFilter sDirFilter = new FileFilter() {
        @Override
        public boolean accept(File file) {
            final String fileName = file.getName();
            // Return directories only and skip hidden directories
            return file.isDirectory() && !fileName.startsWith(HIDDEN_PREFIX);
        }
    };

    /**
     * Get the Intent for selecting content to be used in an Intent Chooser.
     *
     * @return The intent for opening a file with Intent.createChooser()
     * @author paulburke
     */
    public static Intent createGetContentIntent() {
        // Implicitly allow the user to select a particular kind of data
        final Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        // The MIME data type filter
        intent.setType("*/*");
        // Only return URIs that can be opened with ContentResolver
        intent.addCategory(Intent.CATEGORY_OPENABLE);
        return intent;
    }
}

ne peut pas résoudre LocalStorageProvider
Zain

Enfin, une méthode qui marche! (de ce code, je viens de supprimer le LocalStorageProvider)
Starwave

0

Vérifiez ci-dessous la méthode fonctionne aussi très bien Oreo 8.1 ..

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    // TODO ManualMT-generated method stub
    switch (requestCode) {
        case PICKFILE_RESULT_CODE:
            if (resultCode == RESULT_OK) {

                try {
                    FilePath = data.getData().getPath();
                    Uri selectedImageUri = data.getData();

                    if (selectedImageUri.toString().contains("storage/emulated")){
                        String[] split = selectedImageUri.toString().split("storage/");
                        FilePath = "storage/"+split[1];
                    } else {
                        FilePath = ImageFilePath.getPath(getApplicationContext(), selectedImageUri);
                    }

                    recyclerview.setVisibility(View.VISIBLE);

                    if (FilePath == null) {
                        FilePath = "";
                    }
                    File file = new File(FilePath);
                    reqFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
                    image_list.add(FilePath);
                    composeImageAdapter.notifyDataSetChanged();
                } catch (Exception e){
                    Toast.makeText(ClusterCreateNote.this , e.toString(),Toast.LENGTH_SHORT).show();
                }
            }
            break;
    }

}

Classe de chemin URI:

public static class ImageFilePath {

    /**
     * Method for return file path of Gallery image
     *
     * @param context
     * @param uri
     * @return path of the selected image file from gallery
     */
    public static String getPath(final Context context, final Uri uri) {
        String selection = null;
        String[] selectionArgs = null;

        // DocumentProvider
        if (DocumentsContract.isDocumentUri(context, uri)) {

            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.wifAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Log.e("typetype",type);

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                selection = "_id=?";
                selectionArgs = new String[]{
                        split[1]
                };

                Log.e("gddhjf",getDataColumn(context, contentUri, selection, selectionArgs));

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        if ("content".equalsIgnoreCase(uri.getScheme())) {


            if (isGooglePhotosUri(uri)) {
                return uri.getLastPathSegment();
            }

            String[] projection = {
                    MediaStore.Images.Media.DATA
            };
            Cursor cursor = null;
            try {
                cursor = context.getContentResolver()
                        .query(uri, projection, selection, selectionArgs, null);
                int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                if (cursor.moveToFirst()) {
                    return cursor.getString(column_index);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }


    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return
                "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    public static boolean isGooglePhotosUri(Uri uri) {
        return
                "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }
}

1
Vous utilisez la colonne de données, cela ne fonctionnera plus.
HB.

0

Je le fais avec une doublure:

val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, uri)

Qui dans onActivityResult ressemble à:

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE_IMAGE_PICKER ) {
        data?.data?.let { imgUri: Uri ->
            val bitmap = MediaStore.Images.Media.getBitmap(contentResolver, imgUri)
        }
    }
}

Pour une raison quelconque, cette approche ne fonctionne pas si j'utilise l'application de galerie Samsung pour sélectionner une image
KMC

Bizarre. Je développais sur un Samsung Galaxy S10.
Joel Broström

0

Les choses sont compliquées maintenant, surtout après le niveau d'API 29 Android Q.C'est ainsi que vous devriez obtenir le nom de fichier du contenu Uri

        public static String getNameFromContentUri(Context context, Uri contentUri){  
                            Cursor returnCursor = context.getContentResolver().query(contentUri, null, null, null, null);
                            int nameColumnIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
                            returnCursor.moveToFirst();
                            String fileName = returnCursor.getString(nameColumnIndex);
                            return fileName;}

et voici comment obtenir le chemin d'accès complet de Content Uri pour toutes les versions Android

public static String getFullPathFromContentUri(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{
                        split[1]
                };

                   Cursor cursor = null;
                   final String column = "_data";
                   final String[] projection = {
                      column
                    };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

private static String getDataColumn(Context context, Uri uri, String selection,
                                 String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int column_index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

0

Cela fonctionne parfaitement pour moi si la version de votre système est supérieure à 19, j'espère que cela peut vous aider.

  @TargetApi(Build.VERSION_CODES.KITKAT)
    public static String getPath(final Context context, final Uri uri) {
        final boolean isOverKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isOverKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/"
                            + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {
                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(id));
                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];
                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }
                final String selection = "_id=?";
                final String[] selectionArgs = new String[]{split[1]};
                return getDataColumn(context, contentUri, selection,
                        selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();
            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
        return null;
    }

-2

Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), uri);


Cela ne fournit pas de réponse à la question. Une fois que vous avez une réputation suffisante, vous pourrez commenter n'importe quel message ; fournissez plutôt des réponses qui ne nécessitent pas de clarification de la part du demandeur . - De l'avis
ישו אוהב אותך

"Je veux charger l'image dans un bitmap sans avoir à la copier quelque part." , je pense que cette réponse fournit une réponse à la question!
Drastaro
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.