studio picture nougat intent example action_image_capture android android-intent camera orientation

android - picture - Resumen: tome una fotografía utilizando Camera Intent y visualice la foto con la orientación correcta(funciona con suerte en todos los dispositivos)



take photo android nougat (4)

Parece ser lo más simple del mundo: tomar una foto dentro de su aplicación Android utilizando la actividad de cámara predeterminada. Sin embargo, hay muchas dificultades que se cubren en varias publicaciones en StackOverflow y en la web, como, por ejemplo, las Intenciones nulas que se transmiten, la orientación de la imagen no es correcta o OutOfMemoryErrors.

Estoy buscando una solución que me permita

  1. iniciar la actividad de la cámara a través de la intención de la cámara,
  2. recuperar el Uri de la foto, y
  3. recuperar la orientación correcta de la foto.

Además, me gustaría evitar una implementación específica de la configuración del dispositivo (fabricante, modelo, sistema operativo) en la medida de lo posible. Entonces me pregunto: ¿cuál es la mejor manera de lograr esto?


En un Galaxy S3 con CM 10.1 obtengo una excepción nullpointer en BitmapHelper:

bm = BitmapFactory.decodeFileDescriptor (fileDescriptor.getFileDescriptor (), null, opciones);

posteriormente mi UploadPhotoActivity falla en:

try { photo = BitmapHelper.readBitmap(this, cameraPicUri); if (photo != null) { photo = BitmapHelper.shrinkBitmap(photo, 600, rotateXDegrees); thumbnail = BitmapHelper.shrinkBitmap(photo, 100); ImageView imageView = (ImageView) findViewById(R.id.sustainable_action_photo); imageView.setImageBitmap(photo); } else { Log.e(TAG,"IMAGE ERROR 1"); } } catch (Exception e) { Log.e(TAG,"IMAGE ERROR 2"); e.printStackTrace(); }

en el segundo registro (ERROR DE IMAGEN 2). Después de un par de intentos mi cámara se rompió y obtuve un "No se pudo conectar a la cámara" -error.

Lo probé en un Nexus 7 y funciona perfectamente.

Editar: Reducirlo a esto:

fileDescriptor = context.getContentResolver (). openAssetFileDescriptor (selectedImage, "r");

Aunque selectedImage contiene esto:

file: ///storage/emulated/0/DCIM/Camera/IMG_20131023_183343.jpg

El archivoDescriptor devuelve un FileNotFoundException. Revisé el sistema de archivos y la imagen no se guarda en esta ubicación. La cámara PicUri en TakePhotoActivity apunta a una imagen no existente. Actualmente estoy comprobando dónde va todo mal.

Edit2: descubrí el error: como el dispositivo es Samsung, y le dice a la aplicación que es un dispositivo de Samsung, se aplican las soluciones específicas de Samsung. Sin embargo, Cyanogenmod no necesita esas correcciones, y al final el código se rompe. Una vez que elimines

(manufacturerr.contains ("samsung")) &&

Funciona. Como esta es una ROM personalizada, no se puede planificar por supuesto. Estoy tratando de encontrar una forma de detectar si el dispositivo ejecuta cyanogenmod y luego incluir esto en tu código.

Gracias por una buena corrección de cámara!

Edit3: Lo arreglé para ejecutar Cyanogenmod en el Galaxy S3 cambiando tu código a este: Bueno, ahora algunas veces funciona, otras no. Extraño.

if (getPackageManager (). hasSystemFeature ("com.cyanogenmod.android") || (! (fabricante.contains ("samsung")) &&! (fabricante.contains ("sony")) &&! (fabricanter.contains (" lge "))))


Experimento algunos problemas al usar esto con Sony Xperia Z5.

Añadí esto y mejoró mucho.

if (buildType.contains("sony")&& buildDevice.contains("e5823")) { setPreDefinedCameraUri = true;}

Pero 4 veces de 22 reinició la cámara y una vez que se reinició dos veces. Reinicié la aplicación debido a cada prueba. ¿Hay alguna forma de evitar esto o acepto este resultado?

Lo que ocurre es que si la cámara se reinicia puedo presionar el botón Atrás dos veces y pulsar el botón, la imagen está allí en mi Imageview y se guarda


He probado este código con un Sony Xperia Go, un Samsung Galaxy SII, un Samsung Galaxy SIII mini y un Samsung Galaxy Y ¡funcionó en todos los dispositivos!

Pero en el LG E400 (2.3.6) no funcionó y usted obtiene imágenes dobles en la galería. Así que agregué el fabricante .contains ("lge") en el vacío startCameraIntent () y solucionó el problema.

if(!(manufacturer.contains("samsung")) && !(manufacturer.contains("sony")) && !(manufacturer.contains("lge"))) { String filename = System.currentTimeMillis() + ".jpg"; ContentValues values = new ContentValues(); values.put(MediaStore.Images.Media.TITLE, filename); cameraPicUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); intent.putExtra(MediaStore.EXTRA_OUTPUT, cameraPicUri); }


ACTUALIZACIÓN: 2 de enero de 2014: Intenté realmente evitar implementar diferentes estrategias basadas en el fabricante del dispositivo. Desafortunadamente, no pude evitarlo. Al pasar por cientos de publicaciones y hablar con varios desarrolladores, nadie encontró una solución que funcione en todos los dispositivos sin implementar el código específico del fabricante del dispositivo.

Después de publicar mi solución aquí en , algunos desarrolladores me pidieron que publicara mi código en github. Así que aquí está ahora: AndroidCameraUtil en github

El código se probó con éxito en una amplia variedad de dispositivos con Android API-Level> = 8. Para obtener una lista completa, consulte el archivo Readme en github.

CameraIntentHelperActivity proporciona la funcionalidad principal, que también se describe con más detalle a continuación.

Llamar a la actividad de cámara predeterminada:

  • para dispositivos Samsung y Sony : llamo a la actividad de la cámara con la llamada al método para iniciar la actividad para el resultado. Solo configuro la constante CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE. NO configuro ningún otro recurso adicional.
  • para todos los demás dispositivos : llamo a la actividad de la cámara con la llamada al método para iniciarActividadesporResultado como anteriormente. Esta vez, sin embargo, también configuré el intento MediaStore.EXTRA_OUTPUT adicional y proporcioné un URI, donde quiero que se guarde la imagen.

En ambos casos, recuerdo la hora en que se inició la actividad de la cámara.

Resultado de la actividad de la cámara:

  1. Mediastore: Primero, trato de leer la foto que está siendo capturada desde MediaStore. Usando una mangedQuery en el contenido de MediaStore, recupero la última imagen que se está tomando, así como su propiedad de orientación y su marca de tiempo. Si encuentro una imagen y no se tomó antes de que se llamara la intención de la cámara, es la imagen que estaba buscando. De lo contrario, descarto el resultado y pruebo uno de los siguientes enfoques.
  2. Intento adicional: Segundo, trato de obtener una imagen Uri de intent.getData () del intento de regreso. Si esto tampoco funciona, continúo con el paso 3.
  3. Foto predeterminada Uri : Si todos los pasos mencionados anteriormente no funcionaron, uso la imagen Uri que pasé a la actividad de la cámara.

En este punto, recuperé la foto Uri y su orientación, que pasé a UploadPhotoActivity.

Procesamiento de imágenes

Por favor, eche un vistazo de cerca a mi clase BitmapHelper. Se basa en el código descrito en detalle en ese tutorial .

Además, el método shrinkBitmap también rota la imagen si es necesario en función de la información de orientación extraída anteriormente.

Espero que esto sea útil para algunos de ustedes.