简体   繁体   English

CameraX 将图像保存到文件,FileNotFoundException:(权限被拒绝)

[英]CameraX Saving images to file, FileNotFoundException: (Permission Denied)

I'm working with Android Studio, writing in Java. I'm trying to write a piece of software that will take pictures from a camera based on an event.我正在与 Android Studio 合作,在 Java 中写作。我正在尝试编写一款软件,根据事件从相机中拍照。 So first steps first was to figure out the API. Camera is depreciated, so there's Camera2, but the latest is CameraX.所以第一步首先是找出 API。相机已折旧,所以有 Camera2,但最新的是 CameraX。 I've attempted to use both CameraX and Camera2, but for some reason I'm not saving any images.我尝试同时使用 CameraX 和 Camera2,但出于某种原因我没有保存任何图像。 I believe the capture works, but the issue is saving the files.我相信捕获有效,但问题是保存文件。 I don't know what's going on.我不知道发生了什么。

First lets start with permissions.首先让我们从权限开始。 Yes, I have set permissions for both the camera and external storage.是的,我已经为相机和外部存储设置了权限。

    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

  

So lets move on to the code itself.因此,让我们继续讨论代码本身。

I've never saved photos before, but I have worked with text files such as.txt and.csv files.我以前从未保存过照片,但我使用过文本文件,例如 .txt 和 .csv 文件。 Which I've been able to make work.我已经能够做到这一点。

Right now I do a simple button click to capture the image.现在我做了一个简单的按钮点击来捕捉图像。 Which is nothing more than an onclicklistener.这只不过是一个 onclicklistener。 Once I press the button this is what actions occur.一旦我按下按钮,这就是发生的动作。

                SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
                File file = new File(Environment.getDataDirectory(), mDateFormat.format(new Date())+ ".jpg");

                if(!file.exists())
                    file.mkdirs();

                ImageCapture.OutputFileOptions outputFileOptions = new ImageCapture.OutputFileOptions.Builder(file).build();
                imageCapture.takePicture(outputFileOptions, executor, new ImageCapture.OnImageSavedCallback () {
                    @Override
                    public void onImageSaved(@NonNull ImageCapture.OutputFileResults outputFileResults) {
                        Toast.makeText(MainActivity.this, "TEST", Toast.LENGTH_SHORT).show();

                        new Handler().post(new Runnable() {
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "Image Saved successfully", Toast.LENGTH_SHORT).show();
                            }
                        });
                    }
                    @Override
                    public void onError(@NonNull ImageCaptureException error) {
                        error.printStackTrace();
//                        Toast.makeText(MainActivity.this, "Image save FAILED!!!!", Toast.LENGTH_SHORT).show();
                    }
                });

when the app launches the first time, it asks for permission and I grant permission.当应用程序首次启动时,它会请求许可,然后我授予许可。 but looking at the run tab as part of the Android Studio ID, I get the following readout, when I press the capture button但是查看作为 Android Studio ID 一部分的运行选项卡,当我按下捕获按钮时,我得到以下读数

D/ImageCapture: Send image capture request [current, pending] = [0, 1]
D/CaptureSession: Issuing capture request.
W/example.camera: JNI critical lock held for 21.148ms on Thread[14,tid=10076,Runnable,Thread*=0xdc743000,peer=0x13184cf8,"Binder:10045_2"]
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
    Skip the tag entry since data format (ULONG) is unexpected for tag: GPSAltitudeRef
W/ExifInterface: Stop reading file since a wrong offset may cause an infinite loop: 0
    Stop reading file since a wrong offset may cause an infinite loop: 0
W/System.err: androidx.camera.core.ImageCaptureException: Failed to write or close the file
W/System.err:     at androidx.camera.core.ImageCapture$3.onError(ImageCapture.java:669)
        at androidx.camera.core.ImageSaver.lambda$postError$1$ImageSaver(ImageSaver.java:263)
        at androidx.camera.core.-$$Lambda$ImageSaver$eAp-cZyzsEk-LVLazzLE-ezQzwo.run(Unknown Source:8)
W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
    Caused by: java.io.FileNotFoundException: /data/20200728142756.jpg: open failed: EACCES (Permission denied)
        at libcore.io.IoBridge.open(IoBridge.java:496)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:235)
        at java.io.FileOutputStream.<init>(FileOutputStream.java:186)
        at androidx.camera.core.ImageSaver.run(ImageSaver.java:97)
        ... 3 more
W/System.err: Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
        at libcore.io.IoBridge.open(IoBridge.java:482)
        ... 6 more
W/example.camera: JNI critical lock held for 17.651ms on Thread[16,tid=10083,Runnable,Thread*=0xdc74bc00,peer=0x13184de8,"Binder:10045_4"]

I've searched around, and looked for different methods of saving the file, and I've had success with saving the image, sort of, when I use the camera2 api and save the file using outputstream我到处搜索,寻找不同的保存文件的方法,我已经成功地保存了图像,有点,当我使用 camera2 api 并使用 outputstream 保存文件时

When I use Camera2 it appears to save just fine, but I have no idea where it saves, I can't find it.当我使用 Camera2 时,它似乎保存得很好,但我不知道它保存在哪里,我找不到它。 I point this out, because it still appears to be a permission denied error as what I'm seeing is when I open up Device File Explorer its not letting me view /storage/emulator/ it just shows me我指出这一点,因为它似乎仍然是一个权限被拒绝的错误,因为我看到的是当我打开设备文件资源管理器时它不让我查看 /storage/emulator/ 它只是告诉我

ls: /storage/emulated/: Permission denied. 

在此处输入图像描述

all the examples I have found have assumed access with no issues to emulated.我发现的所有示例都假定可以访问,没有任何问题可以模拟。

Does anyone have any insight as to why I'm having permission denied errors?有没有人知道为什么我有权限被拒绝的错误?

UPDATE更新

So I still haven't solved the issue related to the failed mkdir() call.所以我仍然没有解决与失败的 mkdir() 调用相关的问题。 However, I did fix one issue, that could have been causing the issue.但是,我确实解决了一个可能导致问题的问题。 The means as to how I was creating the directory and the file itself wasn't correct.关于我如何创建目录和文件本身的方法不正确。

SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US);
File file = new File(getBatchDirectoryName(), mDateFormat.format(new Date())+ ".jpg");

public String getBatchDirectoryName() {

        String app_folder_path = "";
        app_folder_path = Environment.getExternalStorageDirectory() + "/images";
        File dir = new File(app_folder_path);
        if (!dir.exists() && !dir.mkdirs()) {
            Toast.makeText(MainActivity.this, "Trip", Toast.LENGTH_SHORT).show();
        }

        return app_folder_path;
    }

However, it still fails to create the directory.但是,它仍然无法创建目录。 Which still makes me come back to a permission issue.这仍然让我回到权限问题。

Environment.getExternalStorageDirectory() appears to be deprecated. Environment.getExternalStorageDirectory() 似乎已弃用。 Documentation appears to recommend using getExternalFilesDir(string) or MediaStore.文档似乎建议使用 getExternalFilesDir(string) 或 MediaStore。 However, I'm having issues finding sample use cases.但是,我在查找示例用例时遇到问题。 And I can't imagine, that while deprecated, it would just stop working at all.而且我无法想象,虽然已弃用,但它会完全停止工作。 Most devices on the market are not API 29 or higher.市场上的大多数设备都不是 API 29 或更高。

Based on help from @blackapps, I was able to make changes to my Manifest file to allow access to external storage.在@blackapps 的帮助下,我能够更改我的清单文件以允许访问外部存储。

More information can be found here更多信息可以在这里找到

Request Legacy External Storage 请求旧版外部存储

With @blackapps, and this thread on stackoverflow I was able to update my permissions to allow legacy access.使用@blackapps 和 stackoverflow 上的这个线程,我能够更新我的权限以允许旧版访问。

Because in Android Q they have disabled direct file access, they have added a work around to allow legacy support.因为在 Android Q 中他们禁用了直接文件访问,所以他们添加了一个变通方法以允许遗留支持。 This is, and as others have mentioned, only a temporary fix for the issue.正如其他人所提到的,这只是该问题的临时解决方案。 You will need to follow the new format for saving files going forward with Android R. In my situation, I am only developing a proof of concept and will not need to worry about future versions of Android.您将需要按照 Android R 的新格式保存文件。在我的情况下,我只是在开发概念验证,不需要担心 Android 的未来版本。

To make the temporary fix, do the following要进行临时修复,请执行以下操作

Add the following line添加以下行

android:requestLegacyExternalStorage="true">

inside your <application bracket on the manifest file.在清单文件的 <application 括号内。 Should look similar to this看起来应该与此类似

    <?xml version="1.0" encoding="utf-8"?>
...
    package="com.example.camerax">

...

    <application
        ...
        android:requestLegacyExternalStorage="true">
        <activity android:name=".MainActivity">
            <intent-filter>
                ...
            </intent-filter>
        </activity>
    </application>

remember this is not a long term fix, and will not work when a device is updated to Android R请记住,这不是长期修复,当设备更新到 Android R 时将不起作用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 FileNotFoundException(权限被拒绝) - FileNotFoundException (Permission Denied) 尝试将文件写入Android中的SD卡时,FileNotFoundException(权限被拒绝) - FileNotFoundException (permission denied) when trying to write file to sdcard in Android java.io.FileNotFoundException:/ mnt / sdcard / file(权限被拒绝) - java.io.FileNotFoundException: /mnt/sdcard/file (Permission denied) 在外部存储中保存文件时权限被拒绝 - Permission denied while Saving file in external storage OS X上的Java Applet-FileNotFoundException(权限被拒绝) - Java Applet on OS X - FileNotFoundException (Permission denied) FileNotFoundException:open failed:EACCES(权限被拒绝) - FileNotFoundException: open failed: EACCES (Permission denied) java.io.FileNotFoundException :(权限被拒绝) - java.io.FileNotFoundException: (Permission denied) java.io.FileNotFoundException:/storage/emulated/0/New file.txt:打开失败:EACCES(权限被拒绝) - java.io.FileNotFoundException: /storage/emulated/0/New file.txt: open failed: EACCES (Permission denied) java.io.FileNotFoundException :(我拒绝访问该文件时) - java.io.FileNotFoundException: (Access is denied) when i have permission to the file 文件在Java 1.5中有效,但在Java 7中无效(java.io.FileNotFoundException权限被拒绝) - File works in Java 1.5 but not in Java 7 (java.io.FileNotFoundException Permission Denied)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM