diff --git a/android-client/PMA.Biometric.pas b/android-client/PMA.Biometric.pas index 6f413a6..d417066 100644 --- a/android-client/PMA.Biometric.pas +++ b/android-client/PMA.Biometric.pas @@ -40,6 +40,28 @@ implementation {$IF DEFINED(ANDROID)} uses FMX.BiometricAuth, FMX.Platform; + +const + // DeviceCredential inclus : un telephone protege par un schema ou un code, + // sans empreinte enrolee, doit rester utilisable. C'est le cas courant. + WANTED_STRENGTHS = [TBiometricStrength.Strong, + TBiometricStrength.DeviceCredential]; + +/// Recupere le service ET pose les forces d'authentification. +/// +/// L'ORDRE N'EST PAS COSMETIQUE. Le service Android construit son masque +/// d'authentificateurs a partir de ces forces, et son champ demarre a +/// l'ensemble VIDE - le constructeur ne l'initialise pas. Interroger +/// CanAuthenticate avant de les poser revient donc a demander +/// canAuthenticate(0), qui ne repond jamais « disponible », quel que soit ce +/// que l'appareil sait faire. +function AcquireService(out ASvc: IFMXBiometricAuthService): Boolean; +begin + Result := TPlatformServices.Current.SupportsPlatformService( + IFMXBiometricAuthService, ASvc); + if Result then + ASvc.SetBiometricStrengths(WANTED_STRENGTHS); +end; {$ENDIF} function BiometricAvailable: Boolean; @@ -53,8 +75,7 @@ begin // pas par « pas de biometrie » mais par une boite d'exception en pleine // ouverture du coffre. try - Result := TPlatformServices.Current.SupportsPlatformService( - IFMXBiometricAuthService, LSvc) and LSvc.CanAuthenticate; + Result := AcquireService(LSvc) and LSvc.CanAuthenticate; except Result := False; end; @@ -73,14 +94,19 @@ var begin if not Assigned(AThen) then Exit; - if not BiometricAvailable then + // AcquireService pose les forces ; CanAuthenticate n'a de sens qu'apres. + if not AcquireService(LSvc) then begin AThen(boUnavailable); Exit; end; - if not TPlatformServices.Current.SupportsPlatformService( - IFMXBiometricAuthService, LSvc) then - begin + try + if not LSvc.CanAuthenticate then + begin + AThen(boUnavailable); + Exit; + end; + except AThen(boUnavailable); Exit; end; @@ -90,10 +116,6 @@ begin LProps.Description := APrompt; LProps.CancelButtonText := 'Annuler'; LSvc.SetPromptProperties(LProps); - // DeviceCredential inclus : un telephone sans empreinte enrolee mais avec - // un code de verrouillage reste utilisable, au lieu d'etre bloque. - LSvc.SetBiometricStrengths([TBiometricStrength.Strong, - TBiometricStrength.DeviceCredential]); // Meme raison que plus haut : ce qui remonte de la couche Java doit // ressortir en TBioOutcome, jamais en exception - l'appelant a un chemin