it-swarm.com.de

Image uri zeigt auf einigen Android-Geräten keine Bilder in ImageView an

Ich habe eine ImageView. Wenn Sie auf eine ImageView klicken, wird die Galerie geöffnet, und Sie nehmen ein Bild auf und zeigen es in ImageView. Wenn ich meine App schließe und sie dann öffne, wird das Image dort beibehalten. __ Damit speichere ich das Image Uri auf sharedprefrence . Und beim Öffnen der Anwendung rufe ich dasselbe ab Uri und versucht, das Bild in imageView anzuzeigen.

Bei einigen Handys erscheint das Bild jedoch perfekt wie Mi (Lollipop), Samsung (KitKat) In Handys wie - Motorola (Marshmallow), One Plus One (Marshmallow) ... __ passiert? Hier ist mein Code

Zum Aufnehmen eines Bildes verwende ich 

Intent intent=new Intent();intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent, "Select Picture"), Constants.SELECT_PICTURE);

Und OnActivityResult () Code ist 

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     super.onActivityResult(requestCode, resultCode, data);

     if(requestCode==Constants.SELECT_PICTURE && resultCode==RESULT_OK && null!=data) {
         Uri uri=data.getData();
         Picasso.with(UsersProfileActivity.this)
             .load(uri)
             .centerCrop()
             .resize(200,200)
             .into(img_photo);

         // This profile image i am storing into a sharedpreference        
         profile_image=uri.toString();
     }

Beim Abrufen von sharedprefrence konvertiere ich String mit Uri.parse(profile_image) in uri.

Wenn ich jedoch bemerke, kehrt der uri für verschiedene Android-Handys wie folgt zurück

Mi(Lollipop)- Uri=content://media/external/images/media/12415
samsung(KitKat)-Uri=content://media/external/images/media/786
Motorola(Marshmallow)- Uri=content://com.Android.providers.media.documents/document/image%3A30731
One Plus One (Marshmallow)- Uri=content://com.Android.providers.media.documents/document/image%3A475

Wenn der Uri-Inhalt -inhalt ist: // media/external/images/media/wird Bild auf ImageView Perfect angezeigt und in anderen Fällen nicht

14
abh22ishek

Versuche dies

Ich entwickelte und tested und arbeite an  

  1. Lenovo K3 Note (Marshmallow) 
  2. Motorola (Lutscher)
  3. Samsung (KitKat)

In Ihrem MainActivity.Java hinzufügen

    profilePicture = (ImageView)findViewById(R.id.imgProfilePicture);
    sharedPreferences = getSharedPreferences(getString(R.string.app_name)+"_ProfileDetails",MODE_PRIVATE);

    // get uri from shared preference
    String profilePicUri = sharedPreferences.getString("profilePicUrl","");

    // if uri not found
    if (profilePicUri.equalsIgnoreCase("")){
        // code for open gallery to select image
        Intent intent;
        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat){
            intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
            intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
            intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
        }else{
            intent = new Intent(Intent.ACTION_GET_CONTENT);
        }
        intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
        intent.setType("image/*");

        startActivityForResult(Intent.createChooser(intent, "Select Picture"), SELECT_PICTURE_CONSTANT);
    }else{
        try{
            final int takeFlags =  (Intent.FLAG_GRANT_READ_URI_PERMISSION
                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            // Check for the freshest data.
            getContentResolver().takePersistableUriPermission(Uri.parse(profilePicUri), takeFlags);
            // convert uri to bitmap
            Bitmap bitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.parse(profilePicUri));
            // set bitmap to imageview
            profilePicture.setImageBitmap(bitmap);
        }
        catch (Exception e){
            //handle exception
            e.printStackTrace();
        }
    }

Now Handle onActivityResult.

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == SELECT_PICTURE_CONSTANT && resultCode == RESULT_OK && null != data) {
        Uri uri = data.getData();
        // This profile image i am storing into a sharedpreference
        SharedPreferences.Editor editor = sharedPreferences.edit();
        // save uri to shared preference
        editor.putString("profilePicUrl",uri.toString());
        editor.commit();
        profilePicture.setImageURI(uri);
    }
}

Fügen Sie in Ihrer Manifest-Datei permission hinzu.

<uses-permission Android:name="Android.permission.MANAGE_DOCUMENTS"/>
<uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission Android:name="Android.permission.READ_EXTERNAL_STORAGE" />

Hinweis:  

Assuming Sie haben Code für take permission für Marshmallow hinzugefügt.

Ergebnis Uri 

lenovo K3 Hinweis: content://com.Android.externalstorage.documents/document/primary%3ADCIM%2FCamera%2FIMG_20160606_212815.jpg

samsung: content://com.Android.providers.media.documents/document/image%3A2086

Motorola: content://com.Android.providers.media.documents/document/image%3A15828

12
Pramod Waghmare

Ich denke, das Problem mit dem URI der Image-Datei, ich benutze eine Klasse, um genaue URIs zu erhalten, und es wurde getestet und funktioniert mit allen Versionen.

package fandooo.com.fandooo.util;

import Android.content.ContentUris;
import Android.content.Context;
import Android.database.Cursor;
import Android.net.Uri;
import Android.os.Build;
import Android.os.Environment;
import Android.provider.DocumentsContract;
import Android.provider.MediaStore;

public class ImageFilePath {

    /**
     * Method for return file path of Gallery image
     * 
     * @param context
     * @param uri
     * @return path of the selected image file from gallery
     */
    public static String getPath(final Context context, final Uri uri) {

        // check here to KitKat or new version
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {

            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/"
                            + split[1];
                }
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"),
                        Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] { split[1] };

                return getDataColumn(context, contentUri, selection,
                        selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     * 
     * @param context
     *            The context.
     * @param uri
     *            The Uri to query.
     * @param selection
     *            (Optional) Filter used in the query.
     * @param selectionArgs
     *            (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri,
                                       String selection, String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = { column };

        try {
            cursor = context.getContentResolver().query(uri, projection,
                    selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.Android.externalstorage.documents".equals(uri
                .getAuthority());
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.Android.providers.downloads.documents".equals(uri
                .getAuthority());
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.Android.providers.media.documents".equals(uri
                .getAuthority());
    }

    /**
     * @param uri
     *            The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.Android.apps.photos.content".equals(uri
                .getAuthority());
    }
}

Verwenden Sie getPath, um den genauen Pfad einer Datei zu ermitteln. Es ist die einfachste Art, das von Ihnen definierte Problem zu behandeln. Bitte versuchen Sie es und lassen Sie mich wissen, wenn Sie weitere Hilfe benötigen :)

3
Neo

Zitieren aus 4.4 API-Übersicht :

'Wenn Sie in früheren Versionen von Android einen bestimmten Dateityp von einer anderen App abrufen möchten, muss er eine Absicht mit der Aktion ACTION_GET_CONTENT aufrufen. Diese Aktion ist immer noch die geeignete Methode, um eine Datei anzufordern, die Sie import in Ihre App importieren möchten. Android 4.4 führt jedoch die Aktion ACTION_OPEN_DOCUMENT ein, mit der der Benutzer eine Datei eines bestimmten Typs auswählen kann, und Ermöglichen Sie Ihrer App langfristigen Lesezugriff auf diese Datei ( möglicherweise mit Schreibzugriff), ohne die Datei in Ihre App zu importieren. "(Hervorhebung hinzugefügt)

Um Ihrer App das Abrufen zuvor ausgewählter Bilder zu ermöglichen, ändern Sie einfach die Aktion von ACTION_GET_CONTENT in ACTION_OPEN_DOCUMENT (Lösung bestätigt, dass sie auf Nexus 7 2013 funktioniert).

    Intent intent = new Intent();
    intent.setType("image/*");
    String action = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat ? Intent.ACTION_OPEN_DOCUMENT : Intent.ACTION_GET_CONTENT;
    intent.setAction(action);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), Constants.SELECT_PICTURE);
2
Kai

Übergeben Sie Ihre URI in dieser Methode, wird ein String zurückgegeben und dann in Bitmap umgewandelt

  String path = getPath(getApplicationContext(), uri);
  Bitmap bitmap = BitmapFactory.decodeFile(path);
  imageView.setImageBitmap(bitmap);





 public static String getPath(final Context context, final Uri uri) {

    // DocumentProvider
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KitKat && DocumentsContract.isDocumentUri(context, uri)) {

        if (isExternalStorageDocument(uri)) {// ExternalStorageProvider
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];
            String storageDefinition;


            if ("primary".equalsIgnoreCase(type)) {

                return Environment.getExternalStorageDirectory() + "/" + split[1];

            } else {

                if (Environment.isExternalStorageRemovable()) {
                    storageDefinition = "EXTERNAL_STORAGE";

                } else {
                    storageDefinition = "SECONDARY_STORAGE";
                }

                return System.getenv(storageDefinition) + "/" + split[1];
            }

        } else if (isDownloadsDocument(uri)) {// DownloadsProvider

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);

        } else if (isMediaDocument(uri)) {// MediaProvider
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            Uri contentUri = null;
            if ("image".equals(type)) {
                contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
            } else if ("video".equals(type)) {
                contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
            } else if ("audio".equals(type)) {
                contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
            }

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]{
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }

    } else if ("content".equalsIgnoreCase(uri.getScheme())) {// MediaStore (and general)

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);

    } else if ("file".equalsIgnoreCase(uri.getScheme())) {// File
        return uri.getPath();
    }

    return null;
}
1
Tanveer Bulsari

Ich bin auch schon auf so etwas gestoßen und habe eine nützliche Helper-Klasse gefunden, die Ihnen den genauen Speicherort der Datei angibt. Hier ist der Link .

Sie können die Methoden wie FileUtils.getPath (context, uri) oder FileUtils.getFile (context, uri) verwenden, um die Datei abzurufen. Dann benutze es einfach so:

 Picasso.with(UsersProfileActivity.this)
         .load(Uri.fromFile(file))
         .centerCrop()
         .resize(200,200)
         .into(img_photo);

Hoffe das hilft.

0
Siddharth jain

Nur nicht 100% sicher, ob ich die Frage bekomme. Wenn bestimmte Bilder nicht in der ImageView angezeigt werden können (auch bevor die App geschlossen und neu gestartet wird), besteht das Problem darin, dass Picasso die Inhalte bestimmter Anbieter verarbeiten kann. Ich habe nicht das Gefühl, dass dies der Fall ist, aber wenn dies der Fall ist, sollten Sie in Betracht ziehen, einen Fehler/RFE für diese Bibliothek einzureichen. Wenn Picasso hingegen das Bild für einen bestimmten Uri korrekt anzeigt, jedoch nicht nach der Konvertierung von Uri_org -> String -> Uri_regen, bedeutet dies, dass Uri_org nicht mit Uri_regen identisch ist. Sie können (vorübergehend) ein paar Zeilen Ihren Code hinzufügen, um den String zurück in Uri zu konvertieren und einen Haltepunkt direkt danach zu setzen und die beiden Uris zu vergleichen. Das sollte Ihnen einen Hinweis geben, wie die Dinge schief laufen.

profile_image=uri.toString();
//add the next few lines for debugging purposes only; remove them later
Uri uri2 = Uri.parse(profile_image)
if (!uri.equals(uri2)
   //add a breakpoint on the next line
   Log.d("Uri mismatch), "Ouch");
//remove the lines after you are done with debugging

Wenn Sie den Haltepunkt nicht erreichen, verschieben Sie den Haltepunkt zurück zur "if" -Anweisung und prüfen Sie visuell die beiden Uris (was fast sicher die gleichen sein wird, da Sie sonst den Haltepunkt erreicht hätten. Dies würde jedoch helfen, den Debug zu überprüfen Code selbst). Wenn die Uri gleich sind, wird die String-Einstellung aus irgendeinem Grund nicht korrekt beibehalten. Notieren Sie sich in diesem Fall den ursprünglichen Uri und fügen Sie in der Zeile, die den String zurück in Uri konvertiert, einen Haltepunkt hinzu:

Uri uri = Uri.parse(profile_image) //profile_image is retrieved from sharedpreferences

Wenn das vorherige Experiment funktioniert hat, sollte es hier wieder funktionieren, sofern das Profil nicht anders ist. So oder so sollten Sie Hinweise bekommen, wo das Problem liegt.

Viel Glück!

0
Kaamel

Vielleicht können Sie damit umgehen, indem Sie zuerst den URI in einen echten Pfad konvertieren.

public String getRealPathFromURI(Context context, Uri contentUri) {
    Cursor cursor = null;
    try {
        String[] proj = { MediaStore.Images.Media.DATA };
        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);
    } finally {
        if (cursor != null) {
            cursor.close();
        }
    }
}

Und Ihr onActivityResult sollte so aussehen

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    if(requestCode==Constants.SELECT_PICTURE && resultCode==RESULT_OK && null!=data)
    {
        Uri uri=data.getData();
        String imagePath = getRealPathFromURI(getApplicationContext(), uril); 
Picasso.with(UsersProfileActivity.this).load(imagePath).centerCrop().resize(200,200).into(img_photo);

     profile_image = imagePath;  

    }
0
ikhsan

Könnte ein Problem bei der Versionierung von Picasso sein. Es wurde ein Problem mit dem Laden großer Bilder in Version 2.5.0 (2.4.0 ...?) Behoben, das noch nicht über die Repositorys verfügbar ist.

Sie müssen den nächtlichen Schnappschuss von Picasso manuell einschließen, wodurch das Problem wahrscheinlich behoben wird. Es hat für mich getan.

0
Marc DiMillo

Sie können leicht URI in Bitmap konvertieren:

ParcelFileDescriptor parcelFileDescriptor =
                context.getContentResolver().openFileDescriptor(selectedFileUri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);


        parcelFileDescriptor.close();

Stellen Sie dann Imageview ein: imgview.setImageBitmap (image);

Hoffe, das wird dir helfen.

0

Sie müssen die Berechtigung zum Lesen des externen Speichers für Benutzer zur Laufzeit für Android 6+ anfordern

https://developer.Android.com/training/permissions/requesting.html#perm-check

Hoffe das hilft.

0
Vlad

Das ist mir in der Vergangenheit gelungen. Anstatt es in SharePreferences zu speichern, speichere ich es im Bundle, wenn onSaveInstanceState (Bundle) von: bundle.putParcelable (SOME_KEY, uri) aufgerufen wird. Sie können dies tun, weil Uri Parcelable implementiert. Überprüfen Sie anschließend nach diesem URI in dem in onCreate () übergebenen Bundle. Code: 

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    if (savedInstanceState != null){
        loadImage((Uri)saveInstanceState.getParcelable(SOME_KEY))
    }
}

public void onSaveInstanceState(Bundle bundle){
     bundle.putParcelable(SOME_KEY, uri)
}

P/S: Ich denke, das Problem des Speicherns des uri in SharePreference ist das Kodieren/Dekodieren von Uri.

0
Tin Tran