Image uri no muestra imágenes en ImageView en algún dispositivo Android

Tengo un ImageView. Al hacer clic en un ImageView, se abrirá la galería y recoger una imagen y mostrarla en ImageView. Tengo una condición de que cuando cierre mi aplicación y luego la abra, la imagen se mantendrá allí. Así que para eso, estoy almacenando la imagen Uri en sharedprefrence. Y al abrir la aplicación estoy recuperando el mismo Uri e intento mostrar la imagen en imageView.

Sin embargo, en algunos teléfonos, la imagen parece perfecta como Mi (Lollipop), Samsung (KitKat) pero no aparece en teléfonos como – Motorola (Marshmallow), One Plus One (Marshmallow). ¿Alguna idea de por qué está sucediendo? Aquí está mi código

Para recoger una imagen que estoy usando

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

Y en OnActivityResult () el código es

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

Y mientras recuperaba de sharedprefrence, convertía String en uri usando Uri.parse(profile_image)

Sin embargo, si me doy cuenta, uri devuelve para diferentes teléfonos Android es la siguiente

 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 

Por lo tanto, cuando el contenido de uri es -content: // media / external / images / media / es la imagen de visualización en ImageView Perfect y en otros casos no es

Prueba esto

Desarrollé y tested y trabajé en

  1. Nota de Lenovo K3 (melcocha)
  2. Motorola (Lollipop)
  3. Samsung (KitKat)

En su MainActivity.java agregar

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

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

En su archivo Manifest agregar permission

 <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" /> 

Nota:

Assuming que ha agregado código para take permission para Marshmallow

Resultado Uri

Lenovo K3 Nota: 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

Citando desde 4.4 Visión general del API :

'En versiones anteriores de Android, si desea que su aplicación recupere un tipo específico de archivo desde otra aplicación, debe invocar una intención con la acción ACTION_GET_CONTENT . Esta acción sigue siendo la forma adecuada de solicitar un archivo que desea importar a su aplicación. Sin embargo, Android 4.4 introduce la acción ACTION_OPEN_DOCUMENT , que permite al usuario seleccionar un archivo de un tipo específico y conceder a su aplicación acceso de lectura a largo plazo a ese archivo (posiblemente con acceso de escritura) sin importar el archivo a su aplicación. adicional)

Para permitir que tu aplicación recupere imágenes previamente seleccionadas, solo cambia la acción de ACTION_GET_CONTENT a ACTION_OPEN_DOCUMENT (solución confirmada trabajando en Nexus 7 2013).

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

Creo que el problema con el uri del archivo de imagen, estoy usando una clase para obtener URI exacta, y está probado y trabajando en todas las versiones.

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

Use getPath para encontrar la ruta exacta de un archivo. Es la manera más simple de manejar el problema como usted ha definido. Por favor, intente y hágamelo saber si necesita más ayuda 🙂

Pasa tu URI en este método devolverá una String y lo convertirá en Bitmap

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

Necesita solicitar el permiso para leer el almacenamiento externo al usuario en tiempo de ejecución para Android 6+

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

Espero que esto ayude.

Tal vez usted puede manejarlo mediante la conversión de URI a la ruta real en primer lugar.

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

Y su onActivityResult debería tener este aspecto

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

He conseguido hacer esto en el pasado. En lugar de almacenarlo en SharePreferences, lo guardo en el Bundle cuando onSaveInstanceState (Bundle) es llamado por: bundle.putParcelable (SOME_KEY, uri). Usted puede hacer esto porque Uri implementa Parcelable. Después de eso, compruebe para este uri en el paquete pasado en onCreate (). Código:

 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: Supongo que el problema de almacenar el uri en SharePreference es la codificación / descodificación Uri.

Usted puede fácilmente convertir URI a Bitmap:

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

Y luego establecer en Imageview: imgview.setImageBitmap (imagen);

Espero que esto te ayudará.

Podría ser un problema con versiones de Picasso. Se arreglaron algo con la carga de imágenes grandes en la versión 2.5.0 (2.4.0 …?), Que no está disponible a través de los repositorios todavía.

Tendrás que incluir manualmente la instantánea nocturna de Picasso, y eso probablemente arreglará tu problema. Lo hizo por mí.

También me encuentro con algo como esto antes y encontré una útil clase de ayuda que le da la ubicación exacta del archivo. Aquí está el enlace .

Puede utilizar los métodos como FileUtils.getPath (contexto, uri) o FileUtils.getFile (contexto, uri) para obtener el archivo. Luego, úsalo de la siguiente manera:

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

Espero que esto ayude.

No estoy 100% seguro si tengo la pregunta. Si ciertas imágenes no se pueden mostrar en el imageView (incluso antes de cerrar y reiniciar la aplicación) entonces el problema es con Picasso es ser capaz de manejar el contenido de ciertos proveedores. No estoy teniendo la sensación de que este es el caso, pero si lo es, entonces es posible que desee considerar la presentación de un bug / RFE para esa biblioteca. Por otro lado, si Picasso está mostrando correctamente la imagen de un Uri dado, pero no después de la conversión Uri_org -> String -> Uri_regen entonces significa que Uri_org no es lo mismo que Uri_regen. Usted puede (temporalmente) agregar un par de líneas de su código para convertir la cadena de nuevo a Uri y poner un punto de interrupción justo después y comparar los dos Uri. Eso debería darle una idea de cómo las cosas van mal.

 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 

Si no está pulsando el punto de interrupción, mueva el punto de interrupción de nuevo a la instrucción "if" y visualice los dos Uri (que casi seguramente serán iguales, de lo contrario habría golpeado el punto de interrupción, pero esto ayudaría a comprobar la depuración Código propio). Si los Uri son los mismos, de alguna manera la preferencia String no se está conservando correctamente por alguna razón. En ese caso tome nota del Uri original y añada un punto de interrupción en la línea que convierte la Cadena de nuevo a Uri:

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

Si el experimento anterior funcionó, debería estar funcionando de nuevo aquí a menos que el profile_image sea diferente. De cualquier manera usted debe obtener indicaciones en cuanto a dónde está el problema.

¡Buena suerte!

  • Imagen de Uri a bytesarray
  • Android - Consultando el ContentProvider de SMS?
  • ¿Cómo comprobar si el recurso apuntado por Uri está disponible?
  • URI personalizado esquemas para el Facebook Messenger
  • Android Wear elimina datos de DataApi con deleteDataItems
  • ¿por qué java.net.UnknownHostException: Host no está resuelto: webservername.com:80?
  • Obtener todos los sms de un teléfono Android
  • ¿Cómo obtener la ruta del archivo desde URI?
  • No se pueden seleccionar algunas fotos de Galería en Android
  • Cómo obtener HTML5 video URI en HTML5VFullScreen $ SurfaceVideoView en Android 4.0?
  • CursorLoader, obtiene URI para la base de datos local
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.