web-dev-qa-db-fra.com

Déterminer si un périphérique iOS prend en charge TouchID sans définir de code d'accès

Je développe actuellement une application iOS qui permet aux utilisateurs de se connecter à l'application à l'aide de TouchID, mais ils doivent d'abord définir un mot de passe dans l'application. Le problème est que, pour afficher l'option de mot de passe de configuration permettant d'activer la connexion TouchID, je dois détecter si le périphérique iOS prend en charge TouchID.

En utilisant LAContext et canEvaluatePolicy (comme les réponses ici Si l’appareil prend en charge Touch ID ), je suis en mesure de déterminer si l’appareil actuel prend en charge TouchID si l’utilisateur a configuré le mot de passe sur son appareil iOS. Voici un extrait de code (j'utilise Xamarin, il est donc en C #):

static bool DeviceSupportsTouchID () 
{
    if (UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
    {
        var context = new LAContext();
        NSError authError;
        bool touchIDSetOnDevice = context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out authError);

        return (touchIDSetOnDevice || (LAStatus) Convert.ToInt16(authError.Code) != LAStatus.TouchIDNotAvailable);
    }

    return false;
}

Si l'utilisateur n'a pas configuré le code d'accès du périphérique, authError renvoie simplement l'erreur "PasscodeNotSet", que le périphérique prenne effectivement en charge TouchID ou non. 

Si l'appareil de l'utilisateur prend en charge TouchID, je souhaite toujours afficher l'option TouchID dans mon application, que l'utilisateur ait ou non défini un code d'authentification sur son appareil (je vais simplement avertir l'utilisateur de le configurer en premier). Inversement, si l'appareil de l'utilisateur ne prend pas en charge TouchID, je ne souhaite évidemment pas afficher l'option TouchID dans mon application.

Ma question est donc la suivante: existe-t-il un moyen intéressant de déterminer de manière cohérente si un appareil iOS prend en charge TouchID, que l'utilisateur ait ou non configuré le code d'authentification sur son appareil?

La seule solution à laquelle je peux penser est de déterminer l'architecture du périphérique (auquel il est répondu dans Déterminer si le périphérique iOS est 32 bits ou 64 bits ), car TouchID n'est pris en charge que sur les périphériques dotés d'une architecture 64 bits. Cependant, je cherche s’il existe un moyen plus agréable de le faire.

Merci d'avance! :)

20
ABVincita

En conclusion de la discussion ci-dessous, il n’est pas possible pour le moment de déterminer si un appareil prend en charge ou non TouchID si l’utilisateur n’a pas configuré de code de passe sur son appareil.

J'ai signalé cette faille TouchID sur le rapport de bug d'Apple. Ceux qui veulent suivre le problème peuvent le voir sur Open Radar ici: http://www.openradar.me/20342024

Merci @rckoenes pour l'entrée :)

MODIFIER

Il s'avère que quelqu'un a déjà signalé un problème similaire (# 18364575). Voici la réponse d'Apple concernant le problème:

"L'ingénierie a déterminé que ce problème se comportait comme prévu en fonction des informations suivantes:

Si le mot de passe n'est pas défini, vous ne pourrez pas détecter la présence de Touch ID. Une fois le mot de passe défini, canEvaluatePolicy retournera éventuellement LAErrorTouchIDNotAvailable ou LAErrorTouchIdNotEnrolled et vous pourrez détecter la présence/l'état du Touch ID.

Si les utilisateurs ont désactivé le code d'accès sur leur téléphone avec Touch ID, ils savaient qu'ils ne pourraient pas utiliser Touch ID. Les applications n'ont donc pas besoin de détecter la présence de Touch ID ni de promouvoir les fonctionnalités basées sur Touch ID. " _

Donc ..... la réponse finale de Apple est No. :(

Remarque: une question StackOverflow similaire de la personne qui a signalé cela -> iOS8 vérifie si le périphérique a un Touch ID (Me demande pourquoi je n'ai pas trouvé cette question auparavant malgré mes recherches approfondies ...)

17
ABVincita

La manière correcte de détecter si TouchID est disponible:

BOOL hasTouchID = NO;
// if the LAContext class is available
if ([LAContext class]) {
    LAContext *context = [LAContext new];
    NSError *error = nil;
    hasTouchId = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];
}

Désolé, c'est en Objective-C, vous devrez peut-être le traduire en C #.

Vous devez vous abstenir de vérifier la version du système et simplement vérifier si la classe ou les méthodes sont disponibles.

10
rckoenes

Je sais que c'est une question de l'année dernière, mais cette solution ne fait pas ce dont vous avez besoin? (Code rapide)

if #available(iOS 8.0, *) {
    var error: NSError?
    let hasTouchID = LAContext().canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)

    //Show the touch id option if the device has touch id hardware feature (even if the passcode is not set or touch id is not enrolled)
    if(hasTouchID || (error?.code != LAError.TouchIDNotAvailable.rawValue)) {
        touchIDContentView.hidden = false
    } 
}

Ensuite, lorsque l'utilisateur appuie sur le bouton pour se connecter avec touch id:

@IBAction func loginWithTouchId() {
    let context = LAContext()

    var error: NSError?
    let reasonString = "Log in with Touch ID"

    if (context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error)) {
        [context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
            //Has touch id. Treat the success boolean
        })]
    } else { 
        //Then, if the user has touch id but is not enrolled or the passcode is not set, show a alert message
        switch error!.code{

        case LAError.TouchIDNotEnrolled.rawValue:
            //Show alert message to inform that touch id is not enrolled
            break

        case LAError.PasscodeNotSet.rawValue:
            //Show alert message to inform that passcode is not set
            break

        default:
            // The LAError.TouchIDNotAvailable case.
            // Will not catch here, because if not available, the option will not visible
        }
    }
}

J'espère que ça aide!

7
pcsantana

Pour l'objectif C
Cela fonctionne très bien sur tous les appareils sans vérifier la version de l'appareil.

- (void)canAuthenticatedByTouchID{
LAContext *myContext = [[LAContext alloc] init];
NSError *authError = nil;
NSString *myLocalizedReasonString = touchIDRequestReason;

if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&authError]) {
 }else{
    switch (authError.code) {
        case kLAErrorTouchIDNotAvailable:
            [labelNotSupportTouchID setHidden:NO];
            [switchBtn setHidden:YES];
            [labelEnableTouchid setHidden:YES];
            static dispatch_once_t onceToken;
            dispatch_once(&onceToken, ^{
                [self showAlertMessage:@"EyeCheck Pro" message:@"Device does not support Touch ID Service."];
            });

            break;
    }
  }
}
4
Avinash Jadhav

Voici un moyen un peu fastidieux de déterminer si votre appareil est doté d’un capteur d’identité tactile physique. 

+ (BOOL)isTouchIDExist {
if(![LAContext class]) //Since this mandotory class is not there, that means there is no physical touch id.
    return false;

//Get the current device model name
size_t size;
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
char *model = malloc(size);
sysctlbyname("hw.machine", model, &size, NULL, 0);
NSString *deviceModel = [NSString stringWithCString:model encoding:NSUTF8StringEncoding];

//Devices that does not support touch id
NSArray *deviceModelsWithoutTouchID = [[NSArray alloc]
                                       initWithObjects:
                                       @"iPhone1,1", //iPhone
                                       @"iPhone1,2", //iPhone 3G
                                       @"iPhone2,1", //iPhone 3GS
                                       @"iPhone3,1", //iPhone 4
                                       @"iPhone3,2",
                                       @"iPhone3,3",
                                       @"iPhone4,1", //iPhone 4S
                                       @"iPhone5,1", //iPhone 5
                                       @"iPhone5,2",
                                       @"iPhone5,3", //iPhone 5C
                                       @"iPhone5,4",
                                       @"iPod1,1", //iPod
                                       @"iPod2,1",
                                       @"iPod3,1",
                                       @"iPod4,1",
                                       @"iPod5,1",
                                       @"iPod7,1",
                                       @"iPad1,1", //iPad
                                       @"iPad2,1", //iPad 2
                                       @"iPad2,2",
                                       @"iPad2,3",
                                       @"iPad2,4",// iPad mini 1G
                                       @"iPad2,5",
                                       @"iPad2,5",
                                       @"iPad2,7",
                                       @"iPad3,1", //iPad 3
                                       @"iPad3,2",
                                       @"iPad3,3",
                                       @"iPad3,4", //iPad 4
                                       @"iPad3,5",
                                       @"iPad3,6",
                                       @"iPad4,1", //iPad Air
                                       @"iPad4,2",
                                       @"iPad4,3",
                                       @"iPad4,4", //iPad mini 2
                                       @"iPad4,5",
                                       @"iPad4,6",
                                       @"iPad4,7",
                                       nil];

return ![deviceModelsWithoutTouchID containsObject:deviceModel];

}

Référence: https://www.theiphonewiki.com/wiki/Modelshttps://en.wikipedia.org/wiki/IOS

3
Siva

Pour iOS 11+, vous pouvez utiliser biometryType: LABiometryType of LAContext. Plus de documentation Apple:

/// Indicates the type of the biometry supported by the device.
///
/// @discussion  This property is set only when canEvaluatePolicy succeeds for a biometric policy.
///              The default value is LABiometryTypeNone.
@available(iOS 11.0, *)
open var biometryType: LABiometryType { get }

@available(iOS 11.0, *)
public enum LABiometryType : Int {

    /// The device does not support biometry.
    @available(iOS 11.2, *)
    case none

    /// The device does not support biometry.
    @available(iOS, introduced: 11.0, deprecated: 11.2, renamed: "LABiometryType.none")
    public static var LABiometryNone: LABiometryType { get }

    /// The device supports Touch ID.
    case touchID

    /// The device supports Face ID.
    case faceID
}
0
cocavo