androïde obtenir vrai chemin par Uri.getPath()

j'essaie d'obtenir une image de la galerie.

Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select picture"), resultCode );

après mon retour de cette activité, j'ai une donnée, qui contient Uri. On dirait:

content://media/external/images/1

comment convertir ce chemin en chemin réel (comme /sdcard/image.png ')?

Merci

84
demandé sur davs 2010-05-07 18:27:14

9 réponses

Est-il vraiment nécessaire pour vous d'obtenir un chemin d'accès physique?

Par exemple, ImageView.setImageURI() et ContentResolver.openInputStream() vous permettent d'accéder au contenu d'un fichier sans en connaître le véritable chemin.

50
répondu Márton Molnár 2016-09-06 17:47:12

C'est ce que je fais:

Uri selectedImageURI = data.getData();
imageFile = new File(getRealPathFromURI(selectedImageURI));

et:

private String getRealPathFromURI(Uri contentURI) {
    String result;
    Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
    if (cursor == null) { // Source is Dropbox or other similar local file path
        result = contentURI.getPath();
    } else { 
        cursor.moveToFirst(); 
        int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA); 
        result = cursor.getString(idx);
        cursor.close();
    }
    return result;
}

NOTE: managedQuery() méthode est dépréciée, donc je ne l'utilise pas.

dernière édition: amélioration. On devrait fermer le curseur!!

172
répondu cesards 2014-02-18 12:56:18

@Rene Juuse-ci-dessus dans les commentaires... Merci pour ce lien!!!

. le code pour obtenir le chemin réel est un peu différent d'un SDK à l'autre donc ci-dessous nous avons trois méthodes qui traitent avec différents SDK.

getRealPathFromURI_API19 (): renvoie le chemin réel pour API 19 (ou plus haut mais non testé)) getRealPathFromURI_API11to18 (): renvoie real path pour API 11 à API 18 getRealPathFromURI_below11 (): renvoie le chemin réel pour API below 11

public class RealPathUtil {

@SuppressLint("NewApi")
public static String getRealPathFromURI_API19(Context context, Uri uri){
    String filePath = "";
    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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                               column, sel, new String[]{ id }, null);

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

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


@SuppressLint("NewApi")
public static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
      String[] proj = { MediaStore.Images.Media.DATA };
      String result = null;

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

      if(cursor != null){
       int column_index = 
         cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
       cursor.moveToFirst();
       result = cursor.getString(column_index);
      }
      return result;  
}

public static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri){
           String[] proj = { MediaStore.Images.Media.DATA };
           Cursor 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);
}

font: http://hmkcode.com/android-display-selected-image-and-its-real-path /


mise à jour 2016 mars

pour corriger tous les problèmes avec le chemin des images, j'essaie de créer une galerie personnalisée comme facebook et d'autres applications. C'est parce que vous pouvez utiliser juste des fichiers locaux ( fichiers réels, pas virtuels ou temporaires) , Je résous tous les problèmes avec cette bibliothèque.

https://github.com/nohana/Laevatein (cette bibliothèque est de prendre des photos de l'appareil photo ou de choisir de la galerie , si vous choisissez dans la galerie il a un tiroir avec des albums et juste montrer des dossiers locaux)

15
répondu luizfelipetx 2016-03-25 05:19:51

Note c'est une amélioration dans @user3516549 réponse et je l'ai vérifier sur Moto G3 avec Android 6.0.1

J'ai ce problème j'ai donc essayé de réponse de @user3516549 mais dans certains cas, il ne fonctionnait pas correctement. J'ai trouvé que dans Android 6.0 (ou au-dessus) quand nous commençons Galerie image pick intention puis un écran s'ouvrira qui montre les images récentes lorsque l'utilisateur sélectionne l'image de cette liste, nous obtiendrons uri comme

content://com.android.providers.media.documents/document/image%3A52530

alors que si l'utilisateur sélectionne galerie à partir de tiroir coulissant au lieu de récent, nous obtiendrons uri comme

content://media/external/images/media/52530

donc je dois gérer en getRealPathFromURI_API19()

public static String getRealPathFromURI_API19(Context context, Uri uri) {
        String filePath = "";
        if (uri.getHost().contains("com.android.providers.media")) {
            // Image pick from recent 
            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 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    column, sel, new String[]{id}, null);

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

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();
            return filePath;
        } else {
            // image pick from gallery 
           return  getRealPathFromURI_BelowAPI11(context,uri)
        }

    }

EDIT : si vous essayez d'obtenir le chemin de l'image de fichier dans la carte sd externe en plus de la version puis cochez la case ma question

10
répondu Jaiprakash Soni 2017-05-25 12:00:19

il n'y a pas de véritable chemin .

Un Uri avec un content système est opaque poignée à certains contenus. Si ce Uri représente un contenu ouvert, vous pouvez utiliser ContentResolver et openInputStream() pour obtenir un InputStream sur ce contenu. De même, un Uri avec un schéma http ou https ne représente pas un fichier local, et vous devrez utiliser une API client HTTP pour y accéder.

seul un Uri avec un schéma file identifie un fichier (sauf dans les cas où le fichier a été déplacé ou supprimé après la création du Uri ).

ce que les gens stupides font est d'essayer de dériver un chemin du système de fichiers en essayant de décoder le contenu du Uri , peut-être couplé avec des sorts de lancer pour invoquer $EVIL_DEITY . Au mieux, cela ne sera pas fiable, pour trois raisons:

  1. les règles pour le décodage des valeurs Uri peut changer au fil du temps, comme avec les versions Android, comme la structure du Uri représente un détail de mise en œuvre, pas une interface

  2. même si vous obtenez un chemin du système de fichiers, vous ne pouvez pas avoir le droit d'accéder au fichier

  3. pas toutes les valeurs Uri peuvent être décodées via des algorithmes fixes, car de nombreuses applications ont leurs propres fournisseurs, et ceux-ci peut-point à l'actif de BLOB colonnes de données qui doit être transmis à partir de l'Internet

si vous avez une API limitée qui nécessite un fichier, utilisez le InputStream de openInputStream() pour faire une copie de ce contenu. Qu'il s'agisse d'une copie transitoire (par exemple, utilisée pour une opération de téléchargement de fichier, puis supprimée) ou d'une copie durable (par exemple, pour une fonction "Importer" de votre application) dépend de vous.

6
répondu CommonsWare 2018-04-03 11:15:30

EDIT: Utilisez cette Solution ici: https://stackoverflow.com/a/20559175/2033223 Fonctionne parfaitement!

tout D'abord, merci pour votre solution @luizfelipetx

j'ai un peu changé votre solution. Cela me convient:

public static String getRealPathFromDocumentUri(Context context, Uri uri){
    String filePath = "";

    Pattern p = Pattern.compile("(\d+)$");
    Matcher m = p.matcher(uri.toString());
    if (!m.find()) {
        Log.e(ImageConverter.class.getSimpleName(), "ID for requested image not found: " + uri.toString());
        return filePath;
    }
    String imgId = m.group();

    String[] column = { MediaStore.Images.Media.DATA };
    String sel = MediaStore.Images.Media._ID + "=?";

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

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

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

    return filePath;
}

Note: Nous avons donc des documents et des images, selon que l'image provient de 'récents', 'galerie' ou quoi que ce soit. Donc j'extrait d'abord L'ID de l'image avant de regarder.

4
répondu Javatar 2017-05-23 12:34:41

hii voici mon code complet pour prendre des images de la caméra ou de la galerie

/ / ma déclaration de variable

protected static final int CAMERA_REQUEST = 0;
    protected static final int GALLERY_REQUEST = 1;
    Bitmap bitmap;
    Uri uri;
    Intent picIntent = null;

/ / Onclick

if (v.getId()==R.id.image_id){
            startDilog();
        }

//corps de la méthode

private void startDilog() {
    AlertDialog.Builder myAlertDilog = new AlertDialog.Builder(yourActivity.this);
    myAlertDilog.setTitle("Upload picture option..");
    myAlertDilog.setMessage("Where to upload picture????");
    myAlertDilog.setPositiveButton("Gallery", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(Intent.ACTION_GET_CONTENT,null);
            picIntent.setType("image/*");
            picIntent.putExtra("return_data",true);
            startActivityForResult(picIntent,GALLERY_REQUEST);
        }
    });
    myAlertDilog.setNegativeButton("Camera", new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            picIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
            startActivityForResult(picIntent,CAMERA_REQUEST);
        }
    });
    myAlertDilog.show();
}

//Et le reste des choses

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode==GALLERY_REQUEST){
        if (resultCode==RESULT_OK){
            if (data!=null) {
                uri = data.getData();
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                try {
                    BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    options.inSampleSize = calculateInSampleSize(options, 100, 100);
                    options.inJustDecodeBounds = false;
                    Bitmap image = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
                    imageofpic.setImageBitmap(image);
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                }
            }else {
                Toast.makeText(getApplicationContext(), "Cancelled",
                        Toast.LENGTH_SHORT).show();
            }
        }else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }else if (requestCode == CAMERA_REQUEST) {
        if (resultCode == RESULT_OK) {
            if (data.hasExtra("data")) {
                bitmap = (Bitmap) data.getExtras().get("data");
                uri = getImageUri(YourActivity.this,bitmap);
                File finalFile = new File(getRealPathFromUri(uri));
                imageofpic.setImageBitmap(bitmap);
            } else if (data.getExtras() == null) {

                Toast.makeText(getApplicationContext(),
                        "No extras to retrieve!", Toast.LENGTH_SHORT)
                        .show();

                BitmapDrawable thumbnail = new BitmapDrawable(
                        getResources(), data.getData().getPath());
                pet_pic.setImageDrawable(thumbnail);

            }

        } else if (resultCode == RESULT_CANCELED) {
            Toast.makeText(getApplicationContext(), "Cancelled",
                    Toast.LENGTH_SHORT).show();
        }
    }
}

private String getRealPathFromUri(Uri tempUri) {
    Cursor cursor = null;
    try {
        String[] proj = { MediaStore.Images.Media.DATA };
        cursor = this.getContentResolver().query(tempUri,  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();
        }
    }
}
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {

        final int halfHeight = height / 2;
        final int halfWidth = width / 2;

        // Calculate the largest inSampleSize value that is a power of 2 and keeps both
        // height and width larger than the requested height and width.
        while ((halfHeight / inSampleSize) > reqHeight
                && (halfWidth / inSampleSize) > reqWidth) {
            inSampleSize *= 2;
        }
    }
    return inSampleSize;
}

private Uri getImageUri(YourActivity youractivity, Bitmap bitmap) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream);
    String path = MediaStore.Images.Media.insertImage(youractivity.getContentResolver(), bitmap, "Title", null);
    return Uri.parse(path);
}
1
répondu Tanmay Sahoo 2016-11-15 15:34:50

cela m'a aidé à obtenir uri de la galerie et convertir en un fichier pour le téléchargement Multipart

File file = FileUtils.getFile(this, fileUri);

https://github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java

0
répondu Veeresh Charantimath 2017-06-06 20:01:25

Essayez Cette

encore, si vous obtenez 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 et puis vérifier le niveau API de votre appareil Android après que selon le niveau API, il va générer le chemin réel. Le Code pour générer le chemin réel est différent selon les niveaux de L'API.

voici ma réponse

0
répondu Sunil 2018-04-06 07:36:36