เริ่มจากอธิบายก่อน Fingerprint API เพิ่งจะเพิ่มมาใน API Level 23 หรือ Android M เพราะฉะนั้นหากต่ำกว่านั้นจะไม่สามารถเรียกใช้งานได้ (แต่ใน Samsung galaxy s6 : Lollipop นั้น samsung เขียน library ขึ้นมาเอง สามารถตามไปศึกษาได้ที่ http://developer.samsung.com/resources/pass ) แต่ใน blog นี้เราจะมาเรียนรู้ fingerprint api ที่ android พัฒนาขึ้นมาเอง และเราต้องใช้ fingerprint ของเครื่อง ไม่สามารถจะสร้างลายนิ้วมือได้เอง ต้องไปเปิดการใช้งานและเพิ่มลายนิ้วมือใน setting ของเครื่องก่อน งั้นเรามาเริ่มกันเลย
เพิ่ม permission : USE_FINGERPRINT ใน AndroidManifest.xml
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
กลับมาที่ Activity หลักของเราเริ่มจากประกาศตัวแปรที่เราจะใช้งาน
private FingerprintManager fingerprintManager; private KeyguardManager keyguardManager;
ตรวจสอบเวอร์ชั่นเครื่องว่ารองรับการใช้งาน fingerprint ไหม
* isHardwareDetected จะขึ้นแดงเตือนให้ checkPermission ไม่ต้องเช็คก็ได้นะครับ เพราะไม่ได้อยู่ในกลุ่ม dangerous permissions สามารถไปดูว่า permission ตัวไหนอยู่ในกลุ่ม normal หรือ dangerous จากตรงนี้ http://developer.android.com/guide/topics/security/permissions.html#normal-dangerous
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); . . . //เช็คเวอร์ชั่นของเครื่องต้อง >= 6.0 M จึงจะใช้งาน fingerprintManager ได้ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE); if (fingerprintManager.isHardwareDetected()) { // Device support fingerprint authentication setupFingerPrint(); }else{ txtTitle.setText("Please fill password"); } } else { txtTitle.setText("Please fill password"); } }
หลักจากตรวจสอบแล้วว่า fingerprint สามารถใช้งานได้ก็เริ่มทำเมธอด setupFingerPrint() ถ้าไม่รองรับ fingerprint ก็ให้ title แสดง Please fill password
private void setupFingerPrint() { if (!keyguardManager.isKeyguardSecure()) { // Show a message that the user hasn't set up a fingerprint or lock screen. Toast.makeText(this, "Secure lock screen hasn't set up.\n" + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint", Toast.LENGTH_LONG).show(); return; } if (!fingerprintManager.hasEnrolledFingerprints()) { // This happens when no fingerprints are registered. Toast.makeText(this, "Go to 'Settings -> Security -> Fingerprint' and register at least one fingerprint", Toast.LENGTH_LONG).show(); return; } }
อธิบาย
- keyguardManager.isKeyguardSecure() ตรวจสอบว่าเครื่องได้เปิดการใช้งาน fingerprint ไหม ถ้าไม่ก็ให้แสดงข้อความ
- fingerprintManager.hasEnrolledFingerprints() ตรวจสอบว่าเครื่องได้มีการเพิ่มลายนิ้วมือแล้วหรือยัง ถ้าไม่ก็ให้แสดงข้อความ
หากตรวจสอบแล้วว่าเครื่องเปิดใช้งาน fingerprint และ มีลายนิ้วมือในระบบแล้วก็มาทำ createKey หากจะอัพขึ้นสโตร์ให้เปลี่ยนชื่อ my_key เป็น ชื่อ alias ของ keystore ด้วยนะครับ
/** * Alias for our key in the Android Key Store */ private static final String KEY_NAME = "my_key"; private KeyStore keyStore; private KeyGenerator keyGenerator;
/** * Creates a symmetric key in the Android Key Store which can only be used after the user has * authenticated with fingerprint. */ public void createKey() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { // The enrolling flow for fingerprint. This is where you ask the user to set up fingerprint // for your flow. Use of keys is necessary if you need to know if the set of // enrolled fingerprints has changed. try { keyStore = KeyStore.getInstance("AndroidKeyStore"); } catch (Exception e) { e.printStackTrace(); } 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); // Set the alias of the entry in Android KeyStore where the key will appear // and the constrains (purposes) in the constructor of the Builder keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_NAME, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) // Require the user to authenticate with a fingerprint to authorize every use // of the key .setUserAuthenticationRequired(true) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .build()); keyGenerator.generateKey(); Log.d("main", "createKey: keyGenerate"); } catch (NoSuchAlgorithmException | InvalidAlgorithmParameterException | CertificateException | IOException e) { throw new RuntimeException(e); } }
และต่อด้วย Cipher
/** * Initialize the {@link Cipher} instance with the created key in the {@link #createKey()} * method. * * @return {@code true} if initialization is successful, {@code false} if the lock screen has * been disabled or reset after the key was generated, or if a fingerprint got enrolled after * the key was generated. */ private boolean initCipher() { 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); } }
แล้วก็สร้าง class FingerprintHelper ขึ้นมาเพื่อตรวจสอบลายนิ้วมือ
public class FingerprintHelper extends FingerprintManager.AuthenticationCallback { private CancellationSignal cancellationSignal; private Context context; public FingerprintHelper(Context context) { this.context = context; } //เริ่มตรวจสอบลายนิ้วมือ public void startAuth(FingerprintManager manager, FingerprintManager.CryptoObject cryptoObject) { cancellationSignal = new CancellationSignal(); if (ActivityCompat.checkSelfPermission(context, Manifest.permission.USE_FINGERPRINT) != PackageManager.PERMISSION_GRANTED) { return; } manager.authenticate(cryptoObject, cancellationSignal, 0, this, null); } //หยุดตรวจสอบลายนิ้วมือ public void stopListening() { if (cancellationSignal != null) { cancellationSignal.cancel(); cancellationSignal = null; } } @Override public void onAuthenticationError(int errorCode, CharSequence errString) { super.onAuthenticationError(errorCode, errString); Log.e("FingerprintHelper", "onAuthenticationError:" + errString ); } @Override public void onAuthenticationHelp(int helpCode, CharSequence helpString) { super.onAuthenticationHelp(helpCode, helpString); Toast.makeText(context, "Authentication help\n" + helpString, Toast.LENGTH_LONG).show(); } @Override public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) { super.onAuthenticationSucceeded(result); new AlertDialog.Builder(context) .setCancelable(false) .setMessage("Fingerprint Authentication succeeded") .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); ((MainActivity) context).onResume(); } }).show(); } @Override public void onAuthenticationFailed() { super.onAuthenticationFailed(); Toast.makeText(context, "Authentication failed.", Toast.LENGTH_LONG).show(); } }
จากนั้นก็เรียกใช้งานในเมธอด setupFingerprint
private FingerprintManager.CryptoObject cryptoObject; private FingerprintHelper fingerprintHelper;
private void setupFingerPrint() { if (!keyguardManager.isKeyguardSecure()) { // Show a message that the user hasn't set up a fingerprint or lock screen. Toast.makeText(this, "Secure lock screen hasn't set up.\n" + "Go to 'Settings -> Security -> Fingerprint' to set up a fingerprint", Toast.LENGTH_LONG).show(); return; } if (!fingerprintManager.hasEnrolledFingerprints()) { // This happens when no fingerprints are registered. Toast.makeText(this, "Go to 'Settings -> Security -> Fingerprint' and register at least one fingerprint", Toast.LENGTH_LONG).show(); return; } createKey(); if (initCipher()) { cryptoObject = new FingerprintManager.CryptoObject(cipher); fingerprintHelper = new FingerprintHelper(this); } }
แล้วจึง override สองเมธอดนี้เพื่อสั่งให้ fingerprint ทำงานหรือหยุดทำงาน
@Override protected void onResume() { super.onResume(); if (fingerprintHelper != null) { fingerprintHelper.startAuth(fingerprintManager, cryptoObject); } } @Override protected void onPause() { super.onPause(); if (fingerprintHelper != null) { fingerprintHelper.stopListening(); } }
ที่นี้แล้วก็สามารถตรวจสอบแล้วนิ้วมือได้แล้ว หากตรวจสอบลายนิ้วมือตรงกับที่ลงทะเบียนในเครื่องไว้จะแสดง dialog แต่หากไม่ตรงกัน ก็จะ Toast แจ้งเตือน user แล้วหากเครื่องไม่รองรับ fingerprint แหละ เราก็มาทำส่วนของตรวจสอบรหัสผ่าน 4 ตัวกัน เริ่มจาก เมธอด checkPassword()
private void checkPassword(TabLayout.Tab tab) { if (tab.getPosition() == 1) { String password = editTextPassword.getText().toString().trim(); // example password = 1234 if (password.equals("1234")) { new AlertDialog.Builder(MainActivity.this) .setCancelable(false) .setMessage("Password Authentication succeeded") .setPositiveButton("ok", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); textInputLayout.setError(null); } }).show(); } else { textInputLayout.setError("Password incorrect"); } } }
แล้วจากนั้นก็เรียกใช้งานใน
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() { @Override public void onTabSelected(TabLayout.Tab tab) { checkPassword(tab); } @Override public void onTabUnselected(TabLayout.Tab tab) { } @Override public void onTabReselected(TabLayout.Tab tab) { checkPassword(tab); } });
เป็นอันเสร็จเรียบร้อย
DownloadExampleCode
Reference
- http://www.techotopia.com/index.php/An_Android_Fingerprint_Authentication_Tutorial
- http://android-developers.blogspot.com/2015/10/new-in-android-samples-authenticating.html
Want To Be An Android Dev.: Android : Fingerprint Api Tutorial [การใช้งาน Fingerprint Unlock] >>>>> Download Now
ตอบลบ>>>>> Download Full
Want To Be An Android Dev.: Android : Fingerprint Api Tutorial [การใช้งาน Fingerprint Unlock] >>>>> Download LINK
>>>>> Download Now
Want To Be An Android Dev.: Android : Fingerprint Api Tutorial [การใช้งาน Fingerprint Unlock] >>>>> Download Full
>>>>> Download LINK 0R