Hello @Sreenivasan, Sreejith !
You can try to logging the _context, as it critical for BiometricManager. If Platform.AppContext is null or incorrect, it could cause BiometricManager to fail. Example code:
public BiometricsService()
{
_context = Platform.AppContext ?? global::Android.App.Application.Context;
global::Android.Util.Log.Debug("BiometricsService", $"Platform.AppContext is {(Platform.AppContext == null ? "null" : "not null")}");
_biometricManager = BiometricManager.From(_context);
global::Android.Util.Log.Debug("BiometricsService", $"Context type: {_context.GetType().FullName}");
}
- Run the app and check the logcat output for the context type. It should be something like
Android.App.Application or a MAUI-specific context.
- If
Platform.AppContext is null, the fallback to Android.App.Application.Context might not provide the correct environment for BiometricManager.
If the context is null or incorrect, try accessing the current activity’s context explicitly:
public BiometricsService()
{
_context = Platform.CurrentActivity ?? global::Android.App.Application.Context;
_biometricManager = BiometricManager.From(_context);
global::Android.Util.Log.Debug("BiometricsService", $"Context type: {_context.GetType().FullName}");
}
Test Authenticator Combinations
The -2 error might occur if the specified authenticators (BiometricStrong | DeviceCredential) are not supported. Some devices may only support BiometricWeak or require different flags. You can test CanAuthenticate with different authenticator flags to isolate the issue.
Modify CanAuthenticate in BiometricsService to log results for various authenticator types, example code:
public async Task<bool> CanAuthenticate(bool devicePassword = false)
{
if (_context == null)
{
global::Android.Util.Log.Debug("BiometricsService", "Context is null");
return false;
}
// Check legacy permission check for Android < Q (API 29)
if (Build.VERSION.SdkInt < BuildVersionCodes.Q)
{
var perm = ContextCompat.CheckSelfPermission(_context, Manifest.Permission.UseFingerprint);
if (perm != global::Android.Content.PM.Permission.Granted)
{
global::Android.Util.Log.Debug("BiometricsService", "USE_FINGERPRINT permission not granted");
return false;
}
}
_biometricManager = BiometricManager.From(_context);
// Test different authenticator combinations
var authenticators = new[]
{
BiometricManager.Authenticators.BiometricStrong,
BiometricManager.Authenticators.BiometricWeak,
BiometricManager.Authenticators.DeviceCredential,
BiometricManager.Authenticators.BiometricStrong | BiometricManager.Authenticators.DeviceCredential,
BiometricManager.Authenticators.BiometricWeak | BiometricManager.Authenticators.DeviceCredential
};
foreach (var auth in authenticators)
{
int result = _biometricManager.CanAuthenticate(auth);
global::Android.Util.Log.Debug("BiometricsService", $"CanAuthenticate({auth}) returned: {result}");
if (result == BiometricManager.BiometricSuccess)
{
global::Android.Util.Log.Debug("BiometricsService", $"Supported authenticator: {auth}");
if (auth == BiometricManager.Authenticators.BiometricStrong ||
auth == BiometricManager.Authenticators.BiometricWeak ||
auth == (BiometricManager.Authenticators.BiometricStrong | BiometricManager.Authenticators.DeviceCredential) ||
auth == (BiometricManager.Authenticators.BiometricWeak | BiometricManager.Authenticators.DeviceCredential))
{
return true;
}
}
}
// Fallback to keyguard check if devicePassword is allowed
try
{
var keyguardManager = (KeyguardManager)_context.GetSystemService(Context.KeyguardService);
bool isSecure = keyguardManager?.IsKeyguardSecure ?? false;
global::Android.Util.Log.Debug("BiometricsService", $"Keyguard secure: {isSecure}");
if (isSecure && devicePassword)
{
return true;
}
}
catch (Exception ex)
{
global::Android.Util.Log.Debug("BiometricsService", $"Keyguard check failed: {ex.Message}");
}
return false;
}
If only BiometricWeak or DeviceCredential returns BiometricSuccess, adjust your authenticator flags:
var authenticators = BiometricManager.Authenticators.BiometricWeak | BiometricManager.Authenticators.DeviceCredential;
int canAuthenticate = _biometricManager.CanAuthenticate(authenticators);
Verify Device Biometric Enrollment
Since you’ve confirmed fingerprint and screen lock are enabled, try double-check the enrollment status programmatically, example logging confirmations:
// paste this code in CanAuthenticate after the permission check
if (canAuthenticate == BiometricManager.BiometricErrorNoneEnrolled)
{
global::Android.Util.Log.Debug("BiometricsService", "No biometrics enrolled");
}
else if (canAuthenticate == BiometricManager.BiometricErrorNoHardware)
{
global::Android.Util.Log.Debug("BiometricsService", "No biometric hardware detected");
}
else if (canAuthenticate == BiometricManager.BiometricErrorHwUnavailable)
{
global::Android.Util.Log.Debug("BiometricsService", "Biometric hardware unavailable");
}
If no biometrics are enrolled (BiometricErrorNoneEnrolled), you can prompt the user to enroll a fingerprint with var intent = new Intent(Android.Provider.Settings.ActionSecuritySettings); or set up a screen lock with
Device-Specific
Some Android devices or OS versions (especially custom ROMs or specific manufacturers like Samsung, Xiaomi) may misreport biometric hardware due to quirks in the Android Biometric API. Try to log th edevie details to identify potential issues with:
global::Android.Util.Log.Debug("BiometricsService", $"Device: {Build.Manufacturer} {Build.Model}, API: {Build.VERSION.SdkInt}");
Other check if fallback
- Check your NuGet Package and MAUI compatibility: The
xamarin.androidx.biometric package is a binding for AndroidX Biometric, but its behavior in MAUI may differ due to platform changes.
- Ensure you’re using the latest version of
xamarin.androidx.biometric. Check the NuGet package manager for updates (e.g., version 1.1.0 or higher).
- Verify your .NET MAUI version (e.g., .NET 8 or 9) and ensure compatibility with AndroidX libraries.
- Confirm the
xamarin.androidx.biometric package is referenced in the Android platform project (not the shared project).
- Compare with Xamarin.Forms Setup: You mentioned the code worked in Xamarin.Forms, try to compare the environment between:
- NuGet Versions: Check the
xamarin.androidx.biometric version used in Xamarin.Forms vs. MAUI if match.
- Context Usage:
Xamarin.Forms likely used Android.App.Application.Context or an activity context. Ensure MAUI’s context matches.
- API Level: Confirm the Android API level of the test device matches what worked in Xamarin.Forms.
If all above steps are all failed, you can try to test on another physical device or an emulator with biometric support (e.g., Android Emulator with API 30+ and biometric emulation enabled). You can provide what you find from logging output from code, device details, .NET MAUI version and xamarin.androidx.biometric NuGet version. Also, confirmation of whether KeyguardManager.IsDeviceSecure and IsKeyguardSecure return true.
I hope this helps!