Search code examples
c#uwpwindows-store-appswin-universal-app

How to check if user has granted app the permission for pictures folder?


My UWP app's manifest already asks for that permission. However, it seems like sometimes (perhaps since Windows 1809) that is not granted automatically. Rather, the user needs to open the app's advanced options from the control panel and set it.

So is there a way to check if the app has permissions in order to notify the user?

This is what I mean: Settings > Apps > (Click on app) > Click "Advanced options". Also keep in mind that some apps might not need any permissions so you might not see any for them. Check out MS weather app, it needs two permissions.

screenshot


Solution

  • This is the best solution I have found so far:

    private async Task<StorageLibrary> TryAccessLibraryAsync(KnownLibraryId library)
    {
        try
        {
            return await StorageLibrary.GetLibraryAsync(library);
        }
        catch (UnauthorizedAccessException)
        {
            //inform user about missing permission and ask to grant it
            MessageDialog requestPermissionDialog =
                new MessageDialog($"The app needs to access the {library}. " +
                           "Press OK to open system settings and give this app permission. " +
                           "If the app closes, please reopen it afterwards. " +
                           "If you Cancel, the app will have limited functionality only.");
            var okCommand = new UICommand("OK");
            requestPermissionDialog.Commands.Add(okCommand);
            var cancelCommand = new UICommand("Cancel");
            requestPermissionDialog.Commands.Add(cancelCommand);
            requestPermissionDialog.DefaultCommandIndex = 0;
            requestPermissionDialog.CancelCommandIndex = 1;
    
            var requestPermissionResult = await requestPermissionDialog.ShowAsync();
            if (requestPermissionResult == cancelCommand)
            {
                //user chose to Cancel, app will not have permission
                return null;
            }
    
            //open app settings to allow users to give us permission
            await Launcher.LaunchUriAsync(new Uri("ms-settings:appsfeatures-app"));
    
            //confirmation dialog to retry
            var confirmationDialog = new MessageDialog(
                  $"Please give this app the {library} permission.");
            confirmationDialog.Commands.Add(okCommand);
            await confirmationDialog.ShowAsync();
    
            //retry
            return await TryAccessLibraryAsync(library);
        }
    }
    

    What this does is it first tries to get the given library by its KnownLibraryId. If the user removed the app's permission, then it will fail with UnauthorizedAccessException.

    Now we show the user a MessageDialog that explains the problem and asks him to give the app permission.

    If the user presses Cancel, the method will return null as the user did not grant us the permission.

    Otherwise, we launch the Settings using the special launch URI ms-settings:appsfeatures-app (see docs) which opens the app advanced settings page with the permissions toggles.

    Now here is an unfortunate problem - I have found that changing permission will force close the app at the current moment. I inform the user about this fact in the first dialog. In case this changes in the future, the code is already prepared for this alternative - a new dialog is shown and the user can confirm it when the permission is changed and the method will call itself recursively and try to access the library again.

    Of course, I would recommend saving the user's data before the app closes due to permission changes so that when it is reopened, the data will remain intact and the user's flow is not broken.

    It is also possible to call this permission right after the app is launched if you really rely on this permission for its functionality. This way you know that you either have access, or the user will give it right at the beginning, so there is no harm in the fact that the app will be terminated.

    Update: I have found the issue quite interesting so I have written a blogpost about it.