Android 6.0 saw the introduction of fingerprint authentication, a new security feature that allows users to confirm their identify with a single touch. Well, after that this has become a common way of authentication for users.
Advantages
- Very easy, fast and convenient to use for authentication
- Don’t need to remember
- No struggling with the keyboards
- No more password recovery or resets
- With the help of Fingerprint authentication, online transactions become more convenient, hence your just a tap away from getting verified.
Adding Permission
Inorder to use finger print in your app, you need to add the permission in the Android Manifest.
< uses-permission android:name = "android.permission.USE_FINGERPRINT" /> |
Final Manifest will look like this
<? xml version = "1.0" encoding = "utf-8" ?> < manifest xmlns:android = "http://schemas.android.com/apk/res/android" package = "finger_print_demo.coderzheaven.com.fingerprintdemo" > < uses-permission android:name = "android.permission.USE_FINGERPRINT" /> < application android:allowBackup = "true" android:icon = "@mipmap/ic_launcher" android:label = "@string/app_name" android:roundIcon = "@mipmap/ic_launcher_round" android:supportsRtl = "true" android:theme = "@style/AppTheme" > < activity android:name = ".MainActivity" > < intent-filter > < action android:name = "android.intent.action.MAIN" /> < category android:name = "android.intent.category.LAUNCHER" /> </ intent-filter > </ activity > </ application > </ manifest > |
Layout
Here we will have a simple layout with one TextView that shows the status of the finger print authentication.
<? xml version = "1.0" encoding = "utf-8" ?> < android.support.constraint.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 = "finger_print_demo.coderzheaven.com.fingerprintdemo.MainActivity" > < TextView android:id = "@+id/mStatus" android:layout_width = "match_parent" android:layout_height = "wrap_content" android:gravity = "center" android:textSize = "20sp" app:layout_constraintBottom_toBottomOf = "parent" app:layout_constraintLeft_toLeftOf = "parent" app:layout_constraintRight_toRightOf = "parent" app:layout_constraintTop_toTopOf = "parent" /> </ android.support.constraint.ConstraintLayout > |
Handler Class for Finger Print
We will write a handler class that does the finger print authentication and send back the result.
So Create a java file named FingerPrintHandler and copy the below contents to it.
package finger_print_demo.coderzheaven.com.fingerprintdemo; import android.Manifest; import android.content.Context; import android.content.pm.PackageManager; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; import android.os.CancellationSignal; import android.os.Handler; import android.os.Message; import android.support.annotation.RequiresApi; import android.support.v4.app.ActivityCompat; @RequiresApi (api = Build.VERSION_CODES.M) public class FingerPrintHandler extends FingerprintManager.AuthenticationCallback { private Context context; private Handler handler; // Constructor public FingerPrintHandler(Context mContext, Handler handler) { context = mContext; this .handler = handler; } public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) { CancellationSignal cancellationSignal = new CancellationSignal(); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { return ; } manager.authenticate(cryptoObject, cancellationSignal, 0 , this , null ); } @Override public void onAuthenticationError( int errMsgId, CharSequence errString) { this .sendCallBack( "Fingerprint Authentication error\n" + errString, false ); } @Override public void onAuthenticationHelp( int helpMsgId, CharSequence helpString) { this .sendCallBack( "Fingerprint Authentication help\n" + helpString, false ); } @Override public void onAuthenticationFailed() { this .sendCallBack( "Fingerprint Authentication failed." , false ); } @Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { this .sendCallBack( "Fingerprint Authentication succeeded." , true ); } public void sendCallBack(String e, Boolean success) { Message message = new Message(); message.obj = e; message.arg1 = success ? 1 : 0 ; handler.sendMessage(message); } } |
MainActivity
Now the MainActivity that uses the class for the authentication and displays it in the UI.
package finger_print_demo.coderzheaven.com.fingerprintdemo; import android.Manifest; import android.annotation.TargetApi; import android.app.KeyguardManager; import android.content.pm.PackageManager; import android.graphics.Color; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.widget.TextView; import java.io.IOException; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.NoSuchPaddingException; import javax.crypto.SecretKey; public class MainActivity extends AppCompatActivity implements Handler.Callback { private static final String TAG = MainActivity. class .getSimpleName(); private KeyStore keyStore; private static final String KEY_NAME = "CoderzHeaven" ; private static final int FINGER_PRINT_PERMISSION = 1000 ; private Cipher cipher; private Handler handler; private TextView mStatus; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); handler = new Handler( this ); mStatus = (TextView) findViewById(R.id.mStatus); mStatus.setText( "Use the finger print sensor on your phone to authenticate." ); // Initializing both Android Keyguard Manager and Fingerprint Manager KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE); if (ActivityCompat.checkSelfPermission( this , Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions( this , new String[]{Manifest.permission.USE_FINGERPRINT}, FINGER_PRINT_PERMISSION); return ; } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (fingerprintManager.isHardwareDetected()) { if (fingerprintManager.hasEnrolledFingerprints()) { if (keyguardManager.isKeyguardSecure()) { generateKey(); if (cipherInit()) { FingerprintManager.CryptoObject cryptoObject = new FingerprintManager.CryptoObject(cipher); FingerPrintHandler helper = new FingerPrintHandler( this , handler); helper.startAuth(fingerprintManager, cryptoObject); } } } } } } @Override public void onRequestPermissionsResult( int requestCode, String permissions[], int [] grantResults) { switch (requestCode) { case FINGER_PRINT_PERMISSION: { Log.i( "Camera" , "G : " + grantResults[ 0 ]); // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[ 0 ] == PackageManager.PERMISSION_GRANTED) { // permission was granted, yay! Do the // contacts-related task you need to do. mStatus.setText( "Relaunch the app to take effect" ); } else { // permission denied, boo! Disable the // functionality that depends on this permission. // if (ActivityCompat.shouldShowRequestPermissionRationale // (this, Manifest.permission.CAMERA)) { // // showAlert(); // // } else { // // } } return ; } // other 'case' lines to check for other // permissions this app might request } } @TargetApi (Build.VERSION_CODES.M) protected void generateKey() { try { keyStore = KeyStore.getInstance( "AndroidKeyStore" ); } catch (Exception e) { e.printStackTrace(); } KeyGenerator keyGenerator; try { keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore" ); } catch (NoSuchAlgorithmException | NoSuchProviderException e) { throw new RuntimeException( "Failed to get KeyGenerator instance" , e); } try { keyStore.load( null ); keyGenerator.init( new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setUserAuthenticationRequired( true ) .setEncryptionPaddings( KeyProperties.ENCRYPTION_PADDING_PKCS7) .build()); keyGenerator.generateKey(); } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | CertificateException | IOException e) { throw new RuntimeException(e); } } @TargetApi (Build.VERSION_CODES.M) public boolean cipherInit() { try { cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { throw new RuntimeException( "Failed to get Cipher" , e); } try { keyStore.load( null ); SecretKey key = (SecretKey) keyStore.getKey(KEY_NAME, null ); cipher.init(Cipher.ENCRYPT_MODE, key); return true ; } catch (KeyPermanentlyInvalidatedException e) { return false ; } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) { throw new RuntimeException( "Failed to init Cipher" , e); } } @Override public boolean handleMessage(Message message) { Boolean success = (message.arg1 == 1 ) ? true : false ; if (success) { Log.i(TAG, "FingerPrint Authentication success" ); mStatus.setText( "Finger Print Authentication success" ); mStatus.setTextColor(Color.GREEN); } else { Log.i(TAG, "Finger Print Authentication failed" ); mStatus.setText(message.obj.toString()); } return false ; } } |
Source Code
You can download the complete source code from here…
Good wonderful