相机意图不保存照片
Posted
技术标签:
【中文标题】相机意图不保存照片【英文标题】:Camera Intent not saving photo 【发布时间】:2011-12-04 22:39:21 【问题描述】:我之前成功使用过这个代码 sn-p,但文件指向 SD 卡上的某个位置。
final File temp = new File(getCacheDir(), "temp.jpg");
temp.delete();
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(temp));
startActivityForResult(intent, CONFIG.Intents.Actions.SELECT_CAMERA_PHOTO);
但是,当我使用 getCacheDir 而不是 SD 卡上的 loc 时,似乎永远不会保存照片。这是缓存目录和图像捕获的限制吗?
【问题讨论】:
【参考方案1】:从技术上讲,这是因为在使用相机应用程序捕获图像时不支持写入内部存储。事实上,您可能会注意到 logcat 中打印了一个异常,指出 Writing to internal storage is not supported
。但是,这不起作用的真正原因是,默认情况下,您正在创建一个专用于您的应用程序包的文件,而另一个应用程序(即相机应用程序)无法访问该文件位置,因为它无权访问这样做。外部存储是文件系统中唯一可全局访问的部分。
解决方法是让您创建具有全局 (WORLD_WRITEABLE) 权限的文件。通常,这允许相机应用程序通过传递的 Uri 访问文件。没有真正的方法可以直接在File
上执行此操作,因此您必须使用Context
中可用的方法创建文件,然后再获取它的句柄:
//Remove if exists, the file MUST be created using the lines below
File f = new File(getFilesDir(), "Captured.jpg");
f.delete();
//Create new file
FileOutputStream fos = openFileOutput("Captured.jpg", Context.MODE_WORLD_WRITEABLE);
fos.close();
//Get reference to the file
File f = new File(getFilesDir(), "Captured.jpg");
这也限制了您可以放置文件的位置,因为Context
方法固有地在根“文件”目录中创建文件,并且您无法将其重定向到缓存目录。
HTH
【讨论】:
太好了,我有预感这就是问题所在。我想我只是打算再次暂时将照片保存到 SD 卡中,但我会将其添加到我的工具包中 :) 关于如何解决 Context.MODE_WORLD_WRITEABLE 弃用的任何想法? 来自here: MODE_WORLD_WRITEABLE 在 API 级别 17 中已弃用此常量。创建全局可写文件非常危险,并且可能会导致应用程序出现安全漏洞。强烈建议不要这样做; 在过去的 5 年里事情确实发生了变化 :) ContentProvider(例如 FileProvider)是解决这个问题的最佳解决方案。【参考方案2】:我找到的最佳解决方案是:FileProvider(需要 support-library-v4) 它使用内部存储! https://developer.android.com/reference/android/support/v4/content/FileProvider.html
在应用程序元素的清单中定义您的 FileProvider:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="your.package.name.fileprovider"
android:exported="false"
android:grantUriPermissions="true" >
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/image_path" />
</provider>
如果必须,将相机功能添加到 AndroidManifest.xml 的根元素:
<uses-feature android:name="android.hardware.camera"
android:required="true" />
在 res/xml/image_path.xml 中定义您的图像路径:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="captured_image" path="your/path/"/>
</paths>
Java:
private static final int IMAGE_REQUEST_CODE = 1;
// your authority, must be the same as in your manifest file
private static final String CAPTURE_IMAGE_FILE_PROVIDER = "your.package.name.fileprovider";
4.1 捕获意图:
File path = new File(activity.getFilesDir(), "your/path");
if (!path.exists()) path.mkdirs();
File image = new File(path, "image.jpg");
Uri imageUri = FileProvider.getUriForFile(activity, CAPTURE_IMAGE_FILE_PROVIDER, image);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, IMAGE_REQUEST_CODE);
4.2 onActivityResult():
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent)
if (requestCode == IMAGE_REQUEST_CODE)
if (resultCode == Activity.RESULT_OK)
File path = new File(getFilesDir(), "your/path");
if (!path.exists()) path.mkdirs();
File imageFile = new File(path, "image.jpg");
// use imageFile to open your image
super.onActivityResult(requestCode, resultCode, intent);
【讨论】:
同意 FileProvide 是使用相机意图在内部保存图像的最佳解决方案。 您确定需要 FileProvide 的READ_EXTERNAL_STORAGE
权限吗?我不相信这是正确的。
马丁,我认为你是对的。我会改变我的答案。
@Harry 如果我想捕捉多张图像怎么办?我们必须在 xml 中的 capture_image 中给出硬编码的图像名称?
我在 android 4.4 kitkat 上尝试了上述技术,但相机应用程序无法创建文件。有没有人运气好一点?以上是关于相机意图不保存照片的主要内容,如果未能解决你的问题,请参考以下文章