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

10
对于我的应用程序,我一直在使用自己的相机类来拍照和自己的数据库,但很快我就无法跟上变化,决定使用Android内置的相机应用程序来完成工作,但似乎无法将其保存到文件中。 我错过了什么?该应用程序似乎已经保存了文件,但是它只有0字节。我查看了相机应用程序的源代码,并正在寻找Extras中的“output”以保存该文件。非常感谢您能提供任何帮助。
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());
        }
    }


}
5个回答

16
这段代码有效,尽管我在最后一行可能有点笨。我仍然认为有更好的方法让原始图像仍然保存在某个地方。它仍然发送给我较小的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的杯子蛋糕版本很快就会解决小图片尺寸的问题。


嗨,我使用了你的代码,但是我有一个问题。我已经使用了纵横比和裁剪选项,但它没有采用纵横比。为什么会出现这种异常行为?请帮帮我。 - Geetanjali

6
下面的代码将启动默认相机,并让相机将图像保存到指定的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);

有没有一种方法可以在拍照后自动保存文件?还是让用户在启动相机并拍照后决定更好? - SOLDIER-OF-FORTUNE

4
提示,这篇文章是从文档中找到的: 调用者可以传递额外的EXTRA_OUTPUT参数来控制图像写入的位置。如果没有提供EXTRA_OUTPUT,则会在extra字段中以Bitmap对象的形式返回一个小尺寸的图像。这对于仅需要小图像的应用程序很有用。如果提供了EXTRA_OUTPUT,则全尺寸的图像将被写入EXTRA_OUTPUT的Uri值中。
相关内容位于此处:http://developer.android.com/reference/android/provider/MediaStore.html 因此,如果您告诉应用程序保存完整大小的图像,它就可以为您保存。 **编辑:但是,HTC设备不适用此规则。使用htc sense ui的HTC(而不是nexus)从android 1.5分支出,并携带一个错误,即始终以低分辨率保存图像。您可以启动相机活动并使用相机共享功能来使用全尺寸图像。

4
在第一次尝试中,当Camera应用程序读取您的“output”额外信息时,可能会导致应用程序崩溃,因为它期望它是一个Uri,而您提供的是一个String。Camera应用程序似乎在捕获照片后读取额外的标志。您应该只提供uri,而不是uri.getPath()。然后,由于您已经知道了照片的URI,它将不会在onResult调用中返回。您需要将URI记住在成员变量中。
在第二次尝试中,您将收到缩小了50%的位图。它主要用于视图。我认为完整大小的位图对应用程序的内存预算来说太大了。这可能是缩小的原因。

有道理。我记得在屏幕上放置更大的图像或超过一个未缩放的图像时会出现缓冲区溢出类型的问题... - prasanna

0

我在模拟器上遇到了同样的问题, 我在真机上尝试了一下,它可以工作, 可能是因为虚拟手机无法真正拍照。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接