相机意图不保存照片

发布于 2024-12-09 06:53:06 字数 405 浏览 1 评论 0原文

我之前曾成功使用过此代码片段,但文件指向 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 时,照片似乎从未保存。这是缓存目录和图像捕获的限制吗?

I successfully have used this code snippet before, but with the file pointing to somewhere on the SD card.

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);

However when I use getCacheDir instead of a loc on the SD card it seems the photo is never saved. Is this a limitation of cache dir and image capture?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

混浊又暗下来 2024-12-16 06:53:06

从技术上讲,这是因为使用相机应用程序捕获图像时不支持写入内部存储。事实上,您可能会注意到 logcat 中打印出一条异常,指出不支持写入内部存储。然而,这不起作用的真正原因是,默认情况下,您正在创建一个应用程序包私有的文件,而另一个应用程序(即相机应用程序)无法访问该文件位置,因为它没有权限这样做。外部存储是文件系统中唯一可全局访问的部分。

解决方法是创建具有全局 (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 方法本身会在根“文件”目录中创建文件,因此您可以放置​​文件的位置也受到限制,并且您无法将其重定向到缓存目录。

华泰

Technically, this is because writing to internal storage is not supported when using the Camera application to capture an image. In fact, you may notice an exception printed in logcat stating Writing to internal storage is not supported. However, the real reason this doesn't work is because by default you are creating a file that is private to your application package and another application (i.e. the Camera app) can't access that file location because it doesn't have permission to do so. External storage is the only globally accessibly portion of the filesystem.

The workaround is for you to create the file with global (WORLD_WRITEABLE) permissions. Typically, this allows the Camera app to access the file via the passed Uri. There aren't really methods to do this directly on File, so you have to create the file using the methods available in Context and then grab a handle to it afterward:

//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");

This also sort of limits where you can place the file since the Context methods inherently create files in the root "files" directory, and you can't redirect that to the cache directory.

HTH

聆听风音 2024-12-16 06:53:06

我找到的最佳解决方案是:FileProvider(需要 support-library-v4)
它使用内部存储!
https://developer.android.com/reference/android/support /v4/content/FileProvider.html

  1. 在应用程序元素的 Manifest 中定义您的 FileProvider:

    <前><代码><提供商
    android:name="android.support.v4.content.FileProvider"
    android:authorities="your.package.name.fileprovider"
    安卓:导出=“假”
    android:grantUriPermissions="true" >
    <元数据
    android:name="android.support.FILE_PROVIDER_PATHS"
    android:resource="@xml/image_path" />

  2. 如果需要,将相机功能添加到 AndroidManifest.xml 的根元素:

    
    
  3. 在 res/xml/image_path.xml 中定义图像路径:

    <路径 xmlns:android="http://schemas.android.com/apk/res/android">
    <文件路径名称=“captured_image”路径=“您的/路径/”/>
    
    
  4. Java:

    private static final int IMAGE_REQUEST_CODE = 1;
    // 您的权限,必须与清单文件中的相同 
    私人静态最终字符串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);
    }

Best solution I found is: FileProvider (needs support-library-v4)
It uses the internal storage!
https://developer.android.com/reference/android/support/v4/content/FileProvider.html

  1. Define your FileProvider in Manifest in Application element:

    <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. Add camera feature to AndroidManifest.xml's root element if mandatory:

    <uses-feature android:name="android.hardware.camera"
    android:required="true" />
    
  3. Define your image paths in for example 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 capture intent:

    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);
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文