android, Uri.getPath () ile gerçek yolu alır


107

Galeriden resim almaya çalışıyorum.

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

Bu aktiviteden döndükten sonra Uri içeren bir veriye sahibim. Şöyle görünüyor:

content://media/external/images/1

Bu yolu gerçek yola nasıl dönüştürebilirim (tıpkı ' /sdcard/image.png' gibi )?

Teşekkürler


1
Bu açıkça çok geç bir yorum, ancak sadece startActivityForResultCode yönteminin bir sonuç kodu değil, argüman olarak bir istek kodu aldığını belirtmek istedim.
Tianxiang Xiong

did uri.getPath()Size gerçek yolunu vermedi?
Darpan

# Bunu Hala Deneyin, gerçek yolu bulmak için sorun yaşıyorsanız, cevaplarımı deneyebilirsiniz. Yukarıdaki cevaplar bana yardımcı olmadı. Açıklama : - Bu yöntem URI'yi alır ve ardından Android cihazınızın API düzeyini kontrol eder, bundan sonra API düzeyine göre Gerçek yolu oluşturur. Gerçek yol oluşturma kodu, API seviyelerine göre farklıdır. İşte
Sunil

Yanıtlar:


56

Fiziksel bir yol bulmanız gerçekten gerekli mi?
Örneğin, ImageView.setImageURI()ve ContentResolver.openInputStream()onun gerçek yolunu bilmeden bir dosyanın içeriğine erişmek için izin verir.


Tam olarak aradığım ama bulamadım. Teşekkürler.
davs

6
Pardon ve bu görüntüyü dosyaya dönüştürmek istersem, gerçek yolu öğrenmeden nasıl yapılır?
Chlebta

6
Fiziksel yol, dosya adına ve uzantıya erişim sağlar. Dosya yüklemeleri durumunda.
Clocker

195

Bu benim işim:

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

ve:

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

NOT: managedQuery()yöntem kullanımdan kaldırıldı, bu yüzden kullanmıyorum.

Son düzenleme: İyileştirme. İmleci kapatmalıyız !!


1
stackoverflow.com/a/7265235/375093 Bu başka bir seçenektir, ancak yukarıdakinden daha iyi olması önerilir. Bunu da kontrol edin
Sundeep

6
Merhaba @ m3n0R, Moto G'de MediaStore.Images.ImageColumns.DATA sütunu hiç mevcut değil. Bu sütun olmadan nasıl görüntü elde edilir?
seema

16
ERROR Verilere erişmeden önce İmlecin doğru şekilde başlatıldığından emin olun .. API 19'da kontrol
Mayur R. Amipara

1
@ReneJuuse: Mükemmel kaynak. Sonunda bu sorunu çözmeyi başardım - Android'in başlangıcından bu yana çok fazla değişiklik olduğunu fark etmemiştim. API 21'i çalıştırıyordum ve bağladığınız sitede gösterilen API 19 uygulamasını kullandığımda sonunda işe yaradı.
Milos Ivanovic

2
CursorWindow'dan satır 0, sütun -1 okunamadı. Verilere erişmeden önce İmlecin doğru şekilde başlatıldığından emin olun.
Maveň ツ

18

@Rene Juuse - yorumlarda yukarıda ... Bu bağlantı için teşekkürler!

. gerçek yolu elde etmek için kullanılan kod bir SDK'dan diğerine biraz farklıdır, bu nedenle aşağıda farklı SDK'larla ilgilenen üç yöntemimiz vardır.

getRealPathFromURI_API19 (): API 19 için gerçek yolu döndürür (veya üstü ancak test edilmemiştir) getRealPathFromURI_API11to18 (): API 11'den API 18'e gerçek yolu döndürür getRealPathFromURI_below11 (): 11'in altındaki API için gerçek yolu döndürür

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);
}

yazı tipi: http://hmkcode.com/android-display-selected-image-and-its-real-path/


GÜNCELLEME 2016 Mart

Görüntü yollarıyla ilgili tüm sorunları çözmek için facebook ve diğer uygulamalar olarak özel bir galeri oluşturmayı deniyorum. Bunun nedeni, sadece yerel dosyaları kullanabilmenizdir (gerçek dosyalar, sanal veya geçici değil), bu kitaplıkla tüm sorunları çözüyorum.

https://github.com/nohana/Laevatein (bu kütüphane kameradan fotoğraf çekmek veya galeriden seçim yapmak içindir, galeriden seçerseniz albümleri olan bir çekmecesi vardır ve sadece yerel dosyaları gösterir)


@Clocker da Samsung S4'te
Ricardo

Android'de her türden kaynak görüntüyü yönetmek gerçekten zor. Eğer yüklerseniz veya galeriden seçim yaparsanız, en iyi çözüm facebook'tan bir galeri oluşturmaktır. Sanal veya geçici olmayan, cihazda yalnızca gerçek görüntülerin bulunduğu özel bir galeri. Bu kitaplığı kullanarak uygulamamdaki tüm sorunları düzeltirim. github.com/nohana/Laevatein Gerçekten iyi bir kitaplığı. Özelleştirmek basit değildir, ancak kodu açabilir ve değişikliklerinizi yapabilirsiniz. umuyorum ki bu sana yardım edebilir.
luizfelipetx

Samsung S2 cihazımda 4.4.1 ile bozuldu
Oliver Dixon

Pdf veya doc gibi dosyaları almam gerekiyor, yolu alamıyorum. Lütfen bana yardım edebilir misin?
Anish Kumar

1
Harika! Sonunda gerçekten işe yarayan bir şey. Bunu uzun zamandır arıyordum. Teşekkürler.
Javatar

14

Not Bu, @ user3516549 yanıtındaki bir gelişmedir ve Android 6.0.1 ile Moto G3'te kontrol
ettim Bu sorunu yaşıyorum, bu nedenle @ user3516549 yanıtını denedim ancak bazı durumlarda düzgün çalışmıyordu. Android 6.0'da (veya üzeri) galeri resmini başlatmaya başladığımızda, kullanıcı bu listeden resim seçtiğinde son resimleri gösteren bir ekranın açılacağını buldum.

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

kullanıcı yeni yerine kayan çekmeceden galeriyi seçerse, uri'yi

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

Bu yüzden hallettim 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)
        }

    }

DÜZENLEME: Daha yüksek sürümde harici sdcard'da dosyanın görüntü yolunu almaya çalışıyorsanız, sorumu kontrol edin


Merhaba arkadaşım, evet bu doğru. ancak bu gerçekleşiyor çünkü artık google, telefonunuzdan tüm fotoğrafları google docs'a yüklemek için varsayılan bir biçime sahip. Ve telefonunuza parmaklarınızı kaydedin. Bu uri'yi google docs'tan alırsanız, bunu kullanmadan önce fotoğrafı indirmeniz gerekir. Bu genel olarak iyi değil. Yani, buradaki tüm sorunları çözmek için, şimdi bu kütüphaneyi kullanıyorum. (bu kütüphane sadece yerel dosyaları kullanır ve bu çözümle problemleriniz çözülecektir) veya kodu kütüphaneden çıkarabilir ve probleminize katılmak için kendinizi geliştirebilirsiniz. github.com/nohana/Laevatein Umarım bu size yardımcı olabilir.
luizfelipetx

1+, Çalışması benim için mükemmel. @ JaiprakasSoni'nin cevabında söylediği gibi, uygulamamı Moto G4 oyununda çalıştırdığımda aynı sorunla karşılaştığımı ancak yukarıdaki kodu kullandığımda benim için iyi çalışıyor. Teşekkürler. Sen benim zamanımı kurtar
Shailesh

6

DÜZENLEME: Bu Çözümü burada kullanın: https://stackoverflow.com/a/20559175/2033223 Mükemmel çalışıyor!

Öncelikle çözümünüz için teşekkürler @luizfelipetx

Çözümünüzü biraz değiştirdim. Bu benim için çalışıyor:

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

Not: Dolayısıyla, görselin 'son', 'galeri' veya herhangi birinden gelip gelmediğine bağlı olarak belgelerimiz ve görselimiz var. Bu yüzden bakmadan önce görüntü kimliğini çıkarıyorum.


1

Hii işte kamera veya galeriden görüntü almak için tam kodum

// Değişken bildirimim

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

//Tıklamada

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

// yöntem gövdesi

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();
}

// Ve diğer şeyler

@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);
}

Bu satırın 100 olduğunu nereden biliyorsun options.inSampleSize = calculateInSampleSize(options, 100, 100);
John Joe

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.