Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"java.io.FileNotFoundException: Permission denied" in Android Internal Cache Dir

I am trying to take a picture and save it to the application's internal cache as it is going to be deleted as soon as it is uploaded. I am using the following code to create the file:

public static File createInternalCacheImageFile(Context context, String imageFileName) throws IOException {
        return File.createTempFile(
                imageFileName,
                context.getString(R.string.image_extension),
                context.getCacheDir()
        );
    }

Checking with a file manager with root permissions shows that the file is created fine. I then use the following code to launch the camera intent, which would normally save the image to the file I created:

takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(imageFile));
activity.startActivityForResult(takePictureIntent, REQUEST_CODE_IMAGE_CAPTURE);

The camera activity is shown and after accepting the picture, the result of the activity is 0. When looking at the logcat the following is shown:

07-21 13:19:51.093  12889-12889/? E/CAM_StateSavePic﹕ exception while saving result to URI: Optional.of(file:///data/data/org.serengetitracker.androidapp/cache/image_random_205854910-2018234447.jpg)
    java.io.FileNotFoundException: Permission denied
            at android.os.Parcel.openFileDescriptor(Native Method)
            at android.os.ParcelFileDescriptor.openInternal(ParcelFileDescriptor.java:253)
            at android.os.ParcelFileDescriptor.open(ParcelFileDescriptor.java:199)
            at android.content.ContentResolver.openAssetFileDescriptor(ContentResolver.java:916)
            at android.content.ContentResolver.openOutputStream(ContentResolver.java:686)
            at android.content.ContentResolver.openOutputStream(ContentResolver.java:662)
            at com.android.camera.captureintent.state.StateSavingPicture.onEnter(StateSavingPicture.java:84)
            at com.android.camera.captureintent.stateful.StateMachineImpl.jumpToState(StateMachineImpl.java:62)
            at com.android.camera.captureintent.stateful.StateMachineImpl.processEvent(StateMachineImpl.java:110)
            at com.android.camera.captureintent.state.StateOpeningCamera$9.onClick(StateOpeningCamera.java:307)
            at android.view.View.performClick(View.java:4780)
            at android.view.View$PerformClick.run(View.java:19866)
            at android.os.Handler.handleCallback(Handler.java:739)
            at android.os.Handler.dispatchMessage(Handler.java:95)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5254)
            at java.lang.reflect.Method.invoke(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:372)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)

Why am I not allowed to write an image to the application's internal cache directory?

Note: I do have the android.permission.WRITE_EXTERNAL_STORAGE permissions in my application, although this shouldn't matter as I'm not dealing with the external storage.

like image 311
Vlad Schnakovszki Avatar asked Oct 27 '25 09:10

Vlad Schnakovszki


2 Answers

The camera activity runs in a different app, which does not have access to your app's internal cache directory. You must use an external directory or let the camera app choose the directory itself - and then query that path (another topic) to be able to copy it to your cache directory.

like image 88
l33t Avatar answered Oct 29 '25 00:10

l33t


This is possible without the CAMERA and WRITE_EXTERNAL_STORAGE permissions.

You can create a temporary in your app's cache directory, and give other apps access to it. That makes the file writeable by the camera app:

File tempFile = File.createTempFile("photo", ".jpg", context.getCacheDir());
tempFile.setWritable(true, false);

Now you just need to pass this file as the output file for the camera intent:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mTempFile));  // pass temp file
startActivityForResult(intent, REQUEST_CODE_CAMERA);

Note: the file Uri won't be passed to you in the Activity result, you'll have to keep a reference to the tempFile and retrieve it from there.

like image 31
Phazor Avatar answered Oct 28 '25 23:10

Phazor



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!