android mendapatkan jalur nyata oleh Uri.getPath ()

107

Saya mencoba untuk mendapatkan gambar dari galeri.

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

Setelah saya kembali dari kegiatan ini saya memiliki data yang berisi Uri. Sepertinya:

content://media/external/images/1

Bagaimana cara mengubah jalur ini menjadi jalur nyata (seperti ' /sdcard/image.png')?

Terima kasih

davs
sumber
1
Ini jelas merupakan komentar yang sangat terlambat, tetapi saya hanya ingin menunjukkan bahwa metode startActivityForResultCode mengambil kode permintaan sebagai argumen, bukan kode hasil.
Tianxiang Xiong
tidak uri.getPath()tidak memberi Anda jalan nyata?
Darpan
#Coba Ini Namun, jika Anda mendapatkan masalah untuk mendapatkan jalur yang sebenarnya, Anda dapat mencoba jawaban saya. Jawaban di atas tidak membantu saya. Penjelasan : - Metode ini mendapatkan URI dan kemudian memeriksa API level perangkat Android Anda setelah itu sesuai dengan API level itu akan menghasilkan jalur Real. Kode untuk menghasilkan jalur nyata berbeda menurut level API. Ini Jawaban saya
Sunil

Jawaban:

56

Apakah Anda benar-benar perlu mendapatkan jalur fisik?
Misalnya, ImageView.setImageURI()dan ContentResolver.openInputStream()memungkinkan Anda mengakses konten file tanpa mengetahui jalur aslinya.

molnarm
sumber
Persis seperti yang saya cari, tetapi tidak dapat menemukannya. Terima kasih.
davs
6
Maaf dan Jika saya ingin mengonversi gambar ini ke file, tanpa mendapatkan jalur sebenarnya bagaimana melakukannya?
Chlebta
6
Jalur fisik memberikan akses ke nama file dan ekstensi. Dalam kasus unggahan file.
Clocker
195

Inilah yang saya lakukan:

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

dan:

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

CATATAN: managedQuery()metode tidak digunakan lagi, jadi saya tidak menggunakannya.

Edit terakhir: Peningkatan. Kita harus menutup kursor !!

cesards
sumber
1
stackoverflow.com/a/7265235/375093 Ini adalah opsi lain, tetapi disarankan lebih baik daripada di atas. Lihat ini juga
Sundeep
6
Hai @ m3n0R, Di Moto G, kolom MediaStore.Images.ImageColumns.DATA tidak ada sama sekali. Bagaimana cara mendapatkan gambar tanpa kolom ini?
seema
16
KESALAHAN Pastikan Kursor diinisialisasi dengan benar sebelum mengakses data darinya .. memeriksa API 19
Mayur R. Amipara
1
@ReneJuuse: Sumber daya yang luar biasa. Saya akhirnya berhasil menyelesaikan masalah ini berkat itu - saya tidak menyadari ada begitu banyak perubahan sejak awal Android. Saya menjalankan API 21 dan ketika saya menggunakan implementasi API 19 yang ditunjukkan di situs yang Anda tautkan, akhirnya berhasil.
Milos Ivanovic
2
Tidak dapat membaca baris 0, kolom -1 dari CursorWindow. Pastikan Kursor diinisialisasi dengan benar sebelum mengakses data darinya.
Maveň ツ
18

@Rene Juuse - di atas dalam komentar ... Terima kasih untuk tautan ini!

. kode untuk mendapatkan jalur sebenarnya sedikit berbeda dari satu SDK ke lainnya jadi di bawah ini kami memiliki tiga metode yang menangani SDK yang berbeda.

getRealPathFromURI_API19 (): mengembalikan jalur nyata untuk API 19 (atau lebih tinggi tetapi tidak diuji) getRealPathFromURI_API11to18 (): mengembalikan jalur nyata untuk API 11 ke API 18 getRealPathFromURI_below11 (): mengembalikan jalur nyata untuk API di bawah 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/


UPDATE 2016 Maret

Untuk memperbaiki semua masalah dengan jalur gambar saya mencoba membuat galeri khusus sebagai facebook dan aplikasi lain. Ini karena Anda hanya dapat menggunakan file lokal (file nyata, bukan virtual atau sementara), saya menyelesaikan semua masalah dengan perpustakaan ini.

https://github.com/nohana/Laevatein (perpustakaan ini untuk mengambil foto dari kamera atau memilih dari galeri, jika Anda memilih dari galeri dia memiliki laci dengan album dan hanya menunjukkan file lokal)

luizfelipetx.dll
sumber
@Clocker pada Samsung S4 juga tidak
Ricardo
Saya sangat sulit untuk mengelola semua jenis gambar sumber di android. Jika Anda mengunggah, atau memilih dari galery, solusi terbaik adalah buat sebagai galery dari facebook. Ini adalah galeri khusus dengan hanya gambar nyata di perangkat, tanpa virtual atau sementara. Saya memperbaiki semua masalah di aplikasi saya menggunakan perpustakaan ini. github.com/nohana/Laevatein Perpustakaannya sangat bagus. Untuk menyesuaikan itu tidak sederhana, tetapi Anda dapat membuka kode dan membuat perubahan Anda. Saya harap ini dapat membantu Anda.
luizfelipetx
Rusak pada Samsung S2 saya dengan 4.4.1
Oliver Dixon
Saya perlu mendapatkan file seperti pdf atau doc, saya tidak bisa mendapatkan jalurnya. Bisakah kamu membantuku?
Anish Kumar
1
Hebat! Akhirnya sesuatu yang benar-benar berhasil. Sudah lama mencari ini. Terima kasih.
Javatar
14

Catatan Ini adalah peningkatan dalam jawaban @ user3516549 dan saya telah memeriksanya di Moto G3 dengan Android 6.0.1
Saya mengalami masalah ini, jadi saya telah mencoba jawaban @ user3516549 tetapi dalam beberapa kasus tidak berfungsi dengan baik. Saya telah menemukan bahwa di Android 6.0 (atau lebih tinggi) ketika kita memulai maksud pengambilan gambar galeri maka layar akan terbuka yang menunjukkan gambar terbaru ketika pengguna memilih gambar dari daftar ini kita akan mendapatkan uri sebagai

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

sedangkan jika pengguna memilih galeri dari laci geser bukan yang terbaru maka kita akan mendapatkan uri sebagai

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

Jadi saya harus menanganinya 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: jika Anda mencoba untuk mendapatkan jalur gambar file di sdcard eksternal dalam versi yang lebih tinggi kemudian periksa pertanyaan saya

Jaiprakash Soni
sumber
Hai Sobat, ya itu benar. tetapi ini terjadi karena sekarang google memiliki format default untuk mengunggah semua foto dari ponsel Anda ke google docs. Dan simpan saja jempol di ponsel Anda. Jika Anda mendapatkan uri ini dari google docs, Anda perlu mendownload fotonya sebelum Anda menggunakan ini. Ini tidak bagus secara umum. Jadi, Untuk memperbaiki semua masalah di sini, sekarang saya menggunakan perpustakaan ini. (pustaka ini hanya menggunakan file lokal, dan dengan solusi ini masalah Anda akan terpecahkan), atau Anda dapat mengekstrak kode dari pustaka dan meningkatkan diri Anda untuk mengatasi masalah Anda. github.com/nohana/Laevatein Saya harap ini dapat membantu Anda.
luizfelipetx
1+, Pekerjaannya sempurna untuk saya. Seperti yang dikatakan @JaiprakasSoni dalam jawabannya bahwa saya menghadapi masalah yang sama ketika menjalankan aplikasi saya di permainan Moto G4 tetapi ketika saya menggunakan kode di atas, itu berfungsi dengan baik untuk saya. Terimakasih. Anda menghemat waktu saya
Shailesh
6

EDIT: Gunakan Solusi ini di sini: https://stackoverflow.com/a/20559175/2033223 Bekerja sempurna!

Pertama, terima kasih atas solusi Anda @luizfelipetx

Saya mengubah solusi Anda sedikit. Ini bekerja untuk saya:

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

Catatan: Jadi kami mendapat dokumen dan gambar, tergantung, apakah gambar itu berasal dari 'terbaru', 'galeri' atau apa pun. Jadi saya mengekstrak ID gambar terlebih dahulu sebelum mencarinya.

Javatar
sumber
1

Hai, ini kode lengkap saya untuk mengambil gambar dari kamera atau galeri

// Deklarasi variabel saya

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

// metode tubuh

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

// Dan hal lainnya

@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);
}
Tanmay Sahoo
sumber
Bagaimana Anda tahu adalah 100 di baris ini options.inSampleSize = calculateInSampleSize(options, 100, 100);
John Joe