Fingerabdruck - Authentifikation

  • 4 Antworten
  • Neuster Beitrag
T

TiTan4T

Neues Mitglied
Threadstarter
Hey Leute,

ich möchte in einer von mir privat genutzten App eine Authentifikation via Fingerabdruck einbauen. Bisher funktioniert der ganze Spaß auch.
Dabei habe ich einen ImageButton, der die Abfrage triggert.
Sofern ich den richtigen Finger verwende, klappt auch alles. Die Methode 'onAuthenticationSucceeded' wird ausgeführt und ich kann den Knopf nochmal drücken.
Verwende ich allerdings den falschen Finger, dann wird onAuthenticationFailed ausgeführt und der ImageButton funktioniert erst wieder, wenn ich die App neu öffne, oder eine neue Activity lade und über den Zurück-Knopf zur Main-Acitivity zurückgehe.

Ich würde gerne, dass bei einer Fehleingabe ein erneutes Drücken der Schaltfläche möglich ist.

Dazu muss man sagen, dass ich noch nie ne Android-App geschrieben habe und daher keine Erfahrungen habe.
Hier einmal der Code:

MainActivity:
Code:
package de.oh12.garageopener

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.SystemClock
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Button
import android.widget.ImageButton
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.biometric.BiometricPrompt.PromptInfo
import java.util.concurrent.Executors


class MainActivity : AppCompatActivity() {
    var auth: Authentificator? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val myToolbar: Toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(myToolbar)

        auth = Authentificator(this)

    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        // Inflate the menu; this adds items to the action bar if it is present.
        menuInflater.inflate(R.menu.menu_items, menu)
        return true
    }

    override fun onOptionsItemSelected(item: MenuItem): Boolean {
        startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
        return true
    }

    fun onClickOpen(v: View) {
        //Toast.makeText(this, "Debug-Text", Toast.LENGTH_SHORT).show()
        checkFingerPrint()
    }

    private fun checkFingerPrint() {
        auth?.authentificate()
    }
}
SettingsActivity:
Code:
package de.oh12.garageopener

import android.os.Bundle
import android.view.Menu
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar


class SettingsActivity: AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_settings)

        val myToolbar: Toolbar = findViewById(R.id.toolbar2)
        setSupportActionBar(myToolbar)

        //actionbar
        val actionbar = supportActionBar
        //set actionbar title
        actionbar!!.title = "Einstellungen"
        //set back button
        actionbar.setDisplayHomeAsUpEnabled(true)
        actionbar.setDisplayHomeAsUpEnabled(true)
    }


    override fun onSupportNavigateUp(): Boolean {
        onBackPressed()
        return true
    }
}
Authentificator:
Code:
package de.oh12.garageopener

import android.content.Context
import android.widget.ImageButton
import androidx.appcompat.app.AppCompatActivity
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricPrompt
import androidx.core.content.ContextCompat

class Authentificator(context: AppCompatActivity): BiometricPrompt.AuthenticationCallback() {

    var promptInfo: BiometricPrompt.PromptInfo? = null
    var biometricPrompt: BiometricPrompt? = null
    var context: AppCompatActivity
    init {
        this.context = context
        if(isHardwareSupported(context)) {
            promptInfo = Authentificator.buildBiometricPrompt()

            val executor = ContextCompat.getMainExecutor(context)
            biometricPrompt = BiometricPrompt(context, executor, this)
        }
    }

    fun authentificate() {
        biometricPrompt?.authenticate(promptInfo as BiometricPrompt.PromptInfo)
    }

    override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
        super.onAuthenticationError(errorCode, errString)
    }

    override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
        super.onAuthenticationSucceeded(result)
        var button: ImageButton = context.findViewById(R.id.button_open)
        button.setImageResource(R.drawable.lock_green)
    }

    override fun onAuthenticationFailed() {
        super.onAuthenticationFailed()
    }

    companion object {
        fun isHardwareSupported(context: Context): Boolean {
            return BiometricManager.from(context).canAuthenticate() == BiometricManager.BIOMETRIC_SUCCESS
        }

        fun buildBiometricPrompt(): BiometricPrompt.PromptInfo {
            return BiometricPrompt.PromptInfo.Builder()
                .setTitle("Garage-Open")
                .setSubtitle("Öffnet die Garage")
                .setDescription("Touch your finger on the finger print sensor to authorise your access")
                .setNegativeButtonText("Cancel")
                .build()
        }
    }
}
T
 
D

deek

Stammgast
Du instanziierst BiometricPrompt nur einmal im Konstruktor deiner Authentification Klasse. Ich kenne die Details nicht, aber ich könnte mir vorstellen, dass du für jeden neuen Versuch auch einen neuen BiometricPrompt brauchst.
Also BiometricPrompt(context, executor, this) in die authenticate selbst verschieben.
 
T

TiTan4T

Neues Mitglied
Threadstarter
Das habe ich auch schon ausprobiert. Also:
Code:
fun authentificate() {
    var promptInfo: BiometricPrompt.PromptInfo? = null
    var biometricPrompt: BiometricPrompt? = null
    if(isHardwareSupported(context)) {
        promptInfo = buildBiometricPrompt()

        val executor = ContextCompat.getMainExecutor(context)
        biometricPrompt = BiometricPrompt(context, executor, this)
    }
    biometricPrompt?.authenticate(promptInfo as BiometricPrompt.PromptInfo)
}
Leider hat das nichts am Problem geändert.

€dit:
Das scheint ein Fix zu sein:
Code:
override fun onAuthenticationFailed() {
    super.onAuthenticationFailed()
    biometricPrompt?.cancelAuthentication()
}
Leider muss ich dann immer wieder den ImgButton drücken, wenn ich den Finger falsch aufgelegt habe und er nicht gelesenw erden konnte ...
 
Zuletzt bearbeitet:
D

deek

Stammgast
Starte doch in deinem AuthenticationFailed handler nochmal die Authentication, dann sparst du dir den klick
 
T

TiTan4T

Neues Mitglied
Threadstarter
Damit das sauber funktioniert muss ich die Authentifikation erstmal abbrechen. Wenn ich das aber mache, dann klappt das erneute Starten nicht. Eventuell weil da ein kleiner Delay zwischen muss!?
 
Oben Unten