吾八哥博客

您现在的位置是:首页 > 码农手记 > Delphi > 正文

Delphi

Firemonkey里实现指纹验证功能

吾八哥2017-11-08Delphi4108

最近我写的用于管理密码的APP“由由密码管家”快到发布阶段了,每天抽一两小时测试添砖!最近两天加了ios系统下的指纹验证功能(Touch ID),开始的时候也是各种迷茫,Delphi下使用FireMonkey开发移动端资料确实是少得可怜啊!不过根据xcode下的实现逻辑代码里的关键词还是查阅到了,但使用的过程中也遇到了点小问题,这里就把代码贴出来分享下:

指纹验证接口单元:

unit iOSapi.LocalAuthentication;
interface
uses
  Macapi.ObjectiveC, iOSapi.Foundation;
const
  LAFwk = '/System/Library/Frameworks/LocalAuthentication.framework/LocalAuthentication';
const
  kLAErrorAuthenticationFailed = -1;
  kLAErrorUserCancel = -2;
  kLAErrorUserFallback = -3;
  kLAErrorSystemCancel = -4;
  kLAErrorPasscodeNotSet = -5;
  kLAErrorTouchIDNotAvailable = -6;
  kLAErrorTouchIDNotEnrolled = -7;
  kLAErrorTouchIDLockout = -8;
  kLAErrorAppCancel = -9;
  kLAErrorInvalidContext = -10;
type
  LAPolicy = (notUsed = 0, DeviceOwnerAuthenticationWithBiometrics = 1, DeviceOwnerAuthentication = 2);
  LAContextReply = procedure(success: Boolean; error: NSError) of Object;
  LAContextClass = interface(NSObjectClass)
    ['{6AA41561-0BBC-495C-9ADE-CB38B5AB9305}']
  end;
  LAContext = interface(NSObject)
    ['{8F6B7D53-83A8-43D3-B6C2-116068C382CE}']
    function canEvaluatePolicy(policy: LAPolicy; error: NSError): Boolean; cdecl;
    procedure evaluatePolicy(policy: LAPolicy; localizedReason: NSString; reply: LAContextReply); cdecl;
  end;
  TLAContext = class(TOCGenericImport<LAContextClass, LAContext>)
  end;
implementation
{$IF defined(IOS)}
uses
  Posix.Dlfcn;
{$ENDIF IOS}
{$IF defined(IOS)}
var
  LAModule: THandle;
initialization
LAModule := dlopen(MarshaledAString(LAFwk), RTLD_LAZY);
finalization
dlclose(LAModule);
{$ENDIF IOS}
end.

原来查阅到的资料没有定义错误代码,我进行了补充。调用方法如下:

{$IF DEFINED(IOS)}
procedure TMaster.TouchIDReply(success: Boolean; error: NSError);
begin
  if success then
  begin
    TThread.Synchronize(nil,
      procedure
      begin
        //验证成功
      end);
  end
  else
  begin
    if error.code = kLAErrorUserFallback then
    begin
      //用户点击了输入密码
    end;
  end;
end;
function TMaster.TryTouchID: Boolean;
var
  Context: LAContext;
  canEvaluate: Boolean;
begin
  Result := false;
  Context := TLAContext.Alloc;
  try
    Context := TLAContext.Wrap(Context.init);
    canEvaluate := Context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, nil);
    if canEvaluate = True then
    begin
      Context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, StrToNSStr('通过Home键验证已有手机指纹'),
        TouchIDReply);
      Result := True;
    end;
  finally
    Context.release;
  end;
end;
{$ENDIF}