Android app: Can't save photo. Camera doesn't have permission to save to this location
Asked Answered
S

3

9

I have a user who is not able to use the camera in my Android app even though she seems to have all the right permissions.

She is using a Google Pixel 6 Pro, Android 12 Build/SD1A.210817.037.

She has deleted and reinstalled the app. She has deleted storage and cache associated with the app. She is able to use the camera for other apps. She is using the default camera app.

No one else has complained about this issue, but she is using a recent build update so maybe she's just the first to see it and tell me.

The popup error message says:

Can't save photo. Camera doesn't have permission to save to this location.

In her Settings app, for App Permissions:

  • Camera
  • Files and Media
  • "No permissions denied"

In her Settings app, for all permissions, :

  • Camera: Take pictures and video
  • Files and Media: Read the contents of your shared media, Modify or delete the contents of your shared media

The app permissions:

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

<uses-feature
    android:name="android.hardware.camera"
    android:required="false" />
<uses-feature
    android:name="android.hardware.camera.autofocus"
    android:required="false" />

The app uses a webview and launches the camera from a standard HTML form. This is standard and automatically gives the user the choice of using the camera or file. The image is then normally sent to my server via the form and saved there.

<form action="upload/" method="post" enctype="multipart/form-data" >
      <input type="file" accept="image/*" name="image">
      <input type="submit">
</form>

The user is able to upload an image if she chooses a file, but not if she chooses the camera option. I'm not sure if the error message pops up before or after taking a photo with her camera.

App code:

private int MY_PERMISSIONS_REQUEST_CAMERA = 1;

public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
        uriArrayCallback = filePathCallback;

        if ( (ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED
                        || ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                        || ActivityCompat.checkSelfPermission(getActivity(), android.Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED
                )) {

            requestPermissions(new String[]{android.Manifest.permission.CAMERA,
                            android.Manifest.permission.READ_EXTERNAL_STORAGE,
                            android.Manifest.permission.WRITE_EXTERNAL_STORAGE},
                    MY_PERMISSIONS_REQUEST_CAMERA);
        } else {
            // has permissions
            openFileChooserInternal(NEW_FILECHOOSER_REQUEST_CODE);
        }

        return true;
    }
        
 public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        if (requestCode == MY_PERMISSIONS_REQUEST_CAMERA) {
            boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
            boolean readExternalAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
            boolean writeExternalAccepted = grantResults[2] == PackageManager.PERMISSION_GRANTED;
            if (cameraAccepted && readExternalAccepted && writeExternalAccepted) {
                openFileChooserInternal(NEW_FILECHOOSER_REQUEST_CODE);
            } else {
            }
        }
    }
Stapes answered 12/12, 2021 at 17:48 Comment(6)
Your minimal reproducible example does not show where you are taking the photo and displaying that message.Preempt
Sort of hard to comment without more context. When you launch the camera intent (assuming that is how you interface with the camera) what URI do you pass it? One your app provides access to or one in external/public storage?Firstly
I added the HTML form code that launches the camera.Stapes
@Stapes I'm facing the exact same issue, did you find a solution?Bili
cameraLauncher.launch needs a valid UriCoppery
I am facing the same issue, Has a solution been found? @StapesRandallrandan
R
1

I ran into the same issue, I used MediaStorage for the extra in my intent. Here is an example:

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.DISPLAY_NAME, imageFileName);
values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");
values.put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES);
        
Uri uri = cr.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
        
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
Rhoda answered 25/5, 2022 at 6:23 Comment(0)
I
1

I faced this problem in pixel 7. Solved it using provider in manifest.

Define filepaths.xml in your res/xml/filepaths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths>
 <external-cache-path
     name="images"
     path="." />
</

In your manifest,

    <application>
        <activity
             />
        <provider
            android:name="androidx.core.content.FileProvider"
            android:authorities="package.fileprovider"
            android:grantUriPermissions="true"
            android:exported="false">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/filepaths" />
        </provider>
    </application>

Now use It like this

FileProvider.getUriForFile(
  context,             
  "package.fileprovider",
  createTempFile(context)
)

         fun createTempFile(context: Context): File {
            return File.createTempFile(
                System.currentTimeMillis().toString(),
                ".jpg",
                context.externalCacheDir
            )
        }
Insubordinate answered 27/3, 2023 at 6:21 Comment(0)
R
0

It's a bug specific to Pixel devices: https://issuetracker.google.com/issues/242767872?pli=1

As usual with Google, no resolution

Status: Won't Fix (Infeasible)

We are closing this issue since we didn't receive a response. If you are still facing this problem, please open a new issue and add the relevant information along with reference to this issue.

Raconteur answered 17/3, 2023 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.