3

I'm currently writing a Xamarin Forms app which requires use of the camera, in the code below I am requesting the permission using the Xamarin Essentials Permissions which comes back as "Granted"; immediately following that I am requesting use of the camera to take a photo, which throws the following error.

ex = {Plugin.Media.Abstractions.MediaPermissionException: Camera permission(s) are required.

The permission code

public static async Task<bool> GetPermission<TPermission>() where TPermission : BasePermission, new()
    {
        var hasPermission = await Permissions.CheckStatusAsync<TPermission>();

        if (hasPermission == PermissionStatus.Granted)
            return true;
        else if (hasPermission == PermissionStatus.Disabled)
            return false;

        var result = await Permissions.RequestAsync<TPermission>();
        if (result != PermissionStatus.Granted)
            return false;

        return true;
    }

The photo manager code

if(!await PermissionHelpers.GetPermission<Permissions.Camera>())
        {
            await new ErrorAlert().Show("App can't take a picture without permission to use the camera");
            return string.Empty;
        }

        var photo = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
        {
            PhotoSize = PhotoSize.Small,
            SaveToAlbum = false
        });

As previously said, the GetPermission method returns true, but still the error is thrown.

I'm currently running this on Android. My AndroidManifest.xml has these permission in it.

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

I have now made a sample project to showcase my issue GitHub Repo for the issue

Ben Price
  • 61
  • 1
  • 9

4 Answers4

3

thank you for all of your time gone into helping me to resolve this issue. It turned out that if you are using Xamarin essentials version 1.5.0 you need to install the CurrentActivity NuGet plugin to your android project.

Or, a better solution is update to 1.5.1 which resolves the issue entirely.

Ben Price
  • 61
  • 1
  • 9
1

don't forget

Android

protected override void OnCreate(Bundle savedInstanceState) {
    //...
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
    //...

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
    Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);

    base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}

Documentation

JeePakaJP
  • 830
  • 7
  • 21
1

First of all, I notice you use Xam.Plugin.Media, this plugin need WRITE_EXTERNAL_STORAGE, READ_EXTERNAL_STORAGE and android.permission.CAMERA in Android, You should request these permission at runtime.

You can use following code in the MainActivity

  public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
    protected override void OnCreate(Bundle savedInstanceState)
    {
        TabLayoutResource = Resource.Layout.Tabbar;
        ToolbarResource = Resource.Layout.Toolbar;

        base.OnCreate(savedInstanceState);

        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
        LoadApplication(new App());

        if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) != (int)Permission.Granted)
        {
            RequestPermissions(new string[] { Manifest.Permission.Camera, Manifest.Permission.WriteExternalStorage, Manifest.Permission.ReadExternalStorage }, 0);
        }

    } 

Here is running gif.

enter image description here

Update

If you use this CrossMedia, you need grant Storage and Camera permission.Please open your PhotoManager.cs Add the request storage code like following code.

     public class PhotoManager
{
    public async Task<string> TakeNewPhoto()
    {
        try
        {
            if (!CrossMedia.IsSupported || !CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
            {
                return string.Empty;
            }

            if (!await PermissionHelpers.GetPermission<Permissions.Camera>())
            {
                return string.Empty;
            }
            //=====================================add above line==================================================

            if (!await PermissionHelpers.GetPermission<Permissions.StorageWrite>())
            {
                return string.Empty;
            }

            var photo = await CrossMedia.Current.TakePhotoAsync(new StoreCameraMediaOptions
            {
                PhotoSize = PhotoSize.Small,
                SaveToAlbum = false
            });

            if (photo != null)
            {
                return "photo taken successfully";
            }

            return string.Empty;
        }
        catch (Exception ex)
        {
            return ex.Message;
        }
    }
}

Here is your issueProjects' running GIF.

enter image description here

Leon
  • 8,404
  • 2
  • 9
  • 52
  • I tried adding your if statement to my OnCreate, but still it requests permissions, permissions are granted and then taking a photo throws a permission exception. It even shows that permission is granted under the app in the android App settings – Ben Price Mar 11 '20 at 15:33
  • Update: on a complete clean rebuild with that code in the OnCreate method, permissions are working as intended. I was under the impression that permissions could be asked as and when they are needed, however this did not seem to be the case here. This does however propose a problem later down the line when the user tries to use the camera and they then accept the permission after the fact and it still breaks. – Ben Price Mar 11 '20 at 16:43
  • Do you get the result like me ? If you could get the result like me, you can see my update answer to get the runtime permission. If the reply is helpful, please do not forget to mark it as answer. It will help others who have similar isssue. – Leon Mar 12 '20 at 07:47
  • I don't have the correct result no, the issue still persists assuming the user initially denies permissions. They need to be able to be requested after the startup also. – Ben Price Mar 12 '20 at 09:04
  • Download my dem, run it in your VS, If you have same issue. – Leon Mar 12 '20 at 09:42
  • I can't seem to get your demo project running on my machine, errors to do with missing dll files and failing to create JavaTypeInfo, I have however uploaded my own demo project to showcase my issue a bit better here. https://github.com/BenPrice851/IssueProjects – Ben Price Mar 12 '20 at 11:14
  • @BenPrice Please see my update answer.Your issueProjects need to request storage permission as well. If the reply is help, please do not forget to mark it as answer(click ✔ in the upper right corner of this answer). – Leon Mar 13 '20 at 02:13
  • the issue turned out to be an issue with xamarin essentials version 1.5.0, updating to 1.5.1 resolved the issue entirely. Both the read and write permissions had already been included in my manifest file – Ben Price Mar 13 '20 at 10:41
0

You must add permissions for camera to your Android Manifest file!

In Visual Studio right click your android project.

Go to Options -> Build -> Android Application and tick the box in required permissions that says camera.

NB: If you are going to be recording you may also want to enable microphone and audio permissions.

You must also add:

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

To your android manifest.

James Mallon
  • 1,107
  • 9
  • 25