user984003
user984003

Reputation: 29557

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

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:

In her Settings app, for all permissions, :

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 {
            }
        }
    }

Upvotes: 9

Views: 3517

Answers (3)

Shaon
Shaon

Reputation: 2724

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

Upvotes: 1

0101100101
0101100101

Reputation: 5911

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.

Upvotes: 0

Daniel Lutton
Daniel Lutton

Reputation: 241

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

Upvotes: 1

Related Questions