Android ACTION_IMAGE_CAPTURE Propósito

Estamos intentando utilizar la aplicación de cámara nativa para permitir que el usuario tome una nueva imagen. Funciona muy bien si dejamos fuera el EXTRA_OUTPUT extra y devuelve la pequeña imagen de mapa de bits. Sin embargo, si putExtra(EXTRA_OUTPUT,...) en la intención antes de iniciarlo, todo funciona hasta que intente pulsar el botón "Aceptar" en la aplicación de cámara. El botón "Aceptar" simplemente no hace nada. La aplicación de cámara permanece abierta y nada se bloquea. Podemos anularlo, pero el archivo nunca se escribe. ¿Qué debemos hacer para obtener ACTION_IMAGE_CAPTURE para escribir la imagen tomada en un archivo?

Editar: Esto se hace a través de la intención MediaStore.ACTION_IMAGE_CAPTURE , sólo para ser claro

Este es un error bien documentado en algunas versiones de android. Es decir, en la experiencia de Google construye de androide, captura de imagen no funciona como documentado. Lo que he usado generalmente es algo como esto en una clase de utilidades.

 public boolean hasImageCaptureBug() { // list of known devices that have the bug ArrayList<String> devices = new ArrayList<String>(); devices.add("android-devphone1/dream_devphone/dream"); devices.add("generic/sdk/generic"); devices.add("vodafone/vfpioneer/sapphire"); devices.add("tmobile/kila/dream"); devices.add("verizon/voles/sholes"); devices.add("google_ion/google_ion/sapphire"); return devices.contains(android.os.Build.BRAND + "/" + android.os.Build.PRODUCT + "/" + android.os.Build.DEVICE); } 

Entonces cuando lanzo captura de imagen, creo una intención que comprueba el error.

 Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); if (hasImageCaptureBug()) { i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File("/sdcard/tmp"))); } else { i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); } startActivityForResult(i, mRequestCode); 

Entonces en la actividad que vuelvo a, hago cosas diferentes basadas en el dispositivo.

 protected void onActivityResult(int requestCode, int resultCode, Intent intent) { switch (requestCode) { case GlobalConstants.IMAGE_CAPTURE: Uri u; if (hasImageCaptureBug()) { File fi = new File("/sdcard/tmp"); try { u = Uri.parse(android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), fi.getAbsolutePath(), null, null)); if (!fi.delete()) { Log.i("logMarker", "Failed to delete " + fi); } } catch (FileNotFoundException e) { e.printStackTrace(); } } else { u = intent.getData(); } } 

Esto le ahorra tener que escribir una nueva aplicación de cámara, pero este código tampoco es grande. Los grandes problemas son

  1. Nunca obtendrá imágenes de tamaño completo de los dispositivos con el error. Obtendrá imágenes de 512px de ancho que se insertan en el proveedor de contenido de imagen. En los dispositivos sin el error, todo funciona como documento, obtendrá una imagen normal grande.

  2. Usted tiene que mantener la lista. Como se escribe, es posible que los dispositivos se flash con una versión de android (por ejemplo, las compilaciones de cyanogenmod ) que tiene el error fijado. Si eso sucede, su código se bloqueará. La solución consiste en utilizar toda la huella dactilar del dispositivo.

Sé que esto se ha respondido antes, pero sé que mucha gente se tropezó con esto, así que voy a añadir un comentario.

Tenía este mismo problema ocurren en mi Nexus One. Esto era del archivo que no existía en el disco antes de que la aplicación de la cámara comenzara. Por lo tanto, me aseguré de que el archivo existente antes de iniciar la aplicación de cámara. He aquí un ejemplo de código que usé:

 String storageState = Environment.getExternalStorageState(); if(storageState.equals(Environment.MEDIA_MOUNTED)) { String path = Environment.getExternalStorageDirectory().getName() + File.separatorChar + "Android/data/" + MainActivity.this.getPackageName() + "/files/" + md5(upc) + ".jpg"; _photoFile = new File(path); try { if(_photoFile.exists() == false) { _photoFile.getParentFile().mkdirs(); _photoFile.createNewFile(); } } catch (IOException e) { Log.e(TAG, "Could not create file.", e); } Log.i(TAG, path); _fileUri = Uri.fromFile(_photoFile); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE ); intent.putExtra( MediaStore.EXTRA_OUTPUT, _fileUri); startActivityForResult(intent, TAKE_PICTURE); } else { new AlertDialog.Builder(MainActivity.this) .setMessage("External Storeage (SD Card) is required.\n\nCurrent state: " + storageState) .setCancelable(true).create().show(); } 

Primero crear un único (algo) nombre de archivo utilizando un hash MD5 y ponerlo en la carpeta adecuada. A continuación, comprobar para ver si existe (no debería, pero su buena práctica para comprobar de todos modos). Si no existe, obtendré el directorio padre (una carpeta) y crearé la jerarquía de carpetas (por lo tanto, si las carpetas que conducen a la ubicación del archivo no existen, lo harán después de esta línea. Creo el archivo Una vez que el archivo se crea, obtengo el Uri y lo paso a la intención y luego el botón Aceptar funciona como se espera y todo es de oro.

Ahora, cuando se presiona el botón Ok en la aplicación de cámara, el archivo estará presente en la ubicación dada. En este ejemplo sería /sdcard/Android/data/com.example.myapp/files/234asdioue23498ad.jpg

No hay necesidad de copiar el archivo en el "onActivityResult" como se ha publicado anteriormente.

He pasado por varias estrategias de captura de fotos, y siempre parece haber un caso, una plataforma o ciertos dispositivos, donde algunas o todas las estrategias anteriores fallarán de maneras inesperadas. Pude encontrar una estrategia que utiliza el código de generación URI a continuación que parece funcionar en la mayoría, si no todos los casos.

 mPhotoUri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, new ContentValues()); Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intent.putExtra(MediaStore.EXTRA_OUTPUT, mPhotoUri); startActivityForResult(intent,CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE_CONTENT_RESOLVER); 

Para contribuir más a la discusión y ayudar a los recién llegados, he creado una aplicación de prueba / muestra que muestra varias estrategias diferentes para la implementación de captura de fotografías. Las contribuciones de otras implementaciones se animan a añadir a la discusión.

https://github.com/deepwinter/AndroidCameraTester

Tuve el mismo problema donde el botón Aceptar en la aplicación de la cámara no hizo nada, tanto en el emulador y en el nexo uno.

El problema desapareció después de especificar un nombre de archivo seguro que no MediaStore.EXTRA_OUTPUT espacios en blanco, sin caracteres especiales, en MediaStore.EXTRA_OUTPUT Además, si especifica un archivo que reside en un directorio que todavía no se ha creado, primero debe crearlo. La aplicación de cámara no realiza mkdir para usted.

El flujo de trabajo que describe debe funcionar como lo ha descrito. Podría ayudar si pudiera mostrarnos el código alrededor de la creación de la Intención. En general, el siguiente patrón debe permitirle hacer lo que está intentando.

 private void saveFullImage() { Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File file = new File(Environment.getExternalStorageDirectory(), "test.jpg"); outputFileUri = Uri.fromFile(file); intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri); startActivityForResult(intent, TAKE_PICTURE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if ((requestCode == TAKE_PICTURE) && (resultCode == Activity.RESULT_OK)) { // Check if the result includes a thumbnail Bitmap if (data == null) { // TODO Do something with the full image stored // in outputFileUri. Perhaps copying it to the app folder } } } 

Tenga en cuenta que es la actividad de la cámara que va a crear y guardar el archivo, y no es realmente parte de su aplicación, por lo que no tendrá permiso de escritura a la carpeta de la aplicación. Para guardar un archivo en la carpeta de la aplicación, cree un archivo temporal en la tarjeta SD y muévalo a la carpeta de la aplicación en el controlador onActivityResult .

Para dar seguimiento al comentario de Yenchi anterior, el botón Aceptar tampoco hará nada si la aplicación de cámara no puede escribir en el directorio en cuestión.

Esto significa que no puede crear el archivo en un lugar que sólo puede ser escrito por su aplicación (por ejemplo, algo bajo getCacheDir()) Algo bajo getExternalFilesDir() debería funcionar, sin embargo.

Sería bueno si la aplicación de cámara imprimió un mensaje de error a los registros si no podía escribir en la ruta EXTRA_OUTPUT especificada, pero no encontré uno.

Para que la cámara escriba a sdcard pero mantenga en un nuevo álbum en la aplicación de la galería que uso esto:

  File imageDirectory = new File("/sdcard/signifio"); String path = imageDirectory.toString().toLowerCase(); String name = imageDirectory.getName().toLowerCase(); ContentValues values = new ContentValues(); values.put(Media.TITLE, "Image"); values.put(Images.Media.BUCKET_ID, path.hashCode()); values.put(Images.Media.BUCKET_DISPLAY_NAME,name); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put(Media.DESCRIPTION, "Image capture by camera"); values.put("_data", "/sdcard/signifio/1111.jpg"); uri = getContentResolver().insert( Media.EXTERNAL_CONTENT_URI , values); Intent i = new Intent("android.media.action.IMAGE_CAPTURE"); i.putExtra(MediaStore.EXTRA_OUTPUT, uri); startActivityForResult(i, 0); 

Tenga en cuenta que tendrá que generar un nombre de archivo único cada vez y reemplazar el 1111.jpg que escribí. Esto fue probado con el nexo uno. El uri se declara en la clase privada, por lo que en el resultado de la actividad que soy capaz de cargar la imagen desde el uri a imageView para previsualizar si es necesario.

Te recomiendo que sigas el post de formación android para capturar una foto. Muestran en un ejemplo cómo tomar cuadros pequeños y grandes. También puede descargar el código fuente desde aquí

Tuve el mismo problema y lo arreglé con lo siguiente:

El problema es que cuando se especifica un archivo que sólo su aplicación tiene acceso a (por ejemplo, llamando a getFileStreamPath("file"); )

Es por eso que sólo me aseguré de que el archivo dado realmente existe y que TODOS tiene acceso de escritura a él.

 Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); File outFile = getFileStreamPath(Config.IMAGE_FILENAME); outFile.createNewFile(); outFile.setWritable(true, false); intent.putExtra(android.provider.MediaStore.EXTRA_OUTPUT,Uri.fromFile(outFile)); startActivityForResult(intent, 2); 

De esta manera, la aplicación de cámara tiene acceso de escritura al Uri dado y el botón Aceptar funciona bien 🙂

Es muy sencillo resolver este problema con Actividad Resultado Código Simple intente este método

 if (reqCode == RECORD_VIDEO) { if(resCode == RESULT_OK) { if (uri != null) { compress(); } } else if(resCode == RESULT_CANCELED && data!=null){ Toast.makeText(MainActivity.this,"No Video Recorded",Toast.LENGTH_SHORT).show(); } } 

Creé la biblioteca simple que manejará elegir imágenes de diversas fuentes (galería, cámara), ahorrar quizá a una cierta localización (tarjeta del SD o memoria interna) y devolver la imagen detrás así que por favor libre de utilizarla y de mejorarla – Android-ImageChooser .

El archivo necesita ser grabable por la cámara, como Praveen señaló.

En mi uso quería almacenar el archivo en el almacenamiento interno. Hice esto con:

 Intent i = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); if (i.resolveActivity(getPackageManager()!=null)){ try{ cacheFile = createTempFile("img",".jpg",getCacheDir()); cacheFile.setWritavle(true,false); }catch(IOException e){} if(cacheFile != null){ i.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(cacheFile)); startActivityForResult(i,REQUEST_IMAGE_CAPTURE); } } 

Aquí cacheFile es un archivo global utilizado para referirse al archivo que está escrito. Entonces en el método de resultado la intención devuelta es nula. Entonces el método para procesar la intención se parece a:

 protected void onActivityResult(int requestCode,int resultCode,Intent data){ if(requestCode != RESULT_OK){ return; } if(requestCode == REQUEST_IMAGE_CAPTURE){ try{ File output = getImageFile(); if(output != null && cacheFile != null){ copyFile(cacheFile,output); //Process image file stored at output cacheFile.delete(); cacheFile=null; } }catch(IOException e){} } } 

Aquí getImageFile() es un método de utilidad para nombrar y crear el archivo en el que se debe almacenar la imagen, y copyFile() es un método para copiar un archivo.

Puede utilizar este código

 private Intent getCameraIntent() { PackageManager packageManager = mContext.getPackageManager(); List<ApplicationInfo> list = packageManager.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES); Intent main = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE); List<ResolveInfo> launchables = packageManager.queryIntentActivities(main, 0); if (launchables.size() == 1) return packageManager.getLaunchIntentForPackage(launchables.get(0).activityInfo.packageName); else for (int n = 0; n < list.size(); n++) { if ((list.get(n).flags & ApplicationInfo.FLAG_SYSTEM) == 1) { Log.d("TAG", "Installed Applications : " + list.get(n).loadLabel(packageManager).toString()); Log.d("TAG", "package name : " + list.get(n).packageName); String defaultCameraPackage = list.get(n).packageName; if (launchables.size() > 1) for (int i = 0; i < launchables.size(); i++) { if (defaultCameraPackage.equals(launchables.get(i).activityInfo.packageName)) { return packageManager.getLaunchIntentForPackage(defaultCameraPackage); } } } } return null; } 
 protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_CANCELED) { //do not process data, I use return; to resume activity calling camera intent enter code here } } 
  • Camera.takePicture () no funciona en mi JB & GB & Froyo teléfonos
  • Cómo dibujar una superposición en un SurfaceView utilizado por la cámara en Android?
  • No se puede usar la cámara después de apagar la linterna
  • Phonegap / Cordova cámara plugin - cómo obtener la fecha de la foto / hora?
  • Cómo restringir el complemento para cambiar la cámara trasera / trasera en android / cordova
  • Android: muestra líneas de cuadrícula en la cámara
  • Cómo hacer que el modo de ráfaga esté disponible para la cámara
  • Graba, guarda y reproduce un video en Android
  • Convertir el marco de vista previa en un mapa de bits
  • Cómo tomar fotos en la aplicación Android sin el interfaz de usuario ..?
  • ¿Cuál es la forma correcta de implementar Toque para enfocar para la cámara?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.