今天的文章要來實作關於生物辨識...或稱指紋辨識的功能

說到生物辨識,記得最早接觸到這個概念的還隸屬蘋果吧,我第一次拿到Iphone 6s(二手)時感受到了指紋辨識的美好(笑

後來過了好幾年拿到Iphone 10(二手)的時候又感受到了人臉辨識的美好

 

明明是Android工程師卻都拿蘋果手機

咳咳,總之就在我時常在想為何Android一直都不出指紋辨識的相關機種時,沒想到早在Android很前面的時代就有了(跪

然後更妙的是,我居然一直都沒有去寫這個功能...|・ω・)

好啦,總之本文就來寫一下關於生物辨識

不過有鑒於目前Android的人臉辨識機種還不多,而且模擬器好像也沒辦法測

因此這部分功能暫時跳過,等以後有機會會在寫一篇

 

好的,那這篇就是要來寫指紋辨識,直接看功能吧!

 

還有Github

->https://github.com/thumbb13555/AndroidBlogExamples/tree/main/BiometricExample

好,開始!


 

1. 設定模擬器&載入套件

好的,既然要開發指紋辨識,那當然得先找有支援指紋辨識的機種.....屁啦,並不需要

其實Android studio 的模擬器本身就有該模擬該功能的設置囉!

那首先,我們要先在模擬器裡登錄指紋

 

聲明一下,我用的模擬器是Google Pixel 2, API 30的機種

其實什麼機種都行,不過基本上有支援指紋辨識的機種還是Google的親孩子比較多啦XDD

開好模擬器後,基本上該機種的指紋登錄在Setting->Securly裏面

Setting

然後拉到底下,Fingerprint的部分

Security

而關於按指紋的部分,請點模擬器的圖中位置

截圖 2023-01-14 下午2.20.53

然後找到Fingerprint的部分

截圖 2023-01-14 下午2.21.34

就可以登錄指紋囉!

 

而Android的生物辨識部分,雖然原生的Android就有BiometricManager的套件,不過官方文檔也是提供androidx的套件使用

那麼,就請打開build.gradle

並把套件載入dependencies吧!

dependencies {

    implementation 'androidx.appcompat:appcompat:1.5.1'
    implementation 'com.google.android.material:material:1.7.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.1.4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.0'
    implementation "androidx.biometric:biometric:1.1.0"
}

 

最後記得要Sync呦!(・ω・)b

 


 

2. 撰寫介面&功能

 

好的,接著進入主要功能的區域

首先介面就兩個按鈕,速速帶過!

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btPIN"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="PIN碼登錄"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/guideline2" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.5" />

    <Button
        android:id="@+id/btFinger"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:text="指紋登錄"
        app:layout_constraintBottom_toTopOf="@+id/guideline2"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

再來是主要程式的其中一部分

我想大部人也都知道,因為Android廠家眾多,所以也未必每個機種都有生物辨識....甚至可能連PIN碼驗證都沒有(跪

因此,在寫功能之前我們必須先判斷該手機有沒有生物辨識的功能

其程式如下

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btPIN, btFinger;
        btFinger = findViewById(R.id.btFinger);
        btPIN = findViewById(R.id.btPIN);


        BiometricManager manager = BiometricManager.from(this);
        switch (manager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
            case BiometricManager.BIOMETRIC_SUCCESS:
                Toast.makeText(this, "本裝置可以使用Pin Code或者指紋登錄", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
                Toast.makeText(this, "本裝置不支援指紋登錄", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
                Toast.makeText(this, "生物認證功能目前不可用", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
                //表示該裝置使用者沒有登錄指紋(但裝置支援)
                final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
                enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                        BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
                startActivity(enrollIntent);
                break;
        }
        btFinger.setOnClickListener(v -> {
            
        });

        btPIN.setOnClickListener(v -> {
           
        });


    }

 

這邊需要注意一件事,就是這裡的BiometricManager套件在import時需要選擇androidx.biometric哦!

截圖 2023-01-14 下午2.27.51

主要內容上面的註解都寫了,就自己看吧!

需要注意的也只有要記得import對的套件~

 

 


 

3. 撰寫主要驗證程式

好的,接下來就是重點了

一般來說,我們在做驗證的時候通常會想要優先使用指紋,假設使用者沒登錄或者不方便使用指紋的情況才改去使用Pin碼做驗證

也或許,使用者就乾脆不想用指紋,就是想輸入PIN碼也說不定

因此我寫的內容就針對這兩部分有做出區別,請看Code

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button btPIN, btFinger;
        btFinger = findViewById(R.id.btFinger);
        btPIN = findViewById(R.id.btPIN);


        BiometricManager manager = BiometricManager.from(this);
        switch (manager.canAuthenticate(BIOMETRIC_STRONG | DEVICE_CREDENTIAL)) {
            case BiometricManager.BIOMETRIC_SUCCESS:
                Toast.makeText(this, "本裝置可以使用Pin Code或者指紋登錄", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE:
                Toast.makeText(this, "本裝置不支援指紋登錄", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE:
                Toast.makeText(this, "生物認證功能目前不可用", Toast.LENGTH_SHORT).show();
                break;
            case BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED:
                //表示該裝置使用者沒有登錄指紋(但裝置支援)
                final Intent enrollIntent = new Intent(Settings.ACTION_BIOMETRIC_ENROLL);
                enrollIntent.putExtra(Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
                        BIOMETRIC_STRONG | DEVICE_CREDENTIAL);
                startActivity(enrollIntent);
                break;
        }
        btFinger.setOnClickListener(v -> {
            //如果登錄指紋就會直接跳成PIN碼登錄
            startBiometricPrompt(getInfo(BIOMETRIC_STRONG | DEVICE_CREDENTIAL));
        });

        btPIN.setOnClickListener(v -> {
            startBiometricPrompt(getInfo(DEVICE_CREDENTIAL));
        });


    }

    private BiometricPrompt.PromptInfo getInfo(int method) {
        return new BiometricPrompt.PromptInfo.Builder()
                .setTitle("登錄")
                .setSubtitle("Balabala")
                .setAllowedAuthenticators(method)
                .build();
    }

    private void startBiometricPrompt(BiometricPrompt.PromptInfo promptInfo) {
        Executor executor = ContextCompat.getMainExecutor(this);


        BiometricPrompt biometricPrompt = new BiometricPrompt(this, executor
                , new BiometricPrompt.AuthenticationCallback() {
            @Override
            public void onAuthenticationError(int errorCode, @NonNull CharSequence errString) {
                super.onAuthenticationError(errorCode, errString);
            }

            @Override
            public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
                super.onAuthenticationSucceeded(result);

                Toast.makeText(MainActivity.this, "登錄成功", Toast.LENGTH_SHORT).show();

            }

            @Override
            public void onAuthenticationFailed() {
                super.onAuthenticationFailed();
            }
        });

        biometricPrompt.authenticate(promptInfo);
    }
}

首先幾個步驟,首先要先設定關於彈出的視窗內容

這個內容的話,我們將在BiometricPrompt.PromptInfo這個函式中設定

而我把它包裝在了粉底白字的getInfo的副程式中

 

再來是紫底白字的主要驗證功能的部分,最大的一大坨就是Callback,也就是完成驗證後的回傳

最後,橘底白字的部分當然就是最最最重要的,也就是將先前的資訊載入

基本上就這三個大點是特別要注意的

此外,綠底白字的部分是控制控制要使用的驗證方法

一般來說,如果想要使用者用指紋或者PIN碼驗證的話,在該方法輸入

BIOMETRIC_STRONG | DEVICE_CREDENTIAL

就可以實現(也就是會優先用生物辨識,如果輸入錯誤或者突然不想用的時候就可以切換)

或者只輸入

DEVICE_CREDENTIAL

的話,就不使用指紋辨識,直接使用PIN碼驗證囉!

 


 

4. 關於onAuthenticationSucceeded

中的BiometricPrompt.AuthenticationResult

 

有些細心的人可能會注意到,在Successed中有個回調

@Override
public void onAuthenticationSucceeded(@NonNull BiometricPrompt.AuthenticationResult result) {
    super.onAuthenticationSucceeded(result);

}

 

這部分我承認,我到現在還搞不清楚他到底是打算拿來幹嘛用的

雖然我參考了官方文檔

-> https://developer.android.com/training/sign-in/biometric-auth

不過我還是一直想像不出使用這個功能的場景

而關於這部分的功能,其實我原本是打算做的,也因此研究了整個下午

不過最後實在得不出它的存在意義,也坦白說不知道該如何介紹

所以我想,這部分我就只放上我參考過的連結Github,然後請各位自己研究研究吧

-> https://github.com/isaidamier/blogs.biometrics.cryptoBlog

 


其實我感覺今天的功能不算太難,我幾乎還測試跟取財只花了一個小時左右就弄好了

不過在最後一段有說,光研究那個CryptoObject的應用場景跟內容就搞了一整個下午

然後研究無果,還是放棄了.....

最後這篇文在深夜才發出QAQ

 

好啦,總之我日後如果有想到這部分的功能的話,我在另外寫一篇發表囉

那希望大家都能夠成功實現功能!

arrow
arrow
    創作者介紹
    創作者 碼農日常 的頭像
    碼農日常

    碼農日常大小事

    碼農日常 發表在 痞客邦 留言(2) 人氣()