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