ver una sacar quitar para metadatos informacion imagen fotos eliminar editar edicion datos borrar app android android-intent uri exif android-contentresolver

android - sacar - Una respuesta final sobre cómo obtener datos Exif del URI



quitar edicion de una imagen android (3)

Lo siguiente funciona con todas las aplicaciones que he probado, en cualquier caso:

Eso solo funcionará si el Uri resulta ser algo que viene de MediaStore . Fallará si el Uri resulta venir de cualquier otra cosa.

La respuesta inmediata es No, no encuentra rutas de archivos de contenido uris en la versión más reciente del sistema operativo. Podría decirse que no todos los contenidos urinarios apuntan a imágenes o incluso a archivos.

Correcto. Lo he señalado en muchas ocasiones, como here .

¿Cómo se supone que usemos la clase ExifInterface si no debemos usar paths?

Tu no Use otro código para obtener los encabezados EXIF.

Es posible que existan bibliotecas externas que lean material Exif de una transmisión, pero me pregunto cuál es la forma común / de plataforma para resolverlo.

Use bibliotecas externas.

He buscado un código similar en las aplicaciones de código abierto de Google, pero no encontré nada.

Encontrará algunos en la aplicación Mms .

Este tema se ha discutido en muchas preguntas aquí, con resultados principalmente diferentes y, debido a cambios de API y diferentes tipos de URI, no hay una respuesta definitiva .

No tengo una respuesta, pero hablemos de eso. ExifInterface tiene un único constructor que acepta un filePath . Eso en sí mismo es molesto, ya que ahora se desaconseja confiar en las rutas, debería usar Uri s y ContentResolver . DE ACUERDO.

Nuestro uri llamado uri puede recuperarse de la intención en onActivityResult (si selecciona la imagen de la galería con ACTION_GET_CONTENT ) o puede ser un Uri que teníamos anteriormente (si selecciona la imagen de la cámara y llama a intent.putExtra(MediaStore.EXTRA_OUTPUT, uri) ).

API <19

Nuestro uri puede tener dos esquemas diferentes:

  • Uris procedente de cámaras tendrá principalmente un file:// esquema. Esos son bastante fáciles de tratar, porque mantienen el camino. Puede llamar al new ExifInterface(uri.getPath()) y listo.
  • Uris proveniente de la galería u otros proveedores de contenido generalmente tienen una interfaz de content:// . Personalmente no sé de qué se trata, pero me está volviendo loco.

Este segundo caso, por lo que yo entiendo, debe tratarse con un ContentResolver que puede obtener con Context.getContentResolver() . Lo siguiente funciona con todas las aplicaciones que he probado, en cualquier caso:

public static ExifInterface getPictureData(Context context, Uri uri) { String[] uriParts = uri.toString().split(":"); String path = null; if (uriParts[0].equals("content")) { // we can use ContentResolver. // let’s query the DATA column which holds the path String col = MediaStore.Images.ImageColumns.DATA; Cursor c = context.getContentResolver().query(uri, new String[]{col}, null, null, null); if (c != null && c.moveToFirst()) { path = c.getString(c.getColumnIndex(col)); c.close(); return new ExifInterface(path); } } else if (uriParts[0].equals("file")) { // it''s easy to get the path path = uri.getEncodedPath(); return new ExifInterface(path); } return null; }

API19 +

Mis problemas surgen de Kitkat en adelante con content:// URI. Kitkat presenta el Storage Access Framework (ver here ) junto con un nuevo intento, ACTION_OPEN_DOCUMENT y un selector de plataforma. Sin embargo, se dice que

En Android 4.4 y versiones posteriores, tiene la opción adicional de utilizar el ACTION_OPEN_DOCUMENT intento, que muestra una interfaz de usuario del selector controlada por el sistema que permite al usuario explorar todos los archivos que otras aplicaciones han puesto a disposición. Desde esta única interfaz de usuario, el usuario puede elegir un archivo de cualquiera de las aplicaciones compatibles.

ACTION_OPEN_DOCUMENT no está destinado a reemplazar a ACTION_GET_CONTENT. El que debe usar depende de las necesidades de su aplicación.

Entonces, para mantener esto muy simple, digamos que estamos de acuerdo con el antiguo ACTION_GET_CONTENT : activará un cuadro de diálogo de selección donde puede elegir una aplicación de galería.

Sin embargo, el enfoque de contenido ya no funciona. A veces funciona en Kitkat, pero nunca funciona en Lollipop, por ejemplo. No sé exactamente qué ha cambiado.

He buscado y probado mucho; Otro enfoque adoptado específicamente para Kitkat es:

String wholeId = DocumentsContract.getDocumentId(uri); String[] parts = wholeId.split(“:”); String numberId = parts[1]; Cursor c = context.getContentResolver().query( // why external and not internal ? MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new String[]{ col }, MediaStore.Images.Media._ID + “=?”, new String[]{ numberId }, null);

Esto funciona a veces, pero otros no. Específicamente, funciona cuando wholeId es algo así como image:2839 , pero obviamente se rompe cuando wholeId es simplemente un número.

Puedes probar esto usando el selector de sistema (es decir, disparando la galería con ACTION_OPEN_DOCUMENT ): si eliges una imagen de "Recientes", funciona; si eliges una imagen de "Descargas", se rompe.

Entonces, ¿cómo?

La respuesta inmediata es No , no encuentra rutas de archivos de contenido uris en la versión más reciente del sistema operativo. Podría decirse que no todos los contenidos urinarios apuntan a imágenes o incluso a archivos.

Eso está totalmente bien para mí, y al principio trabajé para evitar esto. Pero entonces, ¿cómo se supone que debemos usar la clase ExifInterface si no deberíamos usar paths?

No entiendo cómo lo hacen las aplicaciones modernas: encontrar orientación y metadatos es un problema al que se enfrenta de inmediato, y ContentResolver no ofrece ninguna API en ese sentido. Tiene ContentResolver.openFileDescriptor() y cosas similares, pero no API para leer metadatos (que realmente está en ese archivo). Es posible que existan bibliotecas externas que lean material Exif de una transmisión, pero me pregunto cuál es la forma común / de plataforma para resolverlo.

He buscado un código similar en las aplicaciones de código abierto de Google, pero no encontré nada.



Para ampliar la respuesta de alex.dorokhov con algún código de muestra. La biblioteca de soporte es una excelente forma de hacerlo.

build.gradle

dependencies { ... compile "com.android.support:exifinterface:25.0.1" ... }

Código de ejemplo:

import android.support.media.ExifInterface; ... try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { ExifInterface exif = new ExifInterface(inputStream); int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); } catch (IOException e) { e.printStackTrace(); }

La razón por la que tuve que hacerlo de esta manera una vez que comenzamos a api 25 (tal vez un problema en 24+ también) pero aún soportando de nuevo a api 19, en Android 7 nuestra aplicación fallaría si pasaba un URI a la cámara que era solo hace referencia a un archivo. Por lo tanto, tuve que crear un URI para pasar a la intención de la cámara de esta manera.

FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", tempFile);

El problema allí es que no es posible convertir el URI en una ruta de archivo real (que no sea mantener la ruta del archivo temporal).