300 votes

Obtenir l'url du contenu à partir du chemin du fichier dans Android

Je connais le chemin absolu d'une image (par exemple, /sdcard/cats.jpg). Existe-t-il un moyen d'obtenir l'url du contenu de ce fichier ?

En fait, dans mon code, je télécharge une image et l'enregistre à un endroit particulier. Afin de définir l'image dans une instance ImageView, j'ouvre actuellement le fichier en utilisant le chemin, je récupère les octets et crée un bitmap, puis je définis le bitmap dans l'instance ImageView. C'est un processus très lent. Si je pouvais obtenir l'url du contenu, je pourrais très facilement utiliser la méthode suivante imageView.setImageUri(uri)

26 votes

Uri uri = Uri.parse("file:///sdcard/img.png") ;

14 votes

+1 au commentaire, juste Uri.parse("file://" + filePath) devrait faire l'affaire.

0 votes

Uri.Parse est déprécié et "à ajouter".

515voto

Francesco Laurita Points 12027

Essayez avec :

ImageView.setImageURI(Uri.fromFile(new File("/sdcard/cats.jpg")));

Ou avec :

ImageView.setImageURI(Uri.parse(new File("/sdcard/cats.jpg").toString()));

3 votes

Merci ! la deuxième méthode fonctionne bien sur 1.6, 2.1 et 2.2 mais la première seulement sur 2.2

36 votes

Aucune de ces méthodes ne résout un chemin d'accès à un fichier vers un URI de contenu. je comprends que cela a résolu le problème immédiat cependant.

0 votes

Dans le cas où vous avez le chemin de la carte SD mais que vous voulez l'uri du contenu, l'idée de @Jon O fonctionne parfaitement : stackoverflow.com/a/11603841/336990

97voto

Jinal Jogiyani Points 183

UPDATE

On suppose ici que votre média (image/vidéo) est déjà ajouté au fournisseur de média de contenu. Si ce n'est pas le cas, vous ne pourrez pas obtenir l'URL du contenu exactement comme vous le souhaitez. URL du contenu exactement comme vous le souhaitez. Au lieu de cela, il y aura un Uri de fichier.

J'ai eu la même question pour mon activité d'explorateur de fichiers. Vous devez savoir que le contenturi pour le fichier ne supporte que les données mediastore comme l'image, l'audio et la vidéo. Je vous donne le code pour obtenir l'uri du contenu d'une image à partir de la sélection d'une image sur la carte SD. Essayez ce code, peut-être qu'il fonctionnera pour vous...

public static Uri getImageContentUri(Context context, File imageFile) {
  String filePath = imageFile.getAbsolutePath();
  Cursor cursor = context.getContentResolver().query(
      MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
      new String[] { MediaStore.Images.Media._ID },
      MediaStore.Images.Media.DATA + "=? ",
      new String[] { filePath }, null);
  if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
  } else {
    if (imageFile.exists()) {
      ContentValues values = new ContentValues();
      values.put(MediaStore.Images.Media.DATA, filePath);
      return context.getContentResolver().insert(
          MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
    } else {
      return null;
    }
  }
}

Pour le support Android Q

public static Uri getImageContentUri(Context context, File imageFile) {
String filePath = imageFile.getAbsolutePath();
Cursor cursor = context.getContentResolver().query(
        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
        new String[]{MediaStore.Images.Media._ID},
        MediaStore.Images.Media.DATA + "=? ",
        new String[]{filePath}, null);
if (cursor != null && cursor.moveToFirst()) {
    int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
    cursor.close();
    return Uri.withAppendedPath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, "" + id);
} else {
    if (imageFile.exists()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            ContentResolver resolver = context.getContentResolver();
            Uri picCollection = MediaStore.Images.Media
                    .getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
            ContentValues picDetail = new ContentValues();
            picDetail.put(MediaStore.Images.Media.DISPLAY_NAME, imageFile.getName());
            picDetail.put(MediaStore.Images.Media.MIME_TYPE, "image/jpg");
            picDetail.put(MediaStore.Images.Media.RELATIVE_PATH,"DCIM/" + UUID.randomUUID().toString());
            picDetail.put(MediaStore.Images.Media.IS_PENDING,1);
            Uri finaluri = resolver.insert(picCollection, picDetail);
            picDetail.clear();
            picDetail.put(MediaStore.Images.Media.IS_PENDING, 0);
            resolver.update(picCollection, picDetail, null, null);
            return finaluri;
        }else {
            ContentValues values = new ContentValues();
            values.put(MediaStore.Images.Media.DATA, filePath);
            return context.getContentResolver().insert(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        }

    } else {
        return null;
    }
  }
}

0 votes

Je cherchais une méthode pour trouver l'URI content:// de mon fichier vidéo enregistré et le code ci-dessus semble fonctionner parfaitement sur le Nexus 4(Android 4.3). Ce serait bien si vous pouviez expliquer le code.

0 votes

J'ai essayé d'obtenir l'Uri de contenu d'un fichier avec le chemin absolu "/sdcard/Image Depo/picture.png". Cela n'a pas fonctionné, alors j'ai débogué le chemin de code et j'ai trouvé que le curseur est vide, et quand l'entrée est ajoutée au ContentProvider, il donne null comme Uri de contenu. Veuillez m'aider.

0 votes

Ceci devrait être la réponse acceptée ! Il s'agit également du correctif pour le plantage des applications dans Android preview N (niveau 24 de l'API à venir), lorsque vous essayez de prendre une photo avec ACTION_IMAGE_CAPTURE en utilisant un fichier : Uri pour EXTRA_OUTPUT, ce qui entraîne une FileUriExposedException. Il suffit de remplacer votre putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile)) avec putExtra(MediaStore.EXTRA_OUTPUT, getImageContentUri(context, imageFile)) .

18voto

Jon O Points 3545

La solution acceptée est probablement la plus adaptée à vos besoins, mais elle consiste à répondre réellement à la question posée dans l'objet du message :

Dans mon application, je dois récupérer le chemin à partir des URI et récupérer l'URI à partir des chemins. 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 la sous-section que vous interrogez) stocke le chemin d'accès au fichier, de sorte que vous utilisez cette information pour le rechercher.

0 votes

Ce n'est pas toujours le cas, il y a deux colonnes semi-garanties qui sont retournées, à savoir OpenableColumns.DISPLAY_NAME & OpenableColumns.SIZE si l'application d'envoi respecte même les "règles". J'ai constaté que certaines applications majeures ne renvoient que ces deux champs et pas toujours les champs de l'adresse. _data champ. Dans le cas où vous ne disposez pas du champ de données qui contient normalement un chemin direct vers le contenu, vous devez d'abord lire le contenu et l'écrire dans un fichier ou dans la mémoire, puis vous disposez de votre propre chemin.

16voto

AndroidDebaser Points 129

// Ce code fonctionne pour les images sur 2.2, je ne suis pas sûr que les autres types de médias fonctionnent.

   //Your file path - Example here is "/sdcard/cats.jpg"
   final String filePathThis = imagePaths.get(position).toString();

   MediaScannerConnectionClient mediaScannerClient = new
   MediaScannerConnectionClient() {
    private MediaScannerConnection msc = null;
    {
        msc = new MediaScannerConnection(getApplicationContext(), this);
        msc.connect();
    }

    public void onMediaScannerConnected(){
        msc.scanFile(filePathThis, null);
    }

    public void onScanCompleted(String path, Uri uri) {
        //This is where you get your content uri
            Log.d(TAG, uri.toString());
        msc.disconnect();
    }
   };

1 votes

Super, cela m'a aidé à partager avec Google+, car cette application nécessite un flux multimédia avec un Uri de contenu - le chemin absolu ne fonctionne pas.

1 votes

Excellent ! Je peux confirmer que cela fonctionne également avec les types de médias audio.

3voto

Bogdan Biv Points 390

Obtention de l'ID du fichier sans écrire de code, juste avec les commandes CLI du shell adb :

adb shell content query --uri "content://media/external/video/media" | grep FILE_NAME | grep -Eo " _id=([0-9]+)," | grep -Eo "[0-9]+"

0 votes

Google "adb get real path from content uri" et cette question est en tête de liste, avec le contenu de votre réponse à 0 vote dans le résumé des résultats de recherche. Alors laissez-moi être le premier à voter. MERCI mon frère !

0 votes

C'est cool. Mais il semble que tu vas avoir : Permission Denial: Do not have permission in call getContentProviderExternal() from pid=15660, uid=10113 requires android.permission.ACCESS_CONTENT_PROVIDERS_EXTERNALLY à moins que vous ne soyez enraciné.

0 votes

Donc cela nécessite un accès Root du téléphone ?

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