内置相机,使用额外的 MediaStore.EXTRA_OUTPUT 存储图片两次(在我的文件夹中,在默认值中)

Posted

技术标签:

【中文标题】内置相机,使用额外的 MediaStore.EXTRA_OUTPUT 存储图片两次(在我的文件夹中,在默认值中)【英文标题】:Built-in Camera, using the extra MediaStore.EXTRA_OUTPUT stores pictures twice (in my folder, and in the default) 【发布时间】:2011-09-14 12:59:46 【问题描述】:

我目前正在开发一个使用内置相机的应用程序。 我通过单击一个按钮将此称为 sn-p:

Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();

intent.putExtra(MediaStore.EXTRA_OUTPUT, outputFileUri);
startActivityForResult(intent, 0);

用相机拍照后,jpg很好存储在sdcard/myFolder/myPicture.jpg,但它也存储在/sdcard/DCIM/ Camera/2011-06-14 10.36.10.jpg,默认路径。

有没有办法阻止内置相机将图片存储在默认文件夹中?

编辑:我想我会直接使用 Camera 类

【问题讨论】:

继续努力........谢谢 【参考方案1】:

另一种方法,在android 2.1上测试,取图库最后一张图片的ID或绝对路径,然后你可以删除重复的图片。

可以这样做:

/**
 * Gets the last image id from the media store
 * @return
 */
private int getLastImageId()
    final String[] imageColumns =  MediaStore.Images.Media._ID, MediaStore.Images.Media.DATA ;
    final String imageOrderBy = MediaStore.Images.Media._ID+" DESC";
    Cursor imageCursor = managedQuery(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, imageColumns, null, null, imageOrderBy);
    if(imageCursor.moveToFirst())
        int id = imageCursor.getInt(imageCursor.getColumnIndex(MediaStore.Images.Media._ID));
        String fullPath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
        Log.d(TAG, "getLastImageId::id " + id);
        Log.d(TAG, "getLastImageId::path " + fullPath);
        imageCursor.close();
        return id;
    else
        return 0;
    

并删除文件:

private void removeImage(int id) 
   ContentResolver cr = getContentResolver();
   cr.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, MediaStore.Images.Media._ID + "=?", new String[] Long.toString(id)  );

此代码基于帖子:Deleting a gallery image after camera intent photo taken

【讨论】:

它工作得很好。但在我的情况下,它会从 SD 卡文件夹中删除图像。我使用的是索尼爱立信手机。在我的应用程序中,我捕获图像并保存到 SD 卡文件夹并返回到我所在的活动添加了从 sd 卡获取图像并添加到网格视图的网格视图。您的代码运行良好,但它从我的文件夹中删除。任何帮助都将是可观的。 @AshishMishra 我不确定我是否理解正确。如果您不想删除,请不要调用 removeImage。 @Derzu你不觉得它会删除错误的图像,其中没有创建重复的图像 @FatalError 是的...如果没有真正保存新图像,则存在此风险。 @Derzu 是否有任何过程可以知道哪个设备创建了重复的图像,哪个没有【参考方案2】:

虽然“Ilango J”的答案提供了基本思想。我想我实际上会写下我是如何做到的。 应该避免我们在 intent.putExtra() 中设置的临时文件路径,因为它是跨不同硬件的非标准方式。在 HTC Desire (Android 2.2) 上它不起作用,而且我听说它可以在其他手机上运行。最好采用一种在任何地方都有效的中立方法。

请注意,此解决方案(使用 Intent)要求手机的 SD 卡可用且未安装到 PC 上。当 SD 卡连接到 PC 时,即使是普通的相机应用程序也无法工作。

1) 启动相机捕捉意图。请注意,我禁用了临时文件写入(跨不同硬件的非标准)

    Intent camera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    startActivityForResult(camera , 0);

2) 处理回调,从 Uri 对象中获取抓取到的图片路径并传递给 step#3

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    switch (requestCode) 
    case CAPTURE_PIC: 
        if (resultCode == RESULT_OK && data != null) 
            Uri capturedImageUri = data.getData();
            String capturedPicFilePath = getRealPathFromURI(capturedImageUri);
            writeImageData(capturedImageUri, capturedPicFilePath);
            break;
        
    
    


public String getRealPathFromURI(Uri contentUri) 
    String[] projx =  MediaStore.Images.Media.DATA ;
    Cursor cursor = managedQuery(contentUri, projx, null, null, null);
    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
    cursor.moveToFirst();
    return cursor.getString(column_index);

3) 克隆并删除文件。看到我使用了 Uri 的 InputStream 来读取内容。 同样可以从capturedPicFilePath 的文件中读取。

public void writeImageData(Uri capturedPictureUri, String capturedPicFilePath) 

    // Here's where the new file will be written
    String newCapturedFileAbsolutePath = "something" + JPG;

    // Here's how to get FileInputStream Directly.
    try 
        InputStream fileInputStream = getContentResolver().openInputStream(capturedPictureUri);
        cloneFile(fileInputStream, newCapturedFileAbsolutePath);
     catch (FileNotFoundException e) 
        // suppress and log that the image write has failed. 
    

    // Delete original file from Android's Gallery
    File capturedFile = new File(capturedPicFilePath);
    boolean isCapturedCameraGalleryFileDeleted = capturedFile.delete();


  public static void cloneFile(InputStream currentFileInputStream, String newPath) 
    FileOutputStream newFileStream = null;

    try 

        newFileStream = new FileOutputStream(newPath);

        byte[] bytesArray = new byte[1024];
        int length;
        while ((length = currentFileInputStream.read(bytesArray)) > 0) 
            newFileStream.write(bytesArray, 0, length);
        

        newFileStream.flush();

     catch (Exception e) 
        Log.e("Prog", "Exception while copying file " + currentFileInputStream + " to "
                + newPath, e);
     finally 
        try 
            if (currentFileInputStream != null) 
                currentFileInputStream.close();
            

            if (newFileStream != null) 
                newFileStream.close();
            
         catch (IOException e) 
            // Suppress file stream close
            Log.e("Prog", "Exception occured while closing filestream ", e);
        
    

【讨论】:

我的安卓 Galaxy S II 上的活动结果数据为空 是的,三星制造的手机有问题。找到解决方法后,我将立即发布该方法。我刚订购了几部也有三星相机问题的 Nexus S 手机。谷歌搜索。其他人也面临这个问题。 这可行,但是当拍摄照片时,元数据会在 MediaStorage 中注册,因此当您浏览图库时,即使文件消失,照片仍会存在。你如何删除它? 对不起,我应该补充一下,这是在 Desire 2.2 上【参考方案3】:

试试这个代码:

 Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
//Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

String path = Environment.getExternalStorageDirectory().getAbsolutePath();
path += "/myFolder/myPicture.jpg";
File file = new File( path );
//file.mkdirs();
Uri outputFileUri = Uri.fromFile( file );
//String absoluteOutputFileUri = file.getAbsolutePath();

intent.putExtra("output", outputFileUri);
startActivityForResult(intent, 0);

【讨论】:

这与上面给出的来源有何不同。毕竟常量MediaStore.EXTRA_OUTPUT也解析为字符串"output" 抓拍图片后做一件事删除myPicture.jpg图片。使用 file.delete() 函数。

以上是关于内置相机,使用额外的 MediaStore.EXTRA_OUTPUT 存储图片两次(在我的文件夹中,在默认值中)的主要内容,如果未能解决你的问题,请参考以下文章

需要在内置相机应用程序中显示自定义形状叠加

JxCapture osx 相机问题

如何避免在 Relay.createcontainer 内置的 graphql 查询中添加额外的字段?

[Unity3D/2D]实现相机对人物角色的跟随效果/相机在一定范围内移动/内置插件实现

内置相机应用程序正确保存我的视频后出现神秘的 NullpointerException

当我尝试捕获图像(内置相机)并将其保存到文件时出现 NullPointerException [重复]