xamarin.androidx.biometric: _biometricsService.CanAuthenticate always returns false

Sreenivasan, Sreejith 125 Reputation points
2025-10-01T14:26:16.5833333+00:00

Fingerprint authentication is working fine in my xamarin forms project using xamarin.androidx.biometric. Now I am migrating it to MAUI and I am getting false value for _biometricsService.CanAuthenticate.

Below is my IBiometricsService interface:


public interface IBiometricsService

{

    LocalAuthenticationType CanAuthenticationWith();

    void AuthenticateUser(Action<bool, string> OnAuthComplete);

    Task<bool> CanAuthenticate(bool devicePassword = false);

}

Android platform BiometricsService service adding below:


[assembly: Dependency(typeof(BiometricsService))]

namespace Project.Android.Services

{

    public class BiometricsService : IBiometricsService

    {

        private Context _context;

        private BiometricManager _biometricManager;

        public BiometricsService()

        {

            _context = Controls.Instance;

        }

        public async Task<bool> CanAuthenticate(bool devicePassword = false)

        {

            if (_context == null)

                return false;

            // Check for biometric permission — starting from Android 10 (API 29) permission is not required for BiometricManager

            // But for backward compatibility, we check

            if (Build.VERSION.SdkInt < BuildVersionCodes.Q)

            {

                var permissionResult = ContextCompat.CheckSelfPermission(_context, Manifest.Permission.UseFingerprint);

                if (permissionResult != Permission.Granted)

                    return false;

            }

            _biometricManager = BiometricManager.From(_context);

            var canAuthenticate = _biometricManager.CanAuthenticate(

                AndroidX.Biometric.BiometricManager.Authenticators.BiometricStrong

                | AndroidX.Biometric.BiometricManager.Authenticators.DeviceCredential);

            return canAuthenticate == AndroidX.Biometric.BiometricManager.BiometricSuccess;

        }

        public async void AuthenticateUser(Action<bool, string> OnAuthComplete)

        {

            var resp = await DependencyService.Get<IFingerprintAuth>().GetAuthenticateAsync("test");

            if (resp.isAutheticated)

            {

                OnAuthComplete?.Invoke(true, string.Empty);

            }

            else

            {

                OnAuthComplete?.Invoke(false, resp.ErrorMessage);

            }

        }

        public LocalAuthenticationType CanAuthenticationWith()

        {

            LocalAuthenticationType authType = LocalAuthenticationType.None;

            //var context = Android.App.Application.Context;

            var context = global::Android.App.Application.Context;

            if (global::Android.OS.Build.VERSION.SdkInt >= global::Android.OS.BuildVersionCodes.M)

            {

                var biometricManager = AndroidX.Biometric.BiometricManager.From(context);

                int canAuthenticate = biometricManager.CanAuthenticate(

                    AndroidX.Biometric.BiometricManager.Authenticators.BiometricStrong |

                    AndroidX.Biometric.BiometricManager.Authenticators.DeviceCredential);

                switch (canAuthenticate)

                {

                    case AndroidX.Biometric.BiometricManager.BiometricSuccess:

                        authType = LocalAuthenticationType.BiometryTouchID_Or_Fingerprint;

                        break;

                    case AndroidX.Biometric.BiometricManager.BiometricErrorNoHardware:

                    case AndroidX.Biometric.BiometricManager.BiometricErrorNoneEnrolled:

                    case AndroidX.Biometric.BiometricManager.BiometricErrorHwUnavailable:

                        authType = LocalAuthenticationType.None;

                        break;

                    default:

                        authType = LocalAuthenticationType.None;

                        break;

                }

                // 🔐 Check if device lockscreen (PIN/pattern/password) is set

                var keyguardManager = (KeyguardManager)context.GetSystemService(global::Android.Content.Context.KeyguardService);

                if (keyguardManager.IsKeyguardSecure)

                {

                    if (authType == LocalAuthenticationType.None)

                        authType = LocalAuthenticationType.Pin;

                }

                // 👆 Check permission for fingerprint usage (older Android versions)

                var permissionResult = ContextCompat.CheckSelfPermission(context, Manifest.Permission.UseFingerprint);

                if (permissionResult == global::Android.Content.PM.Permission.Granted)

                {

                    if (authType == LocalAuthenticationType.None)

                        authType = LocalAuthenticationType.BiometryTouchID_Or_Fingerprint;

                }

            }

            return authType;

        }

    }

}

I have added below permissions in my AndroidManifest.xml


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

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

I have register the BiometricsService like below in MAUIProgram.cs like below:


#if ANDROID

        builder.Services.AddSingleton<IBiometricsService, BiometricsService>();

#endif

Finally accessing it like below:


private readonly IBiometricsService _biometricsService;

public LoginPMAViewModel(IBiometricsService biometricsService) : base(navigationService)

{

    _biometricsService = biometricsService;

}

//accessing it like below, but value is false

var canAuthenticate = await _biometricsService.CanAuthenticate(false);

Is there anything else do we need to add make it work? And xamarin.androidx.biometric is it support for MAUI?

Developer technologies | .NET | .NET MAUI
0 comments No comments
{count} votes

Answer accepted by question author
  1. Tony Dinh (WICLOUD CORPORATION) 3,835 Reputation points Microsoft External Staff
    2025-10-02T06:34:14.1333333+00:00

    Hello @Sreenivasan, Sreejith !

    The NuGet package Xamarin.AndroidX.Biometric provides .NET for Android and .NET MAUI bindings for the official AndroidX Biometric library. It continues to support BiometricPrompt for fingerprint, face, and device credentials on devices running API 14+, so you’re fully covered. Just make sure the package is referenced from your Android head project in MAUI.

    Regarding to the issue, here are the common reasons why your existing Xamarin.Forms biometric code returns false:


    1. In .NET MAUI, DependencyService is still available for backward compatibility, but it’s no longer the recommended way to resolve platform-specific services. It exists mainly to ease migration, and relying on it can cause initialization issues.
    2. After migration that object may no longer exist or be initialized. In your BiometricsService, you’re using Controls.Instance as the context. In MAUI, that may not be initialized properly. Instead, use Platform.CurrentActivity (via Platform.AppContext or MauiApplication.Context) to ensure you’re passing a valid Android Context.
    3. BiometricManager.CanAuthenticate() requires correct flags. In MAUI, you should explicitly pass:
          BiometricManager.Authenticators.BiometricStrong | BiometricManager.Authenticators.DeviceCredential
      
      If you only pass one, some devices will return false.
    4. Since you already added:
          <uses-permission android:name="android.permission.USE_BIOMETRIC" />
          <uses-permission android:name="android.permission.USE_FINGERPRINT" />
      
      This is correct. But on Android 11+ (API 30+), USE_FINGERPRINT is deprecated. Ensure that you request runtime permissions for biometrics if targeting <29.
    5. Other factors that CanAuthenticate will return false if:
      • No fingerprint/face enrolled
      • No secure lock screen set
      • Hardware unavailable
      You can check this with:
          var keyguardManager = (KeyguardManager)context.GetSystemService(Context.KeyguardService);
          bool isSecure = keyguardManager?.IsKeyguardSecure ?? false;
      

    You can update your BiometricsService constructor and context usage:

    public BiometricsService()
    {
        _context = Platform.AppContext ?? Android.App.Application.Context;
        _biometricManager = BiometricManager.From(_context);
    }
    

    And ensure your CanAuthenticate method checks both biometric and device credential:

    var canAuthenticate = _biometricManager.CanAuthenticate(
        BiometricManager.Authenticators.BiometricStrong |
        BiometricManager.Authenticators.DeviceCredential);
     
    return canAuthenticate == BiometricManager.BiometricSuccess;
    

    With these adjustments, your biometric checks in MAUI should behave consistently with your Xamarin.Forms implementation.


    I hope this helps! Let me know if you have solved your issue or have any questions!

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.