Android bekommt echten Weg von Uri.getPath ()

107

Ich versuche, ein Bild aus der Galerie zu bekommen.

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

Nachdem ich von dieser Aktivität zurückgekehrt bin, habe ich Daten, die Uri enthalten. Es sieht aus wie:

content://media/external/images/1

Wie kann ich diesen Pfad in einen echten umwandeln (genau wie ' /sdcard/image.png')?

Vielen Dank

Davs
quelle
1
Dies ist offensichtlich ein sehr später Kommentar, aber ich wollte nur darauf hinweisen, dass die Methode startActivityForResultCode einen Anforderungscode als Argument und keinen Ergebniscode verwendet.
Tianxiang Xiong
hat uri.getPath()dir keinen wirklichen Weg gegeben?
Darpan
#Versuchen Sie dies trotzdem, wenn Sie das Problem haben, den richtigen Weg zu finden, können Sie meine Antworten ausprobieren. Die obigen Antworten haben mir nicht geholfen. Erläuterung : - Diese Methode ruft den URI ab und überprüft anschließend die API-Ebene Ihres Android-Geräts. Je nach API-Ebene wird der Real-Pfad generiert. Der Code zum Generieren eines realen Pfads unterscheidet sich je nach API-Ebene. Hier ist meine Antwort
Sunil

Antworten:

56

Ist es wirklich notwendig, dass Sie einen physischen Weg finden?
Zum Beispiel ImageView.setImageURI()und ContentResolver.openInputStream()ermöglichen Ihnen den Zugriff auf den Inhalt einer Datei, ohne den tatsächlichen Pfad zu kennen.

Molnarm
quelle
Es ist genau das, wonach ich gesucht, aber nicht gefunden habe. Vielen Dank.
Davs
6
Entschuldigung und wenn ich dieses Bild in eine Datei konvertieren möchte, ohne den richtigen Pfad zu finden, wie es geht?
Chlebta
6
Der physische Pfad ermöglicht den Zugriff auf den Dateinamen und die Erweiterung. Bei Datei-Uploads.
Clocker
195

Das ist was ich mache:

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

und:

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

HINWEIS: Die managedQuery()Methode ist veraltet, daher verwende ich sie nicht.

Letzte Änderung: Verbesserung. Wir sollten den Cursor schließen !!

cesards
quelle
1
stackoverflow.com/a/7265235/375093 Dies ist eine weitere Option, die jedoch als besser als oben vorgeschlagen wird. Schauen Sie sich das auch an
Sundeep
6
Hi @ m3n0R, In Moto G ist die Spalte MediaStore.Images.ImageColumns.DATA überhaupt nicht vorhanden. Wie bekomme ich ein Bild ohne diese Spalte?
scheinen
15
ERROR Sicherstellen , dass die Cursor initialisiert korrekt , bevor Daten darauf zugreifen .. in API Prüfung 19
Mayur R. Amipara
1
@ RenJuuse: Ausgezeichnete Ressource. Dank dessen konnte ich dieses Problem endlich beheben - ich wusste nicht, dass es seit der Einführung von Android so viele Änderungen gab. Ich habe API 21 ausgeführt und als ich die API 19-Implementierung verwendet habe, die auf der von Ihnen verlinkten Site angezeigt wird, hat es endlich funktioniert.
Milos Ivanovic
1
Zeile 0, Spalte -1 konnte nicht aus CursorWindow gelesen werden. Stellen Sie sicher, dass der Cursor korrekt initialisiert ist, bevor Sie auf Daten von ihm zugreifen.
Maveň
18

@ Ren Juuse - oben in den Kommentaren ... Danke für diesen Link!

. Der Code zum Abrufen des tatsächlichen Pfads unterscheidet sich von SDK zu SDK. Im Folgenden finden Sie drei Methoden, die sich mit verschiedenen SDKs befassen.

getRealPathFromURI_API19 (): Gibt den realen Pfad für API 19 zurück (oder höher, aber nicht getestet). getRealPathFromURI_API11to18 (): Gibt den realen Pfad für API 11 zu API 18 zurück. getRealPathFromURI_below11 (): Gibt den realen Pfad für API unter 11 zurück

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

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


UPDATE 2016 März

Um alle Probleme mit dem Pfad der Bilder zu beheben, versuche ich, eine benutzerdefinierte Galerie als Facebook und andere Apps zu erstellen. Dies liegt daran, dass Sie nur lokale Dateien verwenden können (reale Dateien, nicht virtuelle oder temporäre). Ich löse alle Probleme mit dieser Bibliothek.

https://github.com/nohana/Laevatein (Diese Bibliothek dient zum Aufnehmen von Fotos von der Kamera oder zum Auswählen aus der Galerie. Wenn Sie aus der Galerie auswählen, hat er eine Schublade mit Alben und zeigt nur lokale Dateien an.)

luizfelipetx
quelle
@Clocker auf Samsung S4 auch nicht
Ricardo
Ich bin wirklich schwer, alle Arten von Quellbildern in Android zu verwalten. Wenn Sie eine Galerie hochladen oder eine Auswahl treffen, ist die beste Lösung, eine Galerie von Facebook zu erstellen. Es ist eine benutzerdefinierte Galerie mit nur realen Bildern im Gerät, keine virtuellen oder temporären. Ich behebe alle Probleme in meiner App mit dieser Bibliothek. github.com/nohana/Laevatein Es ist eine wirklich gute Bibliothek. Das Anpassen ist nicht einfach, aber Sie können Code öffnen und Ihre Änderungen vornehmen. Ich hoffe das kann dir helfen.
Luizfelipetx
Auf meinem Samsung S2 mit 4.4.1 gebrochen
Oliver Dixon
Ich brauche die Dateien wie PDF oder Doc, ich kann den Pfad nicht bekommen. Kannst du mir bitte helfen?
Anish Kumar
1
Genial! Endlich etwas, das wirklich funktioniert. Ich habe lange danach gesucht. Vielen Dank.
Javatar
14

Hinweis Dies ist eine Verbesserung der Antwort von @ user3516549 und ich habe sie auf Moto G3 mit Android 6.0.1 überprüft.
Ich habe dieses Problem, daher habe ich versucht, die Antwort von @ user3516549 zu beantworten, aber in einigen Fällen funktionierte sie nicht richtig. Ich habe festgestellt, dass in Android 6.0 (oder höher), wenn wir mit der Auswahl von Galeriebildern beginnen, ein Bildschirm geöffnet wird, auf dem die neuesten Bilder angezeigt werden, wenn der Benutzer ein Bild aus dieser Liste auswählt

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

Wenn der Benutzer eine Galerie aus der Schiebeschublade anstelle der aktuellen auswählt, erhalten wir uri as

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

Also habe ich es geschafft 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)
        }

    }

BEARBEITEN: Wenn Sie versuchen, den Bildpfad der Datei auf einer externen SD-Karte in einer höheren Version abzurufen, überprüfen Sie meine Frage

Jaiprakash Soni
quelle
Hallo Freund, ja das stimmt. Dies geschieht jedoch, da Google jetzt ein Standardformat zum Hochladen aller Fotos von Ihrem Telefon in Google Docs hat. Und speichern Sie einfach das Daumenzeichen in Ihrem Telefon. Wenn Sie diese URL von Google Docs erhalten, müssen Sie das Foto herunterladen, bevor Sie es verwenden. Das ist im Allgemeinen nicht gut. Um alle Probleme hier zu beheben, benutze ich jetzt diese Bibliothek. (Diese Bibliothek verwendet nur lokale Dateien, und mit dieser Lösung werden Ihre Probleme gelöst.) Oder Sie können den Code aus der Bibliothek extrahieren und sich verbessern, um Ihr Problem zu lösen. github.com/nohana/Laevatein Ich hoffe, das kann Ihnen helfen.
Luizfelipetx
1+, seine Arbeit ist perfekt für mich. Wie @JaiprakasSoni in seiner Antwort sagte, dass ich das gleiche Problem hatte, als ich meine App in Moto G4 Play ausführte, aber wenn ich den obigen Code verwende, funktioniert es gut für mich. Danke. Sie sparen meine Zeit
Shailesh
6

BEARBEITEN: Verwenden Sie diese Lösung hier: https://stackoverflow.com/a/20559175/2033223 Funktioniert perfekt!

Zunächst einmal vielen Dank für Ihre Lösung @luizfelipetx

Ich habe deine Lösung ein wenig geändert. Das funktioniert bei mir:

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

Hinweis: Wir haben also Dokumente und Bilder erhalten, je nachdem, ob das Bild aus "Neuheiten", "Galerie" oder was auch immer stammt. Also extrahiere ich zuerst die Bild-ID, bevor ich sie nachschlage.

Javatar
quelle
1

Hii hier ist mein vollständiger Code zum Aufnehmen von Bildern von einer Kamera oder einem Sturm

// Meine Variablendeklaration

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

// Methodenkörper

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

// Und der Rest der Dinge

@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
quelle
Wie Sie wissen, ist 100 in dieser Zeile options.inSampleSize = calculateInSampleSize(options, 100, 100);
John Joe