faceping.aidocs

Get started with Avalonia

Build a small Avalonia app that enrols your face and verifies it offline, on your own phone.

What you'll build

A face check that works in airplane mode

An app that enrols your face, verifies it live with a head-turn liveness check, and still matches with no network.

About 10 minutesAndroid or iPhoneFree sandbox key
0 of 7 steps doneAbout 10 minutes
FaceCheck
Look at the cameraTap Enrol my face to start.

1

Get a sandbox key#

Sign up at app.faceping.ai/signup with your email, then open Developers → Sandbox keys → Create sandbox key. It starts with fp_test_.

The sandbox is free and instant: up to 25 faces per device, each deleted 24 hours after it was enrolled. No card, no approval.

2

Create the project#

You need the .NET 10 SDK with the Android and iOS workloads, and an Android phone (Android 7 or later, 64-bit) or an iPhone with a cable. The Avalonia template makes a shared project for your screens, plus one project per platform.

dotnet workload install android ios
dotnet new install Avalonia.Templates
dotnet new avalonia.xplat -n FaceCheck
cd FaceCheck
First mobile .NET app on this machine?

The 10 minutes assume your machine already builds .NET apps for phones. If it doesn't, set it up first (the workloads and Android tools take a while to download):

  • Android: the Android SDK and a JDK. Install them with Android Studio, or let .NET fetch them with dotnet build -t:InstallAndroidDependencies (Microsoft's Android set-up guide has the full command). Turn on USB debugging on the phone.
  • iPhone: a Mac with Xcode 26 or later, signed in with your Apple ID (Xcode → Settings → Apple Accounts).
  • Avalonia: see Avalonia's mobile set-up.

FacePing runs on Android and iOS, so you can delete the FaceCheck.Desktop and FaceCheck.Browser projects (they'd still build, but face checks there report that FacePing runs on Android and iOS devices).

3

Add FacePing#

One package, in the shared project and in both platform projects. It brings the face models, liveness checks and a camera control with it.

dotnet add FaceCheck package FacePing.Sdk.Avalonia --prerelease
dotnet add FaceCheck.Android package FacePing.Sdk.Avalonia --prerelease
dotnet add FaceCheck.iOS package FacePing.Sdk.Avalonia --prerelease

FacePing for Avalonia is in preview: --prerelease gets the latest preview from NuGet. It needs Avalonia 12.

Then set the platforms FacePing runs on: 64-bit Android 7 (API 24) or later, and iOS 15 or later. The template's minimums are lower, and the build stops with a message until you change them. Give each app your own reverse-DNS id too (iOS signs the app with it):

<SupportedOSPlatformVersion>24</SupportedOSPlatformVersion>
<RuntimeIdentifiers>android-arm64;android-x64</RuntimeIdentifiers>
<ApplicationId>com.yourcompany.facecheck</ApplicationId>
<SupportedOSPlatformVersion>15.0</SupportedOSPlatformVersion>
<ApplicationId>com.yourcompany.facecheck</ApplicationId>

4

Allow the camera#

The package adds Android's camera permission for you. iOS asks the person with your own words: add them to the iOS project's Info.plist.

FaceCheck.iOS/Info.plist
<!-- inside <dict> -->
<key>NSCameraUsageDescription</key>
<string>FaceCheck uses the camera to verify your face.</string>

5

Turn FacePing on#

Each platform project starts the app in CustomizeAppBuilder. Add FacePing there, with your sandbox key, in both.

using FacePing.Sdk.Avalonia;

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) =>
    base.CustomizeAppBuilder(builder)
        .WithInterFont()
        .UseFacePing(o => o.SandboxKey = "fp_test_…");
using FacePing.Sdk.Avalonia;

protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) =>
    base.CustomizeAppBuilder(builder)
        .WithInterFont()
        .UseFacePing(o => o.SandboxKey = "fp_test_…");

6

Add the screen#

A camera control and two buttons: one enrols your face on the phone, the other verifies it. FaceCameraView is drawn by Avalonia, so it sits in your layout like any other control.

<UserControl xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:fp="using:FacePing.Sdk.Avalonia"
             x:Class="FaceCheck.Views.MainView">
  <StackPanel Margin="24,48,24,24" Spacing="16">
    <fp:FaceCameraView x:Name="Camera" Height="420" />
    <Button Content="Enrol my face" Click="OnEnroll" HorizontalAlignment="Stretch" />
    <Button Content="Verify" Click="OnVerify" HorizontalAlignment="Stretch" />
    <TextBlock x:Name="Status" FontSize="18" HorizontalAlignment="Center" />
  </StackPanel>
</UserControl>
using System;
using Avalonia.Controls;
using Avalonia.Interactivity;
using FacePing.Sdk;
using FacePing.Sdk.Avalonia;

namespace FaceCheck.Views;

public partial class MainView : UserControl
{
    readonly IFacePing faceping = IFacePing.Current;

    public MainView() => InitializeComponent();

    async void OnEnroll(object? sender, RoutedEventArgs e)
    {
        try
        {
            var photo = await Camera.CaptureAsync();
            var result = await faceping.EnrollAsync("me", photo);
            Status.Text = result.Outcome == EnrollOutcome.Enrolled
                ? "Enrolled. Now tap Verify."
                : $"Try again: {result.Outcome}";
        }
        catch (Exception ex) when (ex is FacePingSetupException or FacePingModelException or InvalidOperationException)
        {
            // For example a mistyped key, no connection on the very first run (the sandbox key is
            // activated once), or no camera. The message says which.
            Status.Text = ex.Message;
        }
    }

    async void OnVerify(object? sender, RoutedEventArgs e)
    {
        try
        {
            // A live check: matches your face, then asks you to turn your head (liveness).
            var result = await faceping.VerifyLiveAsync("me", Camera);
            Status.Text = $"{result.Outcome} · {result.Elapsed.TotalSeconds:0.00} s";
        }
        catch (Exception ex) when (ex is FacePingSetupException or FacePingModelException or InvalidOperationException)
        {
            Status.Text = ex.Message;
        }
    }
}

The template's MainView sets a view model as its DataContext in App.axaml.cs; it does no harm, or remove it.

7

Run it on your phone#

Plug your phone in and run a Release build. The first run needs a connection, to activate your sandbox key. Tap Enrol my face, then Verify: you should see Match.

dotnet build FaceCheck.Android -t:Run -c Release
# Simulators have no front camera: use a connected iPhone. The easiest way is Run in Rider or
# Visual Studio. From the command line, build, then install with Xcode's tools (use your ApplicationId):
dotnet build FaceCheck.iOS -c Release -p:RuntimeIdentifier=ios-arm64
xcrun devicectl list devices
xcrun devicectl device install app --device <device id> FaceCheck.iOS/bin/Release/net10.0-ios/ios-arm64/FaceCheck.iOS.app
xcrun devicectl device process launch --device <device id> com.yourcompany.facecheck

First time on an iPhone? dotnet build signs the app with a provisioning profile it finds on your Mac, but it can't create one. If the build says there's no profile for your ApplicationId, make one once in Xcode: create a new iOS App project with the same bundle identifier, pick your Team under Signing & Capabilities, and run it on the phone. Then build again. On the phone, turn on Developer Mode (Settings → Privacy & Security → Developer Mode) and, if iOS says the developer isn't trusted, trust it under Settings → General → VPN & Device Management.

The Android build includes the phone (arm64) and emulator (x86_64) versions of the face engine. For a smaller app, set <RuntimeIdentifiers>android-arm64</RuntimeIdentifiers> (phones only), or publish an Android App Bundle so each phone downloads only its own.

Now switch on airplane mode and tap Verify again. Still a match: the check ran entirely on your phone.

You've built a face check that works offline#

Next, make it real: verify the people in your app (members, staff or people with tickets), and apply to go live when you're ready.