如何使用 Android 上的 MediaStore 将数据从相机保存到磁盘?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/649057/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I save data from Camera to disk using MediaStore on Android?
提问by prasanna
For my application, I'd been using my own Camera class for taking images and my own database but soon enough I couldn't really keep up with changes and I decided to use the built in camera application in Android to do the job, but I can't seem to get it to save file. What am I missing here? The application seems to save the file but it's just 0 bytes. I looked up the source code of the Camera application and it's looking for the "output" in Extras to save the file. Any help would be greatly appreciated.
对于我的应用程序,我一直使用我自己的 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());
}
}
}
回答by prasanna
This worked with the following code, granted I was being a little dumb with the last one. I still think there's got to be a better way so that the original image is still saved somewhere. It still sends me the smaller 25% size image.
这适用于以下代码,当然我对最后一个有点愚蠢。我仍然认为必须有更好的方法才能将原始图像保存在某处。它仍然向我发送较小的 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) {
//
}
}
}
Also, I do know that the cupcake release of Android should fix the small image size soon.
此外,我确实知道 Android 的蛋糕版本应该很快修复小图像尺寸。
回答by Rahul Gupta-Iwasaki
The below code will start the default camera and have the camera save the image to the specified uri. The key is to put the extra "MediaStore.EXTRA_OUTPUT" along with the desired uri.
下面的代码将启动默认相机并让相机将图像保存到指定的 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);
回答by nabulaer
FYI , found this on docs : The caller may pass an extra EXTRA_OUTPUT to control where this image will be written. If the EXTRA_OUTPUT is not present, then a small sized image is returned as a Bitmap object in the extra field. This is useful for applications that only need a small image. If the EXTRA_OUTPUT is present, then the full-sized image will be written to the Uri value of EXTRA_OUTPUT.
仅供参考,在 docs 上找到了这个:调用者可能会传递一个额外的 EXTRA_OUTPUT 来控制该图像的写入位置。如果 EXTRA_OUTPUT 不存在,则在额外字段中将小尺寸图像作为位图对象返回。这对于只需要小图像的应用程序很有用。如果存在 EXTRA_OUTPUT,则全尺寸图像将写入 EXTRA_OUTPUT 的 Uri 值。
located here :http://developer.android.com/reference/android/provider/MediaStore.html
位于此处:http: //developer.android.com/reference/android/provider/MediaStore.html
so the app can save full size image for you , if you tell it where.
所以应用程序可以为你保存全尺寸图像,如果你告诉它在哪里。
**Edit : This is not the case with HTC devices. HTC (not nexus) that uses htc sense ui have branched from android 1.5 and carry a bug that always save the image in low res. you can lunch activity for camera and use the share function from camera to use the full sized image.
**编辑:HTC 设备并非如此。使用 HTC Sense ui 的 HTC(不是 nexus)从 android 1.5 分支出来,并带有一个总是以低分辨率保存图像的错误。您可以为相机进行午餐活动,并使用相机的共享功能来使用全尺寸图像。
回答by nabulaer
In your first attempt, it could be that the Camera app crashes when it reads your "output" extra, since it expects it to be a Uri, while you provide a String. The Camera app seems to read the extra flag after capturing the photo. You should just provide uri, and not uri.getPath(). Then, since you already know the URI to the photo, it will not be returned in the onResult call. You need to remember the URI in a member variable.
在您的第一次尝试中,可能是相机应用程序在读取您的额外“输出”时崩溃,因为它期望它是一个 Uri,而您提供一个字符串。相机应用程序似乎在拍摄照片后读取额外的标志。您应该只提供 uri,而不是 uri.getPath()。然后,由于您已经知道照片的 URI,它不会在 onResult 调用中返回。您需要记住成员变量中的 URI。
In the second attempt you will get a scaled down (50%) bitmap back. It is primarily intended for views. I think the full sized bitmap is too large for the memory budget of the application. This may be the reason for the downscale.
在第二次尝试中,您将获得缩小 (50%) 的位图。它主要用于视图。我认为全尺寸位图对于应用程序的内存预算来说太大了。这可能是降级的原因。
回答by Rene
I got the same Problem with the Emulator, I tried it on a real Phone an it worked, maybe it is because the Virtual Phone can't really take Picures.
我在模拟器上遇到了同样的问题,我在真正的手机上尝试过,它可以工作,也许是因为虚拟手机无法真正拍摄图片。