8.4 Authentifizierung durch biometrische Merkmale 

Viele Smartphones und Tablets haben Fingerabdrucksensoren oder Irisscanner, mit denen sich die Benutzer Ihrer App authentifizieren können. Das geht schneller als das Eingeben eines Passworts und ist halbwegs sicher. Wie Sie biometrische Merkmale abfragen, zeige ich Ihnen anhand der Beispiel-App BiometricPromptDemo. Damit Sie sie auch ohne entsprechende Hardware ausprobieren können, werfen wir zunächst einen Blick auf die Konfiguration des Emulators.
8.4.1 Fingerabdrucksensor im Emulator einrichten 

In den Systemeinstellungen erreichen Sie unter Security • Fingerprint die Seite zum Hinterlegen und Löschen von Fingerabdrücken. Damit Sie sich auf diese Weise authentifizieren können, muss eine zusätzliche Sperrmethode aktiv sein. Da Sie diese im Emulator sehr wahrscheinlich nicht konfiguriert haben, sehen Sie als Erstes die Seite zum Einrichten der Bildschirmsperre (Abbildung 8.11). Wählen Sie am besten Fingerprint + PIN, und geben Sie dann zweimal hintereinander dieselbe Folge aus vier Ziffern ein. Anschließend können Sie einstellen, welche Inhalte Sie auf dem Sperrbildschirm sehen möchten. Done beendet die Konfiguration der Bildschirmsperre.
Jetzt können Sie das Entsperren mit Fingerabdruck einrichten. Die erste Seite des Assistenten ist in Abbildung 8.12 zu sehen. Klicken Sie auf Next.
Abbildung 8.11 Bildschirmsperre einrichten
Abbildung 8.12 Entsperren mit Fingerabdruck einrichten
Öffnen Sie nun mit die Emulatoreinstellungen, und wechseln Sie auf die Seite Fingerprint (Abbildung 8.13). Klicken Sie auf TOUCH THE SENSOR.
Abbildung 8.13 Die Emulator-Einstellungsseite »Fingerprint«
Folgen Sie den Anweisungen im Emulator, und legen Sie den Finger wiederholt auf den virtuellen Sensor, indem Sie TOUCH THE SENSOR erneut anklicken (Abbildung 8.14). Nachdem Sie den virtuellen Fingerabdruck erfolgreich hinterlegt haben, beenden Sie den Assistenten mit Done (Abbildung 8.15).
Die Seite Fingerprint des simulierten Geräts sollte nun in etwa Abbildung 8.16 entsprechen.
Abbildung 8.14 Finger wiederholt auf den virtuellen Sensor legen
Abbildung 8.15 Der Fingerabdruck wurde erfolgreich hinzugefügt.
8.4.2 Jetpack Biometric 

Unterstützung für Fingerabdrucksensoren gibt es schon seit Android 6.0; die Klasse android.hardware.fingerprint.FingerprintManager hat Google mit API-Level 23 eingeführt. Sie koordiniert den Zugriff auf entsprechende Hardware. Allerdings mussten Entwickler selbst für die Interaktion mit dem Anwender sorgen, denn einen systemweiten Dialog gab es noch nicht. Andere biometrische Merkmale waren ebenfalls nicht vorgesehen. Hersteller haben notgedrungen ihr eigenes Süppchen gekocht. Seit Android 9 (API-Level 28) gibt es android.hardware.biometrics.BiometricPrompt. Sie löst den alten FingerprintManager ab. Die Klasse unterstützt zusätzliche Scannertypen (zum Beispiel in das Display eingearbeitete Sensoren) und stellt eine einheitliche Benutzeroberfläche zur Verfügung.
Abbildung 8.16 Ein hinterlegter Fingerabdruck
Jetpack Biometric erleichtert den nicht immer einfachen Umgang mit verschiedenen Plattformversionen. Die Bibliothek stellt eine einheitliche API zur Verfügung und zeigt entweder die systemweite Oberfläche oder einen Nachbau an. Sie steht ab Android 6 zur Verfügung. Um die Komponente in eigenen Programmen zu integrieren, fügen Sie die Zeile
implementation "androidx.biometric:biometric:1.0.1"
Ihrer modulspezifischen build.gradle-Datei hinzu. Die Authentifizierung mittels biometrischer Merkmale ist dann in wenigen Schritten erledigt. Diese zeigt meine Klasse BiometricPromptDemoActivity (Listing 8.17). Als Erstes sollten Sie mit canAuthenticate() abfragen, ob das Gerät die biometrische Authentifizierung unterstützt. Hierfür benötigen Sie ein Objekt des Typs androidx.biometric.BiometricManager. Sie erhalten es durch Aufruf von BiometricManager.from().
package com.thomaskuenneth.androidbuch.biometricprompt
import android.os.Bundle
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.BIOMETRIC_SUCCESS
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.AuthenticationCallback
import androidx.biometric.BiometricPrompt.AuthenticationResult
import androidx.biometric.BiometricPrompt.PromptInfo
import kotlinx.android.synthetic.main.activity_main.*
class BiometricPromptDemoActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
button.setOnClickListener { showDialog() }
val biometricManager = BiometricManager.from(this)
button.isEnabled =
biometricManager.canAuthenticate() == BIOMETRIC_SUCCESS
}
private fun toast(resid: Int) = Toast.makeText(this, resid,
Toast.LENGTH_LONG).show()
private fun showDialog() {
val info = PromptInfo.Builder()
.setDescription(getString(R.string.descr))
.setTitle(getString(R.string.title))
.setConfirmationRequired(true)
.setSubtitle(getString(R.string.subtitle))
.setNegativeButtonText(getString(R.string.cancel))
.build()
BiometricPrompt(this, mainExecutor,
object : AuthenticationCallback() {
override fun onAuthenticationError(errorCode: Int,
errString: CharSequence) {
toast(R.string.error)
}
override fun onAuthenticationSucceeded(
result: AuthenticationResult) {
toast(R.string.ok)
}
override fun onAuthenticationFailed() {
toast(R.string.failed)
}
}).authenticate(info)
}
}
Listing 8.17 Die Klasse »BiometricPromptDemoActivity«
Um den Dialog anzuzeigen, erzeugen Sie einen PromptInfo.Builder. Mit setTitle(), setSubtitle() und setDescription() vergeben Sie einen Titel, Untertitel und eine Beschreibung. setConfirmationRequired() steuert, ob nach einer erfolgreichen Authentifizierung der Dialog automatisch geschlossen werden darf. setNegativeButtonText() blendet einen Button ein, mit dem der Nutzer die Interaktion abbrechen kann. build() erzeugt ein androidx.biometric.BiometricPrompt.PromptInfo-Objekt. Es wird der Methode authenticate() einer BiometricPrompt-Instanz übergeben.
Dessen Konstruktor erwartet eine FragmentActivity, einen Executor und einen AuthenticationCallback. Activities, die den Dialog anzeigen möchten, müssen von androidx.fragment.app.FragmentActivity oder deren Kinder (zum Beispiel AppCompatActivity) ableiten. Die Methoden von AuthenticationCallback werden aufgerufen, je nachdem ob
-
der Benutzer erfolgreich authentifiziert wurde (onAuthenticationSucceeded()),
-
eine Authentifizierung nicht geklappt hat, zum Beispiel weil der Finger nicht richtig auf dem Sensor lag (onAuthenticationFailed()),
Der Executor legt fest, auf welchem Thread der Callback aufgerufen wird. Mein Beispiel verwendet den Mainthread. Die Methode getMainExecutor() gehört zur Klasse android.content.ContextWrapper. Alternativ könnten Sie ContextCompat.getMainExecutor verwenden. Das bietet sich vor allem an, wenn Ihre App auch auf älteren Versionen laufen soll.