如何在 Android 上使用 MediaStore 将数据从相机保存到磁盘?

Posted

技术标签:

【中文标题】如何在 Android 上使用 MediaStore 将数据从相机保存到磁盘?【英文标题】:How do I save data from Camera to disk using MediaStore on Android? 【发布时间】:2010-10-13 12:56:39 【问题描述】:

对于我的应用程序,我一直在使用我自己的 Camera 类来拍摄图像和我自己的数据库,但很快我就跟不上变化了,我决定使用 android 中内置的相机应用程序来完成工作,但我似乎无法让它保存文件。我在这里想念什么?该应用程序似乎保存了文件,但它只有 0 个字节。我查找了 Camera 应用程序的源代码,它正在 Extras 中寻找“输出”来保存文件。任何帮助将不胜感激。

Public class CameraTest extends Activity 
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button cameraButton = (Button) findViewById(R.id.cameraButton);
        cameraButton.setOnClickListener( new OnClickListener()
            public void onClick(View v )
                ContentValues values = new ContentValues();
                values.put(Images.Media.TITLE, "title");
                values.put(Images.Media.BUCKET_ID, "test");
                values.put(Images.Media.DESCRIPTION, "test Image taken");
                Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
                Intent intent = new Intent("android.media.action.IMAGE_CAPTURE");
                intent.putExtra("output", uri.getPath());
                startActivityForResult(intent,0);
            
        );

    

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
        if (requestCode== 0 && resultCode == Activity.RESULT_OK)
            ((ImageView)findViewById(R.id.pictureView)).setImageURI(data.getData());
        
    



【问题讨论】:

【参考方案1】:

这适用于以下代码,当然我对最后一个代码有点愚蠢。我仍然认为必须有一种更好的方法,以便原始图像仍然保存在某个地方。它仍然向我发送较小的 25% 大小的图像。

public class CameraTest extends Activity 
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    Button cameraButton = (Button) findViewById(R.id.cameraButton);
    cameraButton.setOnClickListener( new OnClickListener()
        public void onClick(View v )

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

            startActivityForResult(intent,0);
        
    );



@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    if (requestCode== 0 && resultCode == Activity.RESULT_OK) 
        Bitmap x = (Bitmap) data.getExtras().get("data");
        ((ImageView)findViewById(R.id.pictureView)).setImageBitmap(x);
        ContentValues values = new ContentValues();
        values.put(Images.Media.TITLE, "title");
        values.put(Images.Media.BUCKET_ID, "test");
        values.put(Images.Media.DESCRIPTION, "test Image taken");
        values.put(Images.Media.MIME_TYPE, "image/jpeg");
        Uri uri = getContentResolver().insert(Media.EXTERNAL_CONTENT_URI, values);
        OutputStream outstream;
        try 
            outstream = getContentResolver().openOutputStream(uri);
            x.compress(Bitmap.CompressFormat.JPEG, 70, outstream);
            outstream.close();
         catch (FileNotFoundException e) 
            //
         catch (IOException e) 
            //
        
    

另外,我知道 Android 的纸杯蛋糕版本应该很快会修复小图像尺寸。

【讨论】:

:嘿,我使用了你的代码,但我有一个问题。我使用了纵横比和裁剪选项,但它没有采用纵横比。为什么这是异常行为?请帮助我【参考方案2】:

以下代码将启动默认摄像头并让摄像头将图像保存到指定的 uri。关键是将额外的“MediaStore.EXTRA_OUTPUT”与所需的 uri 一起放置。

File file = new File(Environment.getExternalStorageDirectory().getPath() + "/Images/" + image_name + ".jpg");
Uri imageUri = Uri.fromFile(file);

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);

startActivityForResult(intent, 0);

【讨论】:

有没有办法在拍照后自动保存文件?还是让用户在启动相机并拍照后做出决定会更好。【参考方案3】:

在您的第一次尝试中,相机应用程序可能会在读取您的“输出”额外内容时崩溃,因为它希望它是一个 Uri,而您提供了一个字符串。相机应用程序似乎在拍摄照片后读取了额外的标志。您应该只提供 uri,而不是 uri.getPath()。然后,由于您已经知道照片的 URI,它不会在 onResult 调用中返回。您需要记住成员变量中的 URI。

在第二次尝试中,您将得到一个缩小 (50%) 的位图。它主要用于视图。我认为全尺寸位图对于应用程序的内存预算来说太大了。这可能是降级的原因。

【讨论】:

有道理。我记得遇到较大图像或屏幕上有多个未缩放图像时出现缓冲区溢出类型问题...【参考方案4】:

仅供参考,在 docs 上找到了这个: 调用者可能会传递一个额外的 EXTRA_OUTPUT 来控制此图像的写入位置。如果 EXTRA_OUTPUT 不存在,则将小尺寸图像作为额外字段中的位图对象返回。这对于只需要小图像的应用程序很有用。如果存在 EXTRA_OUTPUT,则将全尺寸图像写入 EXTRA_OUTPUT 的 Uri 值。

位于此处:http://developer.android.com/reference/android/provider/MediaStore.html

所以应用程序可以为你保存完整尺寸的图像,如果你告诉它在哪里。

**编辑:HTC 设备并非如此。使用 htc sense ui 的 HTC(不是 nexus)已从 android 1.5 分支出来,并带有一个始终以低分辨率保存图像的错误。您可以为相机午餐活动,并使用相机的分享功能来使用完整尺寸的图像。

【讨论】:

【参考方案5】:

我在模拟器上遇到了同样的问题, 我在真机上试了一下,效果不错 也许是因为虚拟手机不能真正拍照。

【讨论】:

以上是关于如何在 Android 上使用 MediaStore 将数据从相机保存到磁盘?的主要内容,如果未能解决你的问题,请参考以下文章

调用系统相册

如何在 Android 上使用 Gammaray

如何在 Android 上使用 javax.smartcardio 包?

如何在 Android 相机上使用意图添加功能裁剪图像?

如何在 Android 上使用 QOpenGLWidget?

如何在Android上打破通知的内容