拍摄相机意图后删除图库图像

and*_*low 64 android image android-camera-intent

我知道这有许多不同的方式,但我似乎无法从默认文件夹中删除图库图像.我正确地将文件保存到SD卡,我可以删除该文件,但在Camera文件夹下显示的默认图库文件不会删除.

我希望在返回活动后删除图像,因为文件已存储在SD卡下/Coupon2.

有什么建议?

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*aul 70

我的申请要求我打电话打算拍照.照片不能在图库中,而是必须位于SD卡上的特定目录中.

最初我刚刚使用了EXTRA_OUTPUT,但我很快发现了以下内容: - 有些设备完全使用它并跳过图库. - 有些设备完全忽略它,只能使用图库. - 有些设备确实很糟糕并将完整尺寸的图像保存到图库中,并且只将缩略图保存到我想要的位置.(HTC你知道你是谁...)

所以,当我完成时,我不能盲目地删除一个库文件.最后添加的照片可能是也可能不是我要删除的照片.此外,我可能必须复制该文件,然后替换我自己的文件.因为我的活动是2000行,并且我的公司不希望我们的所有代码都被发布,所以我只发布了执行此操作所涉及的方法.希望这会有所帮助.

另外,我会说,这是我的第一个Android应用程序.如果有一个更好的方法来做我不知道的事情,我不会感到惊讶,但这对我有用!

所以,这是我的解决方案:

首先,在我的应用程序上下文中,我定义一个变量如下:

public ArrayList<String> GalleryList = new ArrayList<String>();
Run Code Online (Sandbox Code Playgroud)

接下来,在我的活动中,我定义了一个方法来获取库中所有照片的列表:

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());
   }
}
Run Code Online (Sandbox Code Playgroud)

这是一个为我的新图像返回唯一文件名的方法:

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();
}
Run Code Online (Sandbox Code Playgroud)

我的Activity中有三个变量,用于存储有关当前文件的信息.字符串(路径),File变量和该文件的URI:

public static String sFilePath = ""; 
public static File CurrentFile = null;
public static Uri CurrentUri = null;
Run Code Online (Sandbox Code Playgroud)

我从不直接设置这些,我只在文件路径上调用一个setter:

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);
   }
}
Run Code Online (Sandbox Code Playgroud)

现在我打电话打算拍照.

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);
}
Run Code Online (Sandbox Code Playgroud)

一旦完成,活动回来,这是我的代码:

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());
            }
         }
      }
   }      
}
Run Code Online (Sandbox Code Playgroud)

  • 不要保留图库项目的ArrayList,而应考虑使用HashMap.现在你的代码嵌套遍历Gallery中的图像两次,所以对于N个图像,你正在运行n ^ 2个比较.这将导致具有许多图像的设备明显滞后.如果使用HashMap,则使用小写文件名作为键.然后,您可以使用containsKey检查文件是否存在,将其转换为O(n)操作. (4认同)

Emi*_*yan 15

如果有人正在寻找一个更简单的解决这个问题的方法,这就是我如何解决这个问题.

我有一个捕获按钮,当按下它时意图被发送,我添加的是我也从图像mediastore获取最后一个id并存储它:

/**
 * 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后,当活动返回时,我运行此代码以检查捕获前的最后一个图像ID,然后捕获后的图像查询的ID大于记录,如果更多则删除位于我为摄像机指定的位置的记录保存.

/*
 * 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();
Run Code Online (Sandbox Code Playgroud)

对我来说这是一个更简单的解决方案,我在我的HTC上测试了这个问题.

另一个方面说明,我最初使用*DATE_TAKEN*不*_ID*作为参数,但似乎是在模拟器上的一些图像被通过的意图捕获了他们的millsecond一些bug*DATE_TAKEN*倍乘以1000,所以我切换到*_ID*,这似乎更强大.

  • @Emil你的答案不是伪代码.如果我看到正常的代码,我希望它能够正常工作.如果您知道答案不完整或者需要更多代码,请在某处提出建议,并告诉读者他需要做些什么才能使其正常工作.这将使您的答案更加完整和成功. (4认同)
  • @Xithias我不在乎你的态度.这与初学者无关,如果你只想复制和粘贴代码 - 不要混淆你正在做的编程. (4认同)
  • @Xithias我简单地描述了一个解决这个问题的简单方法,代码可以指导你.我不打算花时间警告人们代码可能不起作用或某些方法最终会被弃用,因为我不希望任何有能力的程序员只是复制代码片段并抱怨它不起作用. (3认同)
  • @Xithias认为这是一个伪代码来获取你可以实现的方法的要点,不要只是复制代码并期望它工作. (2认同)

ElY*_*nte 15

这将从库中删除该文件:

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);
    }
 }
Run Code Online (Sandbox Code Playgroud)

关于EXTRA_OUTPUT不是标准行为.我认为这种伪算法应该适用于所有情况:

1)不要使用EXTRA_OUTPUT.图像/照片始终会转到图库位置.

2)将文件从库位置复制到所需位置.

3)从库中删除(使用上面的代码)文件.

但是当然它似乎太完美了......在某些设备中(例如原版带有android 2.3的Galaxy Tab),你必须使用EXTRA_OUTPUT和ACTION_IMAGE_CAPTURE,否则意图不起作用.


blu*_*con 5

好吧,我认为整个问题来自于你期望另一个应用程序没有发生某种结果的事实.这是(只是要清楚) -

  • 由于您的应用程序无法捕获图像,因此启动可拍照的活动.
  • 告诉其他应用程序您要保存picutre的位置
  • 在指定的位置使用保存的图像.
  • 但问题是其他应用程序也将图像保存在不同的位置,这是您不希望的.

现在让我们从其他应用程序的角度来看它,它正在捕获图像.让我们考虑两种情况(这是可能的) -

  • 首先,使用fileName选项或要保存图像的位置启动应用程序.
  • 其次,启动应用程序时没有任何额外信息,例如fileName或要保存图像的位置.(如果直接从菜单中启动捕获应用程序,可能会发生这种情况)

理想情况下,应该发生的事情是,如果有额外的信息,如fileName或location,那么他应该使用该位置,如果没有,那么他可以使用他自己的.但是唉,我们来自一个理想的世界,因为当您启动相机应用程序时应该发生的事情没有任何结论,相机应用程序开发人员将有自己的解释.

由于不同的设备具有不同的相机应用设置作为默认设置(是的,通常替换库存相机),所获得的结果将是/将是不同的.

因此,在某些相机中,它可能只保存在其他地方,也可能保存在相机文件夹中(因为相机应用程序可能始终将捕获的图像保存在相机文件夹中,并将其保存在不同的位置是由应用程序)

如果您只是将一个fileName传递给相机应用程序,应该在拍摄一张照片后返回应用程序?我想不是.那么在这种情况下应该怎么做?这一切都非常模糊或灰色地带.

现在,如果您不希望将其保存在Camera文件夹中,那么找出是否可以获取最近捕获的图像的文件名,然后将其从应用程序中删除.或者不要告诉相机应用程序需要保存的位置,只需获取文件名并移动它所需的位置即可.

如果您没有获得文件名,那么您将受到其他应用程序开发人员的支配.(嘿!这也不是他的错,他只是按照他想要的方式设计它!)