xamarin / Essentials

Xamarin.Essentials is no longer supported. Migrate your apps to .NET MAUI, which includes Maui.Essentials.
https://aka.ms/xamarin-upgrade
Other
1.52k stars 505 forks source link

[Bug] Storage permissions Android 13 api 33 #2041

Open ChrisDox opened 2 years ago

ChrisDox commented 2 years ago

Description

I have a strange thing when My TARGET ANDROID VERSION is Android 13.0 (API Level 33)

When i use CrossMedia plugin, i want to ask manual permissions to external storage When i do

await Permissions.RequestAsync<Permissions.StorageRead>(); OR
await Permissions.RequestAsync<Permissions.StorageWrite>();

--> NO displayAlert comes to ask permission and the result is always "Denied"

for other asking like Camera, the displayAlert comes normally and it's ok.

To test i use xamarin essential mediaPicker when i do var photo = await MediaPicker.CapturePhotoAsync();

First i have normal alert with "Allow ... to take pictures an record video" After that i have a PermissionException

StorageWrite permission was not granted: Denied
at Xamarin.Essentials.Permissions.EnsureGrantedAsync[TPermission] () [0x00066] in D:\a\_work\1\s\Xamarin.Essentials\Permissions\Permissions.shared.cs:29 
  at Xamarin.Essentials.MediaPicker.PlatformCaptureAsync (Xamarin.Essentials.MediaPickerOptions options, System.Boolean photo) [0x0007e] in D:\a\_work\1\s\Xamarin.Essentials\MediaPicker\MediaPicker.android.cs:59 

.... And NOT storage permission asking alert

WHEN My TARGET ANDROID VERSION is Android 12.1 (API Level 32) ALL WORKS FINE

In my manifest i have

    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.CAMERA" />
        .....
        <queries>
            <intent>
              <action android:name="android.media.action.IMAGE_CAPTURE" />
            </intent>
         </queries>

Expected Behavior

Alert with Storage authorization asking

Actual Behavior

PermissionException StorageWrite permission was not granted: Denied

Basic Information

RemcoDEV commented 2 years ago

This is the case for more type of permissions when targeting API 33.

ataparia commented 2 years ago

Having similar issue on our end. Can someone from the Xamarin team look in this please?

plebnz commented 2 years ago

Sounds like this could be sorted at same time as https://github.com/xamarin/Essentials/issues/2037

dartur123 commented 2 years ago

Also still experiencing this issue.

andycnguyen commented 2 years ago

We're encountering this issue as well

lazmeister commented 2 years ago

us as well

thomasgalliker commented 2 years ago

Same here. You can use following code to reproduce the problem.

public static async Task<bool> HasStorageReadPermissionsAsync()
{
    var permission = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
    // permission is "Denied" if we check for the very first time
    if (permission != PermissionStatus.Granted)
    {
        // The following call should display the permission dialog;
        // It works perfectly fine on <= API 28 but when I run it on API 33, it just returns "Denied"
        // similar to what ChrisDoc documented above.
        var requestStatus = await Permissions.RequestAsync<Permissions.StorageRead>();
        if (requestStatus == PermissionStatus.Granted)
        {
            return true;
        }
    }
    else
    {
        return true;
    }

    return false;
}
jamesnwarner commented 2 years ago

We're also encountering this issue. It appears to make the camera completely unusable on any device using Android 13 (API 33). Has anyone got a workaround for using the camera?

okdicom commented 2 years ago

Hi James,

I've been able to use the camera using the MediaPlugin (last beta version) of James Montemagno.

You can see the post here: https://github.com/jamesmontemagno/MediaPlugin/issues/946

Hope it helps.

El vie, 21 oct 2022 a las 11:15, James Warner @.***>) escribió:

We're also encountering this issue. It appears to make the camera completely unusable on any device using Android 13 (API 33). Has anyone got a workaround for using the camera?

— Reply to this email directly, view it on GitHub https://github.com/xamarin/Essentials/issues/2041#issuecomment-1286686479, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA2EYX44ZMQIAS5JM2PBF43WEJNKDANCNFSM6AAAAAAQG6GEL4 . You are receiving this because you are subscribed to this thread.Message ID: @.***>

--

Enrique Pereiro Arceredillo I.R.C. MED C.B. 652876023 www.okdicom.com

Este envío es confidencial y está destinado únicamente a la persona a la que ha sido enviado. Puede contener información privada y confidencial. Si usted no es el destinatario al que ha sido remitida, no puede copiarla, distribuirla ni emprender con ella ningún tipo de acción. Si cree que lo ha recibido por error, por favor, notifíquelo al remitente.

This transmission is confidential and intended solely for the person to whom it is addressed. It may contain privileged and confidential information. If you are not the intended recipient, you should not copy, distribute or take any action in reliance on it. If you believe that you have receive this transmission in error, please notify the sender.

jamesnwarner commented 2 years ago

To provide further context to the Xamarin team, since Android 11 (API level 30), the WRITE_EXTERNAL_STORAGE permission does not have any effect on the app's access to storage - https://developer.android.com/training/data-storage#permissions

It appears that on devices using Android 13, the popup dialog to request WRITE_EXTERNAL_STORAGE permission will no longer display. Regardless of whether the code requests it or not.

Therefore it is impossible for users using this version of Android to accept the permission. The fact that the MediaPicker.CapturePhotoAsync() ensures that this permission has been granted means that this method just doesn't work on Android 13.

The Expected Behaviour in the original bug should be that the camera just works, without requiring the WRITE_EXTERNAL_STORAGE permission. That part should be handled in the code if the developer chooses to write the file to storage.

brayden-marshall commented 2 years ago

We're seeing this issue as well.

I was able to use the workaround that okdicom suggested, but that's not ideal since it involves a separate package, and a beta version at that.

Goksly commented 2 years ago

Adding this to the Android manifest may help:

<queries>
  <intent>
    <action android:name="android.media.action.IMAGE_CAPTURE" />
  </intent>
</queries>

It's already in the person's manifest - so no it won't.

tylershelton810 commented 2 years ago

We are also experiencing issues with Android 13 permissions. Will try placing them in the manifest as some have suggested.

DS2107 commented 1 year ago

I have the same problem, I have given all the permissions, but the permission to use the files does not appear and I cannot request access to the files from the user.

Sebastian1989101 commented 1 year ago

Same issue here... a shame that something like this is not fixed asap...

it11111111 commented 1 year ago

We are also having the same issue here

dimonovdd commented 1 year ago

Hi, Can you try that plugin?

If the problem is not solved, create new issue in that repository. I'll try to fix it.

Don't forget to provide a sample project with this error and the reproduction steps.

aismaniotto commented 1 year ago

+1

softsan commented 1 year ago

Any updates on this or work around?

irongut commented 1 year ago

The Android camera will not work without asking for media permission. On Android 13 when targetting Android 13 the media permission is not asked for making it impossible to use the camera.

Google will require Android 13 as a minumum target version on 1st November 2023.

So unless this issue is fixed, Xamarin.Android and Xamarin.Forms will be End Of Life on 1st November 2023 no matter what date Microsoft claim.

grabnerM commented 1 year ago

I am not sure if this is necessarily a xamarin problem. We are facing the same problem. Before we switched to the xamarin.essentials permission request, we used to open the app settings. There the user had to grant the permission by himself. To come back to the problem, on my OnePlus 8T I cant grant the permissions in the settings. Basically there i cant find the storage permission.

EDIT: We are facing this issue in our file downloader. Up to Android 12 we could simply asked the user for permission to download files. (Therefor we added "READ_EXTERNAL_STORAGE" and "WRITE_EXTERNAL_STORAGE" to our AndroidManifest.)

After searching for a solution for this problem for a whole day, i found that Google wanted to increase the security of the apps for Android 13+. So now the user need to give you the permissions for images, videos and audio files seperatly. Unfortunatly Xamarin.Essentials has not gotten updated yet.

daesang commented 1 year ago

public static async Task AskForRequiredStoragePermission() { try { if (DeviceInfo.Platform == DevicePlatform.Android && DeviceInfo.Version.Major >= 13) { return true; }

            var status = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            if (status == PermissionStatus.Granted)
            {
                return true;
            }

            if (status == PermissionStatus.Denied && DeviceInfo.Platform == DevicePlatform.iOS)
            {
                // Prompt the user to turn on in settings
                // On iOS once a permission has been denied it may not be requested again from the application
                return false;
            }

            await Permissions.RequestAsync<Permissions.StorageRead>();
            status = await Permissions.CheckStatusAsync<Permissions.StorageRead>();
            if (status == PermissionStatus.Granted)
                return true;
        }
        catch (Exception ex)
        {
            //Something went wrong
        }
        return false;
    }
eamonnalphin commented 1 year ago

I'm still having this issue; asking for read & write permissions doesn't do anything. No popup, and the permission isn't even listed in the emulator permissions under the app.

Its-AliRaza03 commented 1 year ago

It's working fine after updating to beta version 6.0.1.

AnthonyWeirbach commented 1 year ago

image

https://developer.android.com/about/versions/13/behavior-changes-13#granular-media-permissions

I guess doing something like this? But I am not sure if this would work for write scenarios and I couldn't find any permissions for write for these new permissions.

AnthonyWeirbach commented 1 year ago

looks like there is an open pull request to fix this issue.... https://github.com/xamarin/Essentials/pull/2065

programatix commented 1 year ago

Hopefully the update will be released soon. Currently the only workaround is to target API 32.

giuseppenovielli commented 1 year ago

Please fix this issue! @jfversluis @jamesmontemagno

SHuygh commented 1 year ago

+1

NaagAlgates commented 1 year ago

I'm facing this same issue in my old code. As others suggested, the only option as of now is to target API 32.

Its-AliRaza03 commented 1 year ago

I'm facing this same issue in my old code. As others suggested, the only option as of now is to target API 32.

can you try the solution that I posted above. It's working fine for me.

NaagAlgates commented 1 year ago

I'm facing this same issue in my old code. As others suggested, the only option as of now is to target API 32.

can you try the solution that I posted above. It's working fine for me.

Can you please let me know which dependency I need to upgrade to 6.0.1?

Its-AliRaza03 commented 1 year ago

Can you please let me know which dependency I need to upgrade to 6.0.1?

Xam.Plugin.Media ( https://github.com/jamesmontemagno/MediaPlugin)

jfversluis commented 1 year ago

Could anyone verify that the fix in #2073 that we've just release is enough to cover this one as well?

AnthonyWeirbach commented 1 year ago

@jfversluis Unfortunately I am not in a position to test this right now. As my fix was just to roll back to target API 32. But, I looked over your Commit #2073 and this only fixes the PlatformCaptureAsync() in my case and as others also mentioned in this thread, one of the places that I was experiencing this issue was when I was calling... await Permissions.RequestAsync<Permissions.StorageWrite>(); so the fix in #2073 would not fix the issues out there that are calling Permissions.RequestAsync. Would it be possible to make that same change at a lower level such as within RequestAsync() or is the expected fix for RequestAsync() is that we write in to our code the if condition that is included in your fix for PlatformCaptureAsync()? // StorageWrite no longer exists starting from Android API 33 if (!Platform.HasApiLevel(33))

alexkivikoski commented 1 year ago

Any estimates on whether this is something that will be fixed (this comment might suggest it's not) and on the schedule?

This is causing issues for our customers and we are evaluating our options.

TranTrieuLamQuynh commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

TB-SWG commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

TranTrieuLamQuynh commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

I added "uses-permission android:name="android.permission.READ_MEDIA_IMAGES" into manifest but on device Android 13 cannot open camera. I using MediaPicker.CapturePhotoAsync() Exception: StorageWrite permission was not granted: Denied

TB-SWG commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

I added "uses-permission android:name="android.permission.READ_MEDIA_IMAGES" into manifest but on device Android 13 cannot open camera. I using MediaPicker.CapturePhotoAsync() Exception: StorageWrite permission was not granted: Denied

Make sure you upgraded to Essentials 1.7.5

jfversluis commented 1 year ago

@TB-SWG That sounds like you made it work with the latest version then? Where in the docs is this permission missing?

grabnerM commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

    <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

I added "uses-permission android:name="android.permission.READ_MEDIA_IMAGES" into manifest but on device Android 13 cannot open camera. I using MediaPicker.CapturePhotoAsync() Exception: StorageWrite permission was not granted: Denied

https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=android For us, this worked fine!

TB-SWG commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

I added "uses-permission android:name="android.permission.READ_MEDIA_IMAGES" into manifest but on device Android 13 cannot open camera. I using MediaPicker.CapturePhotoAsync() Exception: StorageWrite permission was not granted: Denied

https://learn.microsoft.com/en-us/xamarin/essentials/media-picker?tabs=android For us, this worked fine!

That is the correct doc link. However note the following in Android 13 https://developer.android.com/about/versions/13/behavior-changes-13 READ/WRITE_EXTERNAL_STORAGE seem to have been deprecated so the documentation needs an update.

sung-insightly commented 1 year ago

1.7.5 fixes it on Android 13 for us, but now testing on an Android12 device fails to work. This fix https://github.com/xamarin/Essentials/blob/1.7.5/Xamarin.Essentials/MediaPicker/MediaPicker.android.cs#L61 needs to actually be checking against api32, not api33.

TranTrieuLamQuynh commented 1 year ago

Has anyone been able to use MediaPicker.CapturePhotoAsync with Essentials 1.7.5 and API 33 on Android 13?

Yes. Changes I needed in manifest

  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />

That permission is missing from documentation and is needed for Android 13 (WriteExternalStorage beforehand)

I added "uses-permission android:name="android.permission.READ_MEDIA_IMAGES" into manifest but on device Android 13 cannot open camera. I using MediaPicker.CapturePhotoAsync() Exception: StorageWrite permission was not granted: Denied

Make sure you upgraded to Essentials 1.7.5

I'm wrong. I not upgrade to Essentials 1.7.5 in share project. But I have a question. On Android 13, If I want to select the image, what permission do I need to request in Essentials.Permissions?

hercul1017 commented 1 year ago

It didn't work for me. I still get "can't connect to camera." error. Am I missing anything?

I downloaded @jfversluis media picker sample app https://github.com/jfversluis/XFEMediaPickerSample and updated all the libraries to the latest. So that I have Xamarin.Essentials version 1.7.5, Xamarin Forms 5.0.0.2545, NETStandard lib 2.0.3. Changed the manifest file like below:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.CAMERA" /> `

</queries>`

I also have android:targetSdkVersion="33" and compile using Android 13.0.

When I use Android pixel 5 API 33 emulator, I got the error.

If the sample app updated and working on API 33, that would be very helpful.

Thanks.

alexkivikoski commented 1 year ago

Has anybody got this working?

gjhdigital commented 1 year ago

same problem here.

Pastajello commented 1 year ago

@gjhdigital @alexkivikoski

Ok so listen here, how about a little trick here: Since on API 33 the WRITE_MEDIA_STORAGE is useless the OS is ignoring it-> setting the permission status as denied. If we only have to internally trick the Essentials to think it is granted it is not THAT hard, is it? There is a place to tell Essentials what is the status of requested permissions. We just have to tell some lies.

Of course you need to remember that if there are multiple permissions in the array you have to replace only the value for the WRITE_MEDIA_STORAGE. AND check if we are on API 33+, before I think the permission is doing something, things will get messy otherwise I guess. But otherwise its working. ;) Just tested. (really this hack took me like 5minutes to think of)

      `public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {

        if (permissions.ToList().Where(x => x == "WRITE_MEDIA_STORAGE") != null)
        {
            var grants= new Permission[] { Permission.Granted };
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grants);
        }
        else
        {
            Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
        }

        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }`
gjhdigital commented 1 year ago

that fixed it for me! thank you!