【问题标题】: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 时,似乎永远不会保存照片。这是缓存目录和图像捕获的限制吗?

【问题讨论】:

    标签: android android-camera-intent


    【解决方案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

    1. 在应用程序元素的清单中定义您的 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>
      
    2. 如果必须,将相机功能添加到 AndroidManifest.xml 的根元素:

      <uses-feature android:name="android.hardware.camera"
      android:required="true" />
      
    3. 在 res/xml/image_path.xml 中定义您的图像路径:

      <paths xmlns:android="http://schemas.android.com/apk/res/android">
      <files-path name="captured_image" path="your/path/"/>
      </paths>
      
    4. 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 上尝试了上述技术,但相机应用程序无法创建文件。有没有人运气好一点?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多