android 에서 printfinger 사용하는 방법 (API 23이상, Mashmellow 이상부터 사용가능)
참고사이트1 : https://munkijung1992.postype.com/post/1696370
참고사이트2 : http://altongmon.tistory.com/496
이렇게 지문을 띄워서 맞으면 성공처리를, 틀리면 TextView 가 흔들리는 Animaion 과 함께 Toast 를 띄웠다.
사용자마다 지문을 DB 나 SharePreference 에 등록하여 지문로그인을 구현해볼까도 했지만,
스케줄 상 일단 지문일치여부 구현만으로도 만족..!
그리고, 지문인식을 사용하기 위해 찾아보니 그나마 많이 쓰는 라이브러리가 있대서 사용하려했지만
자꾸 Gradle 에서 Compile 이 안되어가지고 직접 구현했다 ㅠ.ㅠ
* 사용방법 *
1. AndroidManifest.xml 에 지문인식 권한을 위한 퍼미션 추가
1 2 | <!-- 지문인식에 필요함 --> <uses-permission android:name="android.permission.USE_FINGERPRINT" /> | cs |
2. 다이얼로그로 띄울 예정이므로 보여줄 res-layout 에 dialog_fingerprint.xml 추가
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout 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:orientation="vertical" android:layout_width="200dp" android:layout_height="match_parent" android:padding="5dp"> <ImageView android:layout_width="30dp" android:layout_height="30dp" android:layout_gravity="center" android:layout_marginTop="10dp" app:srcCompat="@drawable/fingerprint" /> <TextView android:id="@+id/dialog_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:paddingBottom="20dp" android:paddingTop="20dp" android:text="정말 탈퇴하시겠습니까?" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/dialog_cancel" android:layout_width="match_parent" android:layout_height="30dp" android:layout_gravity="center" android:background="@drawable/button_radius" android:text="취소" android:textColor="@color/color_white" /> <Button android:id="@+id/dialog_submit" android:layout_width="match_parent" android:layout_height="30dp" android:layout_gravity="center" android:layout_weight="1" android:background="@drawable/button_radius" android:text="안보여야함" android:textColor="@color/color_white" android:visibility="gone"/> <!-- style="?android:attr/borderlessButtonStyle" --> </LinearLayout> </LinearLayout> | cs |
3. 지문인식을 사용할 Activity 나 Fragment 상단에 필드값을 선언해주고
1 2 3 | //지문인식 관련 필드 TextView shakeText; CustomDialog customDialog; | cs |
4. 지문인식을 사용할 Activity 나 Fragment 에 이벤트리스너가 있다면 그 안에 다이얼로그를 띄울 5,6 번째 줄을 추가해준다.
1 2 3 4 5 6 7 8 | //회원탈퇴 버튼 => 지문인식으로 본인확인 ((Button)getView().findViewById(R.id.mypage_quit)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { customDialog = new CustomDialog(getContext(),R.layout.dialog_fingerprint); customDialog.show(); } }); | cs |
5. 지문인식을 사용할 Activity 나 Fragment 하단에 정의해둔 custom 메소드를 추가해준다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | public class CustomDialog extends Dialog { Button btn; EditText editPass; public CustomDialog(final Context context, int layoutResID) { super(context); if(layoutResID==R.layout.dialog_fingerprint){ FingerPrint fingerPrint = new FingerPrint(getContext()); if(fingerPrint.isFingerHarWare()){ if(fingerPrint.isFingerPassCode()){ fingerPrint.initalize(new FingerprintManager.AuthenticationCallback() { @Override //지문인증에 치명적인 오류가 발생하면 호출 public void onAuthenticationError(int errMsgId, CharSequence errString) { Toast.makeText(getContext(), "Authentication error\n" + errString, Toast.LENGTH_SHORT).show(); } @Override //오류가 발생하면 호출되지만 치명적인 예외는 아님 public void onAuthenticationHelp(int helpMsgId,CharSequence helpString) { Toast.makeText(getContext(), "Authentication help\n" + helpString, Toast.LENGTH_SHORT).show(); } @Override //장치에 등록 된 지문이 아닌 경우 호출 public void onAuthenticationFailed() { Toast.makeText(getContext(), "등록되지 않은 지문입니다.", Toast.LENGTH_SHORT).show(); //틀렸을 시 텍스트 좌우로 흔들어주기 Animation shake = AnimationUtils.loadAnimation(getContext(), R.anim.shake); shakeText = (TextView)findViewById(R.id.dialog_text); shakeText.startAnimation(shake); } @Override //장치에 등록 된 지문이 스캔되었을 때 호출 public void onAuthenticationSucceeded( FingerprintManager.AuthenticationResult result) { clientSocketThread = new ClientSocketThread(handler, "quitUser", userVO); clientSocketThread.start(); dismiss(); } }); }else{ startActivity(new Intent(Settings.ACTION_SECURITY_SETTINGS)); } } } //getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); //다이얼로그의 배경을 투명으로 만듦 requestWindowFeature(Window.FEATURE_NO_TITLE); //다이얼로그의 타이틀바를 없애줌 setContentView(layoutResID); //다이얼로그에서 사용할 레이아웃 //취소버튼 => 지문인식에 있음 ((Button)findViewById(R.id.dialog_cancel)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { dismiss(); } }); //확인버튼 => 비밀번호변경에 있음 ((Button)findViewById(R.id.dialog_submit)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { editPass = (EditText)findViewById(R.id.dialog_edit_password); userVO.setPassword(editPass.getText().toString()); clientSocketThread = new ClientSocketThread(handler, "updateUser", userVO); clientSocketThread.start(); Toast.makeText(getContext(), "정상적으로 변경되었습니다.", Toast.LENGTH_SHORT).show(); dismiss(); } }); } } //e.o.CustomDialog | cs |
6. 마지막으로 지문인식 사용을 위해 FingerprintManager 와 Keystore 와 KeyGenerator 와 Cipher 를 사용할 클래스를 생성해준다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | package com.nadri.util; import android.content.Context; import android.hardware.fingerprint.FingerprintManager; import android.os.Build; import android.os.CancellationSignal; import android.security.keystore.KeyGenParameterSpec; import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; import android.support.annotation.RequiresApi; import java.io.IOException; import java.security.InvalidKeyException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; 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; //지문인식 기능은 6.0 이상부터 지원되어 실제 우리 어플에서 사용가능하다는 의미로 선언 @RequiresApi(api = Build.VERSION_CODES.M) public class FingerPrint { private static final String KeyName = "yourKeyPassword"; private static final String AndroidKeyStore = "AndroidKeyStore"; private Context mContext; private FingerprintManager fingerprintManager; private FingerprintManager.CryptoObject cryptoObject; private KeyStore keyStore; private KeyGenerator keyGenerator; private Cipher cipher; //생성자 public FingerPrint(Context mContext) { this.mContext = mContext; setKeyStore(); } //콜백 초기화 메소드 public void initalize(FingerprintManager.AuthenticationCallback callback) { CancellationSignal cancellationSignal = new CancellationSignal(); //취소신호 fingerprintManager.authenticate(cryptoObject, cancellationSignal, 0, callback, null); } //하드웨어 지원 가능 여부 public boolean isFingerHarWare(){ return fingerprintManager.isHardwareDetected(); } //하드웨어 현재 지문 여부 public boolean isFingerPassCode(){ return fingerprintManager.hasEnrolledFingerprints(); } //KeyStore 세팅 private void setKeyStore() { //FingerPrint Manager Setting fingerprintManager = (FingerprintManager) mContext.getSystemService(Context.FINGERPRINT_SERVICE); cryptoObject = new FingerprintManager.CryptoObject(cipher); //keyStore //표준 android 키 저장소 컨테이너 식별자 ("AndroidKeyStore")를 사용하여 키 저장소에 대한 참조를 가져옴 try { keyStore = KeyStore.getInstance(AndroidKeyStore); } catch (KeyStoreException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } //keyGenerator try { //key 생성 keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, AndroidKeyStore); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } //keyGenerator initalize //새 개인 키 생성 try { //빈 ketStore 초기화 keyStore.load(null); //keyGenerator 초기화 keyGenerator.init(new KeyGenParameterSpec.Builder(KeyName, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setBlockModes(KeyProperties.BLOCK_MODE_CBC) .setUserAuthenticationRequired(true) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_PKCS7) .build()); //key 생성 keyGenerator.generateKey(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } // cipher initalize try { cipher = Cipher.getInstance(KeyProperties.KEY_ALGORITHM_AES + "/" + KeyProperties.BLOCK_MODE_CBC + "/" + KeyProperties.ENCRYPTION_PADDING_PKCS7); } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } // cipher set Key try { keyStore.load(null); SecretKey key = (SecretKey) keyStore.getKey(KeyName, null); cipher.init(Cipher.ENCRYPT_MODE, key); } catch (KeyPermanentlyInvalidatedException e) { e.printStackTrace(); } catch (KeyStoreException | CertificateException | UnrecoverableKeyException | IOException | NoSuchAlgorithmException | InvalidKeyException e) { e.printStackTrace(); } } } | cs |
7. 위에까지 하면 되지만, 틀렸을 때 텍스트뷰가 흔들리는 애니메이션을 보여주기 위해 res 에 anim 폴더를 만들고 shake.xml 을 생성해주면 정말 끝!
1 2 3 4 5 | <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="0" android:toXDelta="10" android:duration="500" android:interpolator="@anim/cycle_3" /> <!-- 0.5초 동안 X10 만큼 3번 흔들어라 --> | cs |
'MOBILE > Android' 카테고리의 다른 글
안드로이드 Browser (Internet) 띄우기 (0) | 2018.08.03 |
---|---|
[Android] Fragment 뒤로가기 버튼누르면 이전 Fragment 보여지게 하는 방법 (4) | 2018.08.03 |
안드로이드 ImageView 에 이미지를 URL로 가져와서 뿌려주는 방법 (4) | 2018.08.03 |
안드로이드 원하는 뷰 좌우로 흔들리게 애니메이션 설정하는 방법 (0) | 2018.08.03 |
안드로이드 이미지 본연의 크기를 고집하는 xml 소스 (0) | 2018.08.03 |
댓글