MAUI-Android: Scheduling of App Permsssions
xam maui csharp android permissions
The Video Capture app as recently discussed here requires both Camera and Audio permissions. At (first) runtime, the user gets a prompt to approve the use of these. There is an issue where the Audio permission prompt may need appear. This has been resolved by separating them and puting in suitable task delays.
About
Been again using GitHub Copilot and WindSurf AI, this time to resolve MAUI permissions issues.
An Android specific MAUI Video Capture library using the .NET MAUI Community Toolkit has been developed and published on NuGet. There is also a sample app as code on GitHub that uses it. The app needs some user permissions , via user approval, to use the phone’s camera and audio:

Permissions Dialogs
Links
- The GitHub App only Project MauiMediaRecorderVideoAndroidApp … uses NuGet page:
- The NuGet Package djaus2_MauiMediaRecorderVideoLib
- The precursor app PhotoTimingDjaus
- Previous blog post on this Maui Android Phone App … With Issues
- Another blog post here wrt GitHub Copilot and this app development GitHub Copilot v Documentation: How far can you go with Copilot
- Also Blog post: maui-Should_Runtime_Identifier_only_be_in_the_app
1. The Permissions Method
The method is in the library and needs to be called from the app:
VideoKapture.RequestPermissionsStatic()
Comment: The permissions code is embedded in the library to simplify the library’s reuse.
2. App Android Manifest
The permissions are declared in the app’s Platform/Android/AndroidManifest.xml
.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<application android:allowBackup="true" android:icon="@mipmap/appicon" android:roundIcon="@mipmap/appicon_round" android:supportsRtl="true" tools:replace="android:icon">
</application>
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
</manifest>
3. Calling the Method for the App
The library then has a method that iterates through these in-app permissions actioning their permissions. The call to this method is in-app in Platform/Android/MainActivity.cs
.
namespace MauiCameraViewSample
{
[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState); // Ensure base initialization always occurs
VideoKapture.RequestPermissionsStatic();
}
}
}
4. Accessing the app specified permissions in the Lib
public static async void RequestPermissionsStatic()
{
var context = Platform.CurrentActivity;
var info = context.PackageManager.GetPackageInfo(context.PackageName, PackageInfoFlags.Permissions);
if (info.RequestedPermissions != null)
{
...
...
}
}
5. Iterating through the permissions
if (info.RequestedPermissions != null)
{
List<string> permissionsToRequest = new List<string>();
foreach (var permission in info.RequestedPermissions)
{
System.Diagnostics.Debug.WriteLine($"Declared permission: {permission}");
PermissionStatus status = PermissionStatus.Granted;
...
...
}
}
6. Android Permissions
The permission type is only a string. This has to be translated to specific Android permissions for actions, such as CheckStatusAsync()
in this case.
//Nb: Some permissions can't be handled this way.
if (permission == Manifest.Permission.Camera)
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Camera>();
else if (permission == Manifest.Permission.RecordAudio)
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Microphone>();
etc
if (status != PermissionStatus.Granted)
{
permissionsToRequest.Add(permission);
}
A list of Permissions that haven’t been formally requested and are required is created for further processing..
7. Bulk Permission Call Fail
GitHub Copilot at this point suggesting calling for the permissions as one line of code
ActivityCompat.RequestPermissions(context, permissionsToRequest.ToArray(), 101);
It was found, as per slightly earlier versions fo the library on NuGet, that the user is only prompted for the Video permissions when the app is first run with the video functionality not being available. This was remedied by running the app a second time at which point the Audio permission was requested.
Solution
The first attempt was to separate the permission requests such as:
foreach (var permission in permissionsToRequest)
{
ActivityCompat.RequestPermissions(context, new[] { permission }, 101);
}
This did not solve it. A Task delay of arbitrary length was added but did not immediately resolve the situation. Its was decided that a wait until a permission is granted would be better:
foreach (var permission in permissionsToRequest)
{
PermissionStatus status = PermissionStatus.Granted;
ActivityCompat.RequestPermissions(context, new[] { permission }, 101);
// Allow time for the UI to process each request
do
{
if (permission == Manifest.Permission.Camera)
{
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Camera>();
}
else if (permission == Manifest.Permission.RecordAudio)
{
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Microphone>();
}
etc
} while (status != PermissionStatus.Granted);
}
This would work when debugging sometimes and other times not. So a significant task delay was added after the do-loop , a smaller delay at the start for each permission and a smaller delay within after each check.
if (permissionsToRequest.Count > 0)
{
foreach (var permission in permissionsToRequest)
{
await Task.Delay(2* TaskDelayUnit);
PermissionStatus status = PermissionStatus.Granted;
ActivityCompat.RequestPermissions(context, new[] { permission }, 101);
// Allow time for the UI to process each request
do
{
await Task.Delay(TaskDelayUnit);
if (permission == Manifest.Permission.Camera)
{
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Camera>();
}
else if (permission == Manifest.Permission.RecordAudio)
{
status = await Microsoft.Maui.ApplicationModel.Permissions.CheckStatusAsync<Microsoft.Maui.ApplicationModel.Permissions.Microphone>();
}
etc
} while (status != PermissionStatus.Granted);
await Task.Delay(4* TaskDelayUnit); // Allow time for the UI to process each request
}
}
TaskDelayUnit is defined as 250mS.
This worked 😄!
Discussion.
It would be better if there is a more deterministic method for waiting for the permissions to be granted rather than using task delays. Also, the size of TaskDelayUnit could be reduced until this does not work so as to determine a minimum. This should though be a setting in the app and be passed to the library (2Do). Finally, there should be a timeout with app failure if a permission is not completed within a specified number of do-loops (2Do).
Topic | Subtopic | |
This Category Links | ||
Category: | Xamarin Index: | Xamarin |
Next: > | PhotoT iming | Triggering Video Capture |
< Prev: | MAUI-Android | Should Runtime Identifier only be in the app? |

