• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps Secret camera, fails to save or I can't find files

Nightpoison

Newbie
Aug 29, 2019
11
1
testing on Pixel 3a, Android API 29 +

So I'm writing an application that needs to take a picture based on an event, other than a user pressing a camera button. No big deal. I just set the event rather than an onclicklistner, right. Sure. The first problem was most of the information out there revolved around intent and calling the basic camera application. So I had to dig into the camera API's. Camera, Camera2, CameraX. Well I'm now looking at Camera2 and CameraX. CameraX seems a lot simpler.

Anyway moving on. I have pulled two different examples that I'm going to strip down to look at just the capture functionality. Both examples have a preview screen, and a button. I'm going to throw the preview screen out and create a take picture event.

The problem I'm having is one application fails to save the picture while the other application I can't find where the pictures are being saved. I believe there is a permission issue that I'm having trouble with.

BOTH
with both applications I have permissions set in my manifest file.

Code:
<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"/>

I also check for permission on both API's for both camera and storage access during onCreate()

Java:
if(allPermissionsGranted()){
    Toast.makeText(MainActivity.this, "Granted", Toast.LENGTH_SHORT).show();
    startCamera(); //start camera if permission has been granted by user
} else{
    Toast.makeText(MainActivity.this, "Denied", Toast.LENGTH_SHORT).show();
    ActivityCompat.requestPermissions(this, REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS);
}

private boolean allPermissionsGranted(){

    for(String permission : REQUIRED_PERMISSIONS){
        if(ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED){
            return false;
        }
    }
    return true;
}

CameraX

Here is were things differ. I create the file the image is to be saved in this way.

Java:
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;

This is where I believe the root issue is for some reason I think its a permission issue. When ever I check if the directory exists and then create the directory if it doesn't exist, and try's to create the directory it always fails. I always see the Toast message. I took a look at the stacktrace and I see the following errors.

Code:
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)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err:     at java.lang.Thread.run(Thread.java:919)
W/System.err: Caused by: java.io.FileNotFoundException: /storage/emulated/0/images/20200730085024.jpg: open failed: ENOENT (No such file or directory)
        at libcore.io.IoBridge.open(IoBridge.java:496)
W/System.err:     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: ENOENT (No such file or directory)
        at libcore.io.Linux.open(Native Method)
W/System.err:     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
D/EGL_emulation: eglMakeCurrent: 0xe09de0c0: ver 3 0 (tinfo 0xe0a8fb90)
W/example.camera: JNI critical lock held for 18.377ms on Thread[15,tid=8749,Runnable,Thread*=0xd531e600,peer=0x13c40348,"Binder:8690_3"]
W/example.camera: JNI critical lock held for 19.631ms on Thread[15,tid=8749,Runnable,Thread*=0xd531e600,peer=0x13c40348,"Binder:8690_3"]

It appears that it can't find the file/directory. Based on passed experience with .csv files, and the reading I should be able to look at the device via the Device File Explorer. However when I open it and look at the /storage/emulated/ folder it just gives me a permission denied message.

upload_2020-7-30_9-13-45.png


This is the case even if I'm running an emulator or the app directly on the device.

Camera2
The application that I'm running the Camera2 API appears to save the image, but I cant find the images. I get the same access issue from the screen shot above, and the images are stored in this location. So I feel like its a permission issue still.

For this application I don't attempt to create any new directories.

Java:
file = new File(Environment.getExternalStorageDirectory()+"/"+UUID.randomUUID().toString()+".jpg");

The problem with this is, in the final code, I will be creating a new folder for each time the application is run, as each time the app is run will be its own log of files. There will be photos and data files that will need to be organized by instance.

But with that said, even if I port this way of saving data to the device, as it appears to save the images, doesn't fail, I still don't have access to the images.

Any insight?
 
  • Like
Reactions: Tharpebb63
Since youre already running Q or android R, theres something called "Scoped storage" which isolates your process to only access certain directories... Iirc you had to set some specific flags to allow access outside of those.

In particular you wanna look at:
https://developer.android.com/reference/android/R.attr#requestLegacyExternalStorage

Keep in mind that with android R this flag is ignored and youre forced to use your app /data/data dir and some other ones...

Also see this as reference:
https://developer.android.com/preview/privacy/storage
 
Upvote 0
Based on help from @Thagorsson, I was able to make changes to my Manifest file to allow access to external storage.

I was able to update my permissions to allow legacy access.

Because in Android Q they have disabled direct file access, they have added a work around to allow legacy support. 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, at this time.

To make the temporary fix, do the following

set up your manifest file similar to this.

Code:
android:requestLegacyExternalStorage="true">
inside your <application bracket on the manifest file. 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
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones