Pregunta

Sé que esto se ha preguntado de muchas maneras diferentes, pero aún así no puedo eliminar la imagen de la galería de la carpeta predeterminada. Estoy guardando el archivo en la tarjeta SD correctamente y puedo eliminar la multa de ese archivo, pero el archivo de imagen de la galería predeterminado que se muestra debajo de la cámara de carpeta no se eliminará.

Me gustaría que la imagen elimine una vez que se devuelva la actividad ya que el archivo ya se almacena en la tarjeta SD debajo /Coupon2.

¿Alguna sugerencia?

public void startCamera() {
    Log.d("ANDRO_CAMERA", "Starting camera on the phone...");

    mManufacturerText = (EditText) findViewById(R.id.manufacturer);
    String ManufacturerText = mManufacturerText.getText().toString();
    String currentDateTimeString = new Date().toString();

    Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    File filedir = new File(Environment.getExternalStorageDirectory()+"/Coupon2");
    filedir.mkdirs();

    File file = new File(Environment.getExternalStorageDirectory()+"/Coupon2", ManufacturerText+"-test.png");
    outputFileUri = Uri.fromFile(file);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);

    startActivityForResult(intent, CAMERA_PIC_REQUEST);
}

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CAMERA_PIC_REQUEST && resultCode == -1) {  
        Intent intent = new Intent("com.android.camera.action.CROP");
        intent.putExtra("crop", "true");
        intent.putExtra("scale", "true");

        intent.putExtra("return-data", false);
        intent.setDataAndType(outputFileUri, "image/*");
        intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
        startActivityForResult(intent, CAMERA_CROP_REQUEST);
    }else { 
        SetImage();
        saveState();
    }
}
¿Fue útil?

Solución

Mi aplicación requiere que llame a una intención de tomar una foto. La foto no puede estar en la galería, sino que debe estar en un directorio específico en la tarjeta SD.

Originalmente acabo de usar el extra_output, pero pronto descubrí lo siguiente: - Algunos dispositivos lo usan por completo y omiten la galería. - Algunos dispositivos lo ignoran por completo y solo usan la galería. - Algunos dispositivos realmente apestan y guardan una imagen de tamaño completo en la galería, y guardan una miniatura solo en la ubicación que quería. (Htc sabes quién eres ...)

Entonces, no puedo eliminar ciegamente un archivo de la galería cuando termine. La última foto agregada puede o no ser la que quiero eliminar. Además, es posible que tenga que copiar ese archivo reemplazando el mi propio después. Debido a que mi actividad es 2000 líneas, y mi empresa no querría que se publique todo nuestro código, solo estoy publicando los métodos involucrados en hacer esto. Ojalá esto ayude.

Además, afirmaré, esta es mi primera aplicación de Android. No me sorprendería si hubiera una mejor manera de hacer esto que simplemente no conozco, ¡pero esto es lo que funciona para mí!

Entonces, aquí está mi solución:

Primero, en el contexto de mi aplicación defino una variable de la siguiente manera:

public ArrayList<String> GalleryList = new ArrayList<String>();

A continuación, en mi actividad, defino un método para obtener una lista de todas las fotos en la galería:

private void FillPhotoList()
{
   // initialize the list!
   app.GalleryList.clear();
   String[] projection = { MediaStore.Images.ImageColumns.DISPLAY_NAME };
   // intialize the Uri and the Cursor, and the current expected size.
   Cursor c = null; 
   Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
   //
   // Query the Uri to get the data path.  Only if the Uri is valid.
   if (u != null)
   {
      c = managedQuery(u, projection, null, null, null);
   }

   // If we found the cursor and found a record in it (we also have the id).
   if ((c != null) && (c.moveToFirst())) 
   {
      do 
      {
        // Loop each and add to the list.
        app.GalleryList.add(c.getString(0));
      }     
      while (c.moveToNext());
   }
}

Aquí hay un método para devolver un nombre de archivo único para mi nueva imagen:

private String getTempFileString()
{
   // Only one time will we grab this location.
   final File path = new File(Environment.getExternalStorageDirectory(), 
         getString(getApplicationInfo().labelRes));
   //
   // If this does not exist, we can create it here.
   if (!path.exists())
   {
      path.mkdir();
   }
   //
   return new File(path, String.valueOf(System.currentTimeMillis()) + ".jpg").getPath();
}

Tengo tres variables en mi actividad que almacenan información para mí sobre un archivo actual. Una cadena (ruta), una variable de archivo y un URI a ese archivo:

public static String sFilePath = ""; 
public static File CurrentFile = null;
public static Uri CurrentUri = null;

Nunca configuré estos directamente, solo llamo a un setter en la ruta del archivo:

public void setsFilePath(String value)
{
   // We just updated this value. Set the property first.
   sFilePath = value;
   //
   // initialize these two
   CurrentFile = null;
   CurrentUri = null;
   //
   // If we have something real, setup the file and the Uri.
   if (!sFilePath.equalsIgnoreCase(""))
   {
      CurrentFile = new File(sFilePath);
      CurrentUri = Uri.fromFile(CurrentFile);
   }
}

Ahora llamo una intención de tomar una foto.

public void startCamera()
{
   Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
   // Specify the output. This will be unique.
   setsFilePath(getTempFileString());
   //
   intent.putExtra(MediaStore.EXTRA_OUTPUT, CurrentUri);
   //
   // Keep a list for afterwards
   FillPhotoList();
   //
   // finally start the intent and wait for a result.
   startActivityForResult(intent, IMAGE_CAPTURE);
}

Una vez hecho esto, y la actividad regresa, aquí está mi código:

protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
   if (requestCode == IMAGE_CAPTURE)
   {
      // based on the result we either set the preview or show a quick toast splash.
      if (resultCode == RESULT_OK)
      {
         // This is ##### ridiculous.  Some versions of Android save
         // to the MediaStore as well.  Not sure why!  We don't know what
         // name Android will give either, so we get to search for this
         // manually and remove it.  
         String[] projection = { MediaStore.Images.ImageColumns.SIZE,
                                 MediaStore.Images.ImageColumns.DISPLAY_NAME,
                                 MediaStore.Images.ImageColumns.DATA,
                                 BaseColumns._ID,};
         //    
         // intialize the Uri and the Cursor, and the current expected size.
         Cursor c = null; 
         Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
         //
         if (CurrentFile != null)
         {               
            // Query the Uri to get the data path.  Only if the Uri is valid,
            // and we had a valid size to be searching for.
            if ((u != null) && (CurrentFile.length() > 0))
            {
               c = managedQuery(u, projection, null, null, null);
            }
            //   
            // If we found the cursor and found a record in it (we also have the size).
            if ((c != null) && (c.moveToFirst())) 
            {
               do 
               {
                  // Check each area in the gallary we built before.
                  boolean bFound = false;
                  for (String sGallery : app.GalleryList)
                  {
                     if (sGallery.equalsIgnoreCase(c.getString(1)))
                     {
                        bFound = true;
                        break;
                     }
                  }
                  //       
                  // To here we looped the full gallery.
                  if (!bFound)
                  {
                     // This is the NEW image.  If the size is bigger, copy it.
                     // Then delete it!
                     File f = new File(c.getString(2));

                     // Ensure it's there, check size, and delete!
                     if ((f.exists()) && (CurrentFile.length() < c.getLong(0)) && (CurrentFile.delete()))
                     {
                        // Finally we can stop the copy.
                        try
                        {
                           CurrentFile.createNewFile();
                           FileChannel source = null;
                           FileChannel destination = null;
                           try 
                           {
                              source = new FileInputStream(f).getChannel();
                              destination = new FileOutputStream(CurrentFile).getChannel();
                              destination.transferFrom(source, 0, source.size());
                           }
                           finally 
                           {
                              if (source != null) 
                              {
                                 source.close();
                              }
                              if (destination != null) 
                              {
                                 destination.close();
                              }
                           }
                        }
                        catch (IOException e)
                        {
                           // Could not copy the file over.
                           app.CallToast(PhotosActivity.this, getString(R.string.ErrorOccured), 0);
                        }
                     }
                     //       
                     ContentResolver cr = getContentResolver();
                     cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, 
                        BaseColumns._ID + "=" + c.getString(3), null);
                     break;                        
                  }
               } 
               while (c.moveToNext());
            }
         }
      }
   }      
}

Otros consejos

Si alguien está buscando un trabajo más simple sobre este problema, así es como resolví el problema.

Tengo un botón de captura y cuando se presiona se envía la intención, lo que agregué es que también voy y obtengo la última identificación de Image MediaStore y la almacene:

/**
 * Gets the last image id from the media store
 * @return
 */
private int getLastImageId(){
    final String[] imageColumns = { MediaStore.Images.Media._ID };
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    final String imageWhere = null;
    final String[] imageArguments = null;
    Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
    if(imageCursor.moveToFirst()){
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        imageCursor.close();
        return id;
    }else{
        return 0;
    }
}

Luego, cuando la actividad regresa, ejecuto este código en verificación de la última ID de imagen antes de capturar, luego consultas para las imágenes después de la captura tienen una identificación más grande y luego grabada y Si es más, se elimina el registro ubicado en la ubicación que especifiqué para que la cámara se guarde.

/*
 * Checking for duplicate images
 * This is necessary because some camera implementation not only save where you want them to save but also in their default location.
 */
final String[] imageColumns = { MediaStore.Images.Media.DATA, MediaStore.Images.Media.DATE_TAKEN, MediaStore.Images.Media.SIZE, MediaStore.Images.Media._ID };
final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
final String imageWhere = MediaStore.Images.Media._ID+">?";
final String[] imageArguments = { Integer.toString(MyActivity.this.captureLastId) };
Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, imageWhere, imageArguments, imageOrderBy);
if(imageCursor.getCount()>1){
    while(imageCursor.moveToNext()){
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        String path = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
        Long takenTimeStamp = imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.DATE_TAKEN));
        Long size = imageCursor.getLong(imageCursor.getColumnIndex(MediaStore.Images.Media.SIZE));
        if(path.contentEquals(MyActivity.this.capturePath)){
            // Remove it
            ContentResolver cr = getContentResolver();
            cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[]{ Long.toString(id) } );
            break;
        }
    }               
}
imageCursor.close();

Para mí, esta fue una solución mucho más simple, y probé mi HTC que estaba teniendo este problema.

Otra nota al margen, Originalmente usé * date_taken * no * _id * como parámetro, pero parece haber algún error que en el emulador algunas de las imágenes que se capturaban a través de la intención tenían su MillSegund * date_taken * multiplicado por un 1000, así que cambié a * _Id* que parece ser mucho más robusto.

Esto eliminará el archivo de la galería:

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

    if (requestCode == CAMERA_PIC_REQUEST && resultCode == RESULT_OK) { 

        /* Copy the file to other directory or whatever you want */

        // mContext is the context of the activity
        mContext.getContentResolver().delete(data.getData(), null, null);
    }
 }

Sobre el comportamiento extra_output no estándar. Creo que este pseudoalgoritmo debería funcionar en todos los casos:

1) No use Extra_Output. La imagen/foto siempre irá a la ubicación de la galería.

2) Copie el archivo desde la ubicación de la galería a la ubicación deseada.

3) Eliminar (con el código superior) el archivo de la galería.

Pero, por supuesto, parece ser demasiado perfecto ... en algunos dispositivos (por ejemplo, la Tab Galaxy original con Android 2.3), debe usar Extra_Output con Action_Image_Capture, sin esto, la intención no funciona.

Bueno, creo que todo el problema proviene del hecho de que espera un cierto resultado de otra aplicación que no está sucediendo. Que es (solo para ser claro) -

  • Inicie una actividad que pueda tomar una foto, ya que su aplicación no captura imágenes.
  • Dígale a la otra aplicación dónde desea guardar el picutre
  • Use la imagen guardada en la ubicación que especificó.
  • Pero el problema es que la otra aplicación también ha guardado la imagen en una ubicación diferente también, lo que no desea que lo haga.

Ahora veamos desde la otra perspectiva de la aplicación, que está capturando la imagen. Consideremos dos escenarios (lo cual es posible) -

  • Primero, la aplicación se inicia con la opción del nombre de archivo o ubicación donde se guardará la imagen.
  • En segundo lugar, la aplicación se inicia sin ninguna información adicional como el nombre de archivo o la ubicación donde se guardará la imagen (esto podría suceder si la aplicación de captura está lauchada directamente desde el menú)

Ahora, idealmente, lo que debería haber sucedido es que si hay información adicional como el nombre de archivo o la ubicación, entonces debería haber usado esa ubicación si no, puede usar la suya. Pero, por desgracia, somos de un mundo ideal y dado que nada está escrito en piedra en lo que debería suceder cuando lance una aplicación de cámara, el desarrollador de aplicaciones de cámara tendrá su propia interpretación.

Dado que diferentes dispositivos tienen una aplicación de cámara diferente establecida como predeterminada (sí, la cámara de stock generalmente se reemplaza) los resultados obtenidos son/serán diferentes.

Por lo tanto, en algunas cámaras se puede guardar en un solo lugar en otro, también podría guardar en la carpeta de la cámara (ya que la aplicación de la cámara siempre puede guardar la imagen capturada en la carpeta de la cámara y guardarla en una ubicación diferente es una bonificación dada por la aplicación)

Si solo pasa un nombre de archivo a la aplicación de la cámara, ¿debería devolver la aplicación después de tomar una foto? Yo creo que no. Entonces, ¿qué debería en tal escenario? Todo es muy ambiguo o un área gris.

Ahora, si no desea que se guarde en la carpeta de la cámara, averigüe si puede obtener el nombre de archivo de la imagen recientemente capturada y luego bórralo de su aplicación. O no le digas a la aplicación de la cámara dónde debe guardarla, solo obtenga el nombre de archivo y mueva la ubicación que desee.

Si no obtiene el nombre de archivo, entonces está a merced del otro desarrollador de aplicaciones. (¡Oye! ¡Tampoco es su culpa, él solo lo diseñó de la manera que quiere!)

Creo que no puedes hacer lo que quieras. Eso es triste pero no puedo encontrar otra respuesta.

Si trabaja con la implementación de la cámara de Google, funciona bien. Simplemente no almacena la foto en la galería en extra_output se especifica.

Pero cuando te enfrentas a otros dispositivos, pueden hacer algo completamente diferente. Esto se debe a que HTC, LG y tal vez otros tienen implementación de cámara personalizada y no puede hacer nada al respecto. Puede dejarlo tal como está o escribir su propia cámara que funcionará exactamente como lo necesita.

En realidad, no está relacionado con esta pregunta, pero un día descubrirá que la intención del cultivo no funciona en algunos dispositivos (http://groups.google.com/group/android-developers/browse_frm/thread/2dd647523926192c/4b6d087073a39607?tvc=1&pli=). Entonces, de nuevo, si lo necesita, tendrá que escribirlo usted mismo.

Esta no es una tarea fácil de resolver, pero puede abordar un método difícil. Si cualquiera necesita una solución simple y de trabajo para esto. Pruebe el siguiente código:

  1. Guarde la hora actual en mili en segundo lugar antes de llamar a la intención de la cámara.
  2. OnactivityResult Consuly La imagen Uri cuya fecha tomada es mayor que el milisegundo en el paso 1. Y eliminar el archivo. Eso es todo.
String[] projection = {MediaStore.Images.ImageColumns.SIZE,
                MediaStore.Images.ImageColumns.DISPLAY_NAME,
                MediaStore.Images.ImageColumns.DATA,
                BaseColumns._ID,MediaStore.Images.ImageColumns.DATE_ADDED};
        final String imageOrderBy = MediaStore.Images.Media._ID + " DESC";
        final String selection = MediaStore.Images.Media.DATE_TAKEN+" > "+mImageTakenTime;
        //// intialize the Uri and the Cursor, and the current expected size.
        Cursor c = null;
        Uri u = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
        c = getActivity().managedQuery(u, projection, selection, null, imageOrderBy);
        if(null != c && c.moveToFirst()){
            ContentResolver cr = getActivity().getContentResolver();
            cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    BaseColumns._ID + "=" + c.getString(3), null);
        }

Mira aquí - Ese es un código que guarda la imagen para EXTRA_OUTPUT carpeta sin guardarla en la galería. De esta manera, en mi aplicación, solía tomar una foto directamente de la cámara y luego eliminar la imagen tomada.

Este es el código que uso que toma una foto y la guarda en la ubicación especificada

Uri outputFileUri;

public void takePhoto() {
    File directory = new File(Environment.getExternalStorageDirectory()
            + "/HI-Tech" + "/");

    if (!directory.exists()) {
        directory.mkdir();
    }

    int count = 0;
    if (directory != null) {
        File[] files = directory.listFiles();
        if (files != null) {
            count = files.length;
        }
    }
    count++;
    String imagePath = "IMAGE_" + count + ".jpg";
    File file = new File(directory, imagePath);
    outputFileUri = Uri.fromFile(file);

        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
    startActivityForResult(intent, JobActivity.TAKE_PIC);
}

Luego manejo la respuesta.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    try {
        if (resultCode == RESULT_OK) {
            if (requestCode == JobActivity.TAKE_PIC) {
                Bitmap bitmap = decodeFile(new File(outputFileUri.getPath()), 160, 120);
    } catch (Exception e) {
        Log.e("Error", "Unable to set thumbnail", e);
    }
}

Tuve que declarar la base de salida como una variable global, ya que no encontré una forma de adquirir la ruta guardada OnActivityResult. Al pasar la salida de salida, notará que la imagen no se guarda en la cámara plegable sino en la ubicación especificada. He probado este código en mi NEXUS1 y una cosa barata de Samsung.

Espero que esto ayude

También estaba luchando con este problema. Por cierto, este problema está marcado como Obsolete en el android localizador de bichos. Por alguna razón, el equipo de Android ya no considera esto como un error. Tal vez porque esto está relacionado con el fabricante.

Parece que todas las soluciones (de este hilo y otras publicaciones de blog, etc.) forman el siguiente algoritmo:

  1. Guarde un identificador único de la última foto tomada;
  2. Inicie la actividad de la cámara usando Intent con EXTRA_OUTPUT ;
  3. Tome una foto y verifique si una identificación de la última foto tomada en la galería ha cambiado para decidir si debe eliminarse.

Algo similar se propone en la respuesta aceptada.

Pero descubrí que dicho enfoque no se puede usar en un código de producción. Por ejemplo, imaginemos una situación simple:

Usted almacena una identificación de la última foto tomada en la galería y lanzas la actividad de la cámara. Cuando el usuario toma una foto en algunos dispositivos, la actividad de la cámara muestra un diálogo con Cancel y OK botones (o algo así). Y la lógica detrás de ellos es la siguiente:

  • Si el usuario presiona Cancel Regresa a la actividad de la cámara y puede continuar tomando fotos.
  • Si él/ella (el usuario) presiona OK Botón La actividad de la cámara devuelve el resultado a su aplicación.

Las notas importantes aquí: resulta que en algunos dispositivos (probé en LG y HTC) la imagen ya se puede guardar mientras se presenta este diálogo.

Ahora imagine qué pasa si el usuario por alguna razón decide tocar Home Botón e inicia otra aplicación (por ejemplo, otra aplicación de cámara donde el usuario puede tomar diferentes fotos!). Y luego regresa a su aplicación donde todavía se presenta ese diálogo y presiona OK. Obviamente, en ese caso, su aplicación, su eliminará el archivo incorrecto ... y decepcionará al usuario :(

Entonces, después de mucha investigación, decidí que el mejor enfoque para superar este problema es escribir su propio motor de cámara o simplemente usar algunas libres de terceros como esta: cámara material.

Es probable que su mejor opción sea manejar la clase de cámara directamente, y luego almacenar el JPEG o RAW devuelto en la devolución de llamada donde desee.

Alternativamente, puede intentar eliminar la imagen tomada por _id del proveedor de contenido para los medios después de que se haya agregado. Simplemente busque por consulta y elimínelo a través de ContentResolver.delete, sin embargo, no estoy seguro de la implementación.

Después de luchar con esto por un tiempo, mordí la bala y Escribí mi propia cámara Caputere Activity. Estoy convencido de que esto es mucho más portátil y más seguro que el MediaStore.ACTION_IMAGE_CAPTURE soluciones. La imagen se almacenará donde la almacena y en ningún otro lugar y no está en peligro de eliminar algún archivo no relacionado por accidente. Además, es posible adaptar exactamente la función de cámara real a los requisitos.

Por razones de portabilidad, utilicé el Camera clase, no cámara2.

Vale la pena tener en cuenta que todos los parámetros de la cámara deben estar configurados, especialmente el tamaño de la imagen, el modo de enfoque y el modo de flash, todos pueden estar en un estado inesperado al comenzar la cámara.

Publicar esto como una respuesta, no como un comentario, porque en mi opinión es la respuesta correcta que resulta en esfuerzo mínimo.

protected void onActivityResult(int requestCode, int resultCode, Intent data) {  
    if (requestCode == CAMERA_REQUEST && resultCode == RESULT_OK) {

    Bitmap photo = (Bitmap) data.getExtras().get("data");
    Uri tempUri = Utils.getUri(getActivity(), photo);
    File finalFile = new File(getRealPathFromURI(tempUri));
    finalFile.delete();
    }  
}


public String getRealPathFromURI (Uri contentUri) {
    String path = null;
    String[] proj = { MediaStore.MediaColumns.DATA };
    Cursor cursor = getActivity().getContentResolver().query(contentUri, proj, null, null, null);
    if (cursor.moveToFirst()) {
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
        path = cursor.getString(column_index);
    }
    cursor.close();
    return path;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top