【问题标题】:Android: How to save the camera result to a private fileAndroid:如何将相机结果保存到私人文件
【发布时间】:2013-11-18 21:56:25
【问题描述】:

我正在尝试从相机中获取图像并将其直接保存到我的应用程序的私有文件目录中。出于安全考虑,该图像不应在任何时候公开访问。

通常,您授予对私有文件的临时访问权限的方式是使用 ContentProvider 并在 Intent 中设置 GRANT_WRITE_URI_PERMISSION 标志。按照FileProvider 中的文档,我做了以下事情:

AndroidManfiest.xml

<manifest> 
    ...
    <application>
        ...
        <provider
            android:authorities="com.my.domain"
            android:name="android.support.v4.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths" />
        </provider>
        ...

res/xml/file_paths.xml

<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <files-path name="my_images" path="images/"/>
</paths>

当启动相机活动时,我从一个活动中执行以下操作:

File imageFile = getInternalImageFile();
Uri captureUri = FileProvider.getUriForFile(this, "com.my.domain", imageFile);

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);

// grant temporary access to the file
intent.setData(captureUri);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);

// tell the camera where to save the file
intent.putExtra(MediaStore.EXTRA_OUTPUT, captureUri);

startActivityForResult(intent, IMAGE_CAPTURE_REQUEST_CODE);

然而,这会导致相机应用程序立即返回而无需执行任何操作。我怀疑是因为它不希望有任何意图数据集 (Intent.setData())。

上述策略效果不佳。那么,如何安全地将摄像头拍摄的图像直接保存到应用的私有文件目录中呢?

【问题讨论】:

  • 问题是授予对私有文件的访问权只有在应用程序实际使用它时才有效。在你的情况下,我会保存在任何地方,然后将其移动到私人存储中。
  • @njzk2 这实际上是我的应用程序目前所做的,但确定在任何时间段内将文件保存到外部存储(或任何可公开访问的内容)都存在安全风险。因此需要将其直接保存到内部存储中。
  • 您可以随时在您的应用中重新实现相机活动。

标签: android android-camera-intent


【解决方案1】:

我有同样的问题,但我使用 clipData 解决了它。

Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setClipData(ClipData.newRawUri(null, contentUri));
intent.putExtra(MediaStore.EXTRA_OUTPUT, contentUri);

http://developer.android.com/reference/android/content/Intent.html#setClipData(android.content.ClipData)

intent 中的 ClipData 不用于 Intent 匹配或其他此类操作。从语义上讲,它就像 extras,用于通过 Intent 传输附加数据。将其用于数据的附加功能的主要特点是 FLAG_GRANT_READ_URI_PERMISSION 和 FLAG_GRANT_WRITE_URI_PERMISSION 将对剪辑数据中包含的任何 URI 项进行操作。这很有用,尤其是在您要传输包含多个内容的 Intent 时:接收者可能没有访问内容提供者的全局权限的 URI。

希望对你有所帮助。

Pd:对不起我的英语。 :)

【讨论】:

  • 嗨,我在设置 contentURI 时遇到了困难,它是否类似于问题中的 captureUri?一些关于定义 contectURI 的代码真的会很有帮助。
  • 这是一个很好的答案。我已经搜索了几个小时,但没有看到任何提到 setClipData() 的文档或示例。没有它,我总是得到一个 SecurityException (“Permission Denial:opening provider...”)。我仍然需要弄清楚如何访问通过我的相机存储的文件,但至少看起来它已经存储在 somewhere ;)
【解决方案2】:

那么,如何安全地将从相机拍摄的图像直接保存到我的应用的私有文件目录中?

自己拍照,使用android.hardware.Camera。无法保证用户将拥有一个知道如何将数据保存到content://Uri 路径的相机应用程序。他们应该支持他们,但并非所有人都这样做。例如,截至 2016 年 6 月,Google 相机应用程序不支持 content:// Uri for ACTION_VIDEO_CAPTURE

【讨论】:

  • 再次阅读 javadoc,EXTRA_OUTPUT 需要一个内容 Uri。
猜你喜欢
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 2019-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多