본문 바로가기

IT/Java언어

[안드로이드] 지문인식(fingerprint) 사용하기 (api<23도 가능)

안녕하세요 남갯입니다.


가입하고 처음 글을쓰게 되었는데요? 


예전에 지문인식을 통한 어플리케이션을 개발했었는데, 구글에서 제공하는 지문인식 샘을 이용하여 개발하였습니다.


구글에서 제공하는 지문인식 라이브러리 


https://github.com/googlesamples/android-FingerprintDialog


저는 오늘 구글에서 샘플로 제공한 지문인식 라이브러리를 통한 개발방법을 소개해드리려 합니다.


먼져 위 사이트에 접속하여




위 빨간 버튼을 이용하여 다운하고 압축을 푼후 프로젝트를 열어보도록 하겠습니다. (file - open - gradle 모양의 프로젝트)


일단 열어서 실행을 실행을 해보면 




         



맨 왼쪽의 화면이 나오게 됩니다.


 구매(purchase)나 구매 무효화 (invaldated) 버튼을 클릭하게되면 


2번째 사진과 같이 암호화 인증사진이 나오게되고 


지문을 통해 인증할 경우 3번사진, Use Password버튼을 클릭시 비밀번호를 통해 인증을 하는 예제입니다.


현재 구글에서 제공하는 지문인식의 경우 




프로젝트 왼쪽 아래 들어가보게 되면




minSdk가 23으로 나와있습니다.  즉 마시멜로우(6.0) 버젼이상만 이용가능 하다는거죠!!


하지만 minSdk의 경우 대부분 낮게 잡습니다..... 많은 단말기를 지원하기 위해서죠.... 23으로 잡을경우 23이하의 단말에는 지원이 안되게 되지요 ㅠㅠㅠ 아몰랑!!!!

따라서 저는 23이하의 프로젝트에도 갖다 써도 이용할 수 있도록 구성을 해보겠습니다.!!!




짝짝짝!!(자축중) 




자 이제 준비는 끝났으니 프로젝트를 하나 만들어 보겠습니다!



일단! 기본프로젝트를 생성합니다. minSdk는 17로 설정합니다!! 구글에서도 요즘 minSdk는 17로 나오더라구요


17이면 요즈음 웬만한 휴대폰은 돌아갑니다! 정말 초기버젼이 아니면요!




짜란!! 완성이 되었구요!


manifest에


<uses-permission android:name="android.permission.USE_FINGERPRINT" />


를 추가합니다 그리고


에라 모르겠다!!! 예제프로젝트의 클래스를 복사애서 붙여넣기합니다! 


방법은 왼쪽 프로젝트의 복사할 클래스를 ctrl - C 다들 아시죠?



요로코로 복사하고



ctrl - V를 누르면 이렇게 복사가 됩니다...


으 벌써부터 빨간줄이 확 뜹니다.... 이걸 어떻게 전부다 블로그에 옮겨야할지 모르겠지만


디자인적으로 설명하는게 아니므로 




요렇게 파란색으로 되어있는 파일들도 내가 만든 프로젝트의 동일한 위치로 옮겨줍니다. (ctrl c - ctrl v)


주의사항!!!  

샘플소스 xml 내에 style이 들어가 있습니다.

그 스타일은 minSdk 21이므로 스타일을 변경하거나 삭제하거나 공부를 한 후 변경하는것을 추천합니다.


일부 수정해야 하는 부분이 있으니 아래 사항을 참고하세요!


colors.xml

<resources>
<color name="colorPrimary">#3F51B5</color>
<color name="colorPrimaryDark">#303F9F</color>
<color name="colorAccent">#FF4081</color>
<color name="warning_color">#f4511e</color>
<color name="hint_color">#42000000</color>
<color name="success_color">#009688</color>
</resources>


String.xml

<resources>
<!--
The similar strings app_name is added in the Application/template directory, but depending
on the template directory makes it hard for the sample buildable with Android.mk.
Thus defining the application_name with different name from the template.
-->
<string name="app_name">FingerprintDialog</string>
<string name="action_settings">Settings</string>
<string name="cancel">Cancel</string>
<string name="use_password">Use password</string>
<string name="sign_in">Sign in</string>
<string name="ok">OK</string>
<string name="password">Password</string>
<string name="fingerprint_description">Confirm fingerprint to continue</string>
<string name="fingerprint_hint">Touch sensor</string>
<string name="password_description">Enter your store password to continue</string>
<string name="purchase">Purchase</string>
<string name="purchase_not_invalidated">Purchase not invalidated</string>
<string name="purchase_button_not_invalidated_description">
You can proceed to purchase with this button \n even if a new fingerprint is enrolled
</string>
<string name="fingerprint_not_recognized">Fingerprint not recognized. Try again</string>
<string name="fingerprint_success">Fingerprint recognized</string>
<string name="item_title">White Mesh Pluto Backpack</string>
<string name="item_price">$62.68</string>
<string name="item_description">Mesh backpack in white. Black textile trim throughout.</string>
<string name="purchase_done">Purchase successful</string>
<string name="new_fingerprint_enrolled_description">A new fingerprint was added to this device, so your password is required.</string>
<string name="use_fingerprint_in_future">Use fingerprint in the future</string>
<string name="use_fingerprint_to_authenticate_title">Use fingerprint to authenticate</string>
<string name="use_fingerprint_to_authenticate_key" >use_fingerprint_to_authenticate_key</string>
<string name="description_bugdroid_icon">Android bugdroid image</string>
<string name="description_fingerprint_icon">Fingerprint icon</string>
</resources>




이렇게 복사 붙여넣기를 하면 많은 FingerprintAuthenticationDialogFragment 클래스의 에러가 사라집니다.(레이아웃이나 스트링구성을 가져왔기 때문입니다)


그리고 그림도 가져옵니다! 그림같은경우 나중에는 다른그림을 이용할 때 변경하고 싶은 그림에 맞춰 변경을 하시면 됩니다.




일단 FingerprintManager는 최소 api가 23이다. 따라서 FingerprintManagerCompat을 이용해야한다. 


FingerprintManagerCompat 의 내부를 들어가보면 빌드버젼에 따라 다르게 이용하게 되어있다 즉

낮으면 낮은것에 맞게 높으면 높은것에 맞게 되어있다는 것이다!!!



변경해도 안되시는 분은 ctrl + space를 누르시면 위와같은 화면으로 선택이 가능하다.



-FingerprintManager의 것들을 FingerprintManagerCompat로 변경한다.


1. FingerprintUiHelper 의 생성자부분

2. onAuthenticationSucceeded   부분

3. startListening 부분


-getColor 의 api는 23이다

deprecated 된 theme부분을 안쓰는 getColor를 이용하면 이용할 수 있다. 

유연한 코드가 되려면 빌드버젼을 비교하여 getColor를 버젼에 따라 사용하는게 좋겠다.


public void startListening(FingerprintManager.CryptoObject cryptoObject) {
if (!isFingerprintAuthAvailable()) {
return;
}
mCancellationSignal = new CancellationSignal();
mSelfCancelled = false;
// The line below prevents the false positive inspection from Android Studio
// noinspection ResourceType
mFingerprintManager
.authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);
mIcon.setImageResource(R.drawable.ic_fp_40px);
}

그리고 FingerprintManager의 것들을 FingerprintManagerCompat로 변경됨과 동시에


mFingerprintManager
.authenticate(cryptoObject, mCancellationSignal, 0 /* flags */, this, null);

부분이 빨간색이 나오게된다. 전송하는 parameter 순서가 다르므로


mFingerprintManager
.authenticate(cryptoObject, 0 /* flags */ , mCancellationSignal, this, null);


순서를 바꿔주고!




취소신호 선언부에가서 ctrl + space를 통해 v4.os로 변경한다.



mCancellationSignal = new CancellationSignal();

이 생성자 부분도 ctrl + space를 이용해서 생성하면 된다.


mCancellationSignal = new android.support.v4.os.CancellationSignal();


요렇게 추가해줍니다


FingerprintUiHelper는 이름에서도 보시다싶이 UI를 담당하는 부분입니다. 

매개변수로 FingerprintManagerCompat 를 전송해야하지만 저는 Util클래스로 받아오고 쓸수있게 수정하였습니다

따라서 저의 생성자는 


FingerprintUiHelper(FingerprintManagerCompat fingerprintManager,
ImageView icon, TextView errorTextView, Callback callback) {
mFingerprintManager = fingerprintManager;
mIcon = icon;
mErrorTextView = errorTextView;
mCallback = callback;
}

이러한 형태에서 


FingerprintUiHelper(Context context, ImageView icon, TextView errorTextView, Callback callback) {
this.context = context;
this.mIcon = icon;
this.mErrorTextView = errorTextView;
this.mCallback = callback;
}

이러한 형태로 바꿉니다.


private final FingerprintManagerCompat mFingerprintManager;

는 외부 Util 클래스에서 불러올것이므로 삭제하고


Util 클래스를 다음과 같이 제작한다


public class Util {

public static boolean isFingerprintAuthAvailable(Context context) {
FingerprintManagerCompat mFingerprintManager;
mFingerprintManager = FingerprintManagerCompat.from(context);
if (mFingerprintManager.isHardwareDetected() && mFingerprintManager.hasEnrolledFingerprints()) {
return true;
} else {
return false;
}
}
public static FingerprintManagerCompat getFingerprintManagerCompat(Context context){
FingerprintManagerCompat mFingerprintManager;
mFingerprintManager = FingerprintManagerCompat.from(context);
return mFingerprintManager;
}

}


이렇게 제작한 이유는 매개변수로 넘겨준 FingerprintManagerCompat 값을 재사용하기 편하게 하기위해 제작하였다.

(다른방법으로 하셔도 무방합니다)



이렇게 하면 fingerprintUiHelper는 어느정도 완성이 되었다.



이제 FingerprintAuthenticationDialogFragment 로 가보자!




이번에도 동일하게 에러나는 부분을 제거해보겠다.




private FingerprintManager.CryptoObject mCryptoObject;


이부분과 관련된 부분을 compat 형태로 변경한다! 

private FingerprintManagerCompat.CryptoObject mCryptoObject;

나머지부분은 위에서 너무 많은 설명을 반복적으로 했으므로 생략한다.



그리고 아까 변경한 생성자에 맞게 변경한다


mFingerprintUiHelper = new FingerprintUiHelper(
mActivity.getSystemService(FingerprintManagerCompat.class),
(ImageView) v.findViewById(R.id.fingerprint_icon),
(TextView) v.findViewById(R.id.fingerprint_status), this);
updateStage();


이렇게 된 부분을 


mFingerprintUiHelper = new FingerprintUiHelper(getActivity().getApplicationContext(),
(ImageView) v.findViewById(R.id.fingerprint_icon),
(TextView) v.findViewById(R.id.fingerprint_status), this);
updateStage();


이렇게 변경한다



@onAttach 부분과 setCryptoObject 부분은 삭제한다.


필자는 등록부분은 삭제하였습니다. 기존에 스마트폰에 잠금으로 등록된 지문인식을 이용할 수 있게 만드는게 목적이였으므로

등록하는 부분은 과감히 삭제한다.


private void verifyPassword() {
if (!checkPassword(mPassword.getText().toString())) {
return;
}
if (mStage == Stage.NEW_FINGERPRINT_ENROLLED) {
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putBoolean(getString(R.string.use_fingerprint_to_authenticate_key),
mUseFingerprintFutureCheckBox.isChecked());
editor.apply();

if (mUseFingerprintFutureCheckBox.isChecked()) {
// Re-create the key so that fingerprints including new ones are validated.
mActivity.createKey(MainActivity.DEFAULT_KEY_NAME, true);
mStage = Stage.FINGERPRINT;
}
}
mPassword.setText("");
mActivity.onPurchased(false /* without Fingerprint */, null);
dismiss();
}


여기의 내용을 삭제하고 비밀번호를 sharedpreference로 저장하고 불러오도록 제작해보았다.


틀릴경우 좌우로 흔들리는 애니메이션을 통해 틀렸음을 알려주는 형태이다.



---------애니메이션 소스-----------

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="100"
android:fromXDelta="0"
android:toXDelta="20"
android:repeatCount="3"
android:repeatMode="reverse"
>
</translate>
</set>

---------------------------------



private void verifyPassword() {

if(mPassword.getText().toString().equals(mSharedPreferences.getString(Constant.PASSWORD_NUN ,"wrong" ))){
dismiss();
secretAuthorize.success();
mStage = Constant.FINGERPRINT;
}else{
mBackupContent.startAnimation(vibrateAnim);
mPassword.setText("");
}
}


인터페이스의 형태로 엑티비티로 성공여부를 전송해주는데

secretAuthorize.success();


public interface SecretAuthorize {
void success();
void fail();
}

의 인터페이스를 만들었다. 원래 생성자로 저 값을 전달할수 있는 클래스의경우 생성자를 통해 전달하지만

dialogFragment는 기본생성자 이외에 생성이 불가능하므로 


public void setCallback(SecretAuthorize secretAuthorize){
this.secretAuthorize = secretAuthorize;
}


을 통해 인터페이스를 메인에서 사용하도록 만들었다.



@Override
public void onAuthenticated() {
// Callback from FingerprintUiHelper. Let the activity know that authentication was
// successful.
mActivity.onPurchased(true /* withFingerprint */, mCryptoObject);
dismiss();
}


이부분에서 엑티비티로 성공값을 전달하는 부분인데


public void onAuthenticated() {
// Callback from FingerprintUiHelper. Let the activity know that authentication was
// successful.
dismiss();
secretAuthorize.success();
}


위에 생성한 인터페이스를 이용해 엑티비티에서 이용하게 만들었다.





기존에 구글에서 제공하는 소스를 minsdk 23 -> 17로 변경하는 작업이였다.


처음쓰는 글이였기에 무엇을 포함하고 무엇을 추가해야할지 몰라서 무작정 적었던거 같다.


궁금한점은 댓글 부탁드립니다!


더 발전해가겠습니다.



소스는 첨부파일에 올려놓을께요


https://github.com/namget/namgetfingerprint



안드로이드 지문인식에 대한 변경점에 대해 글쓴거 링크 첨부드립니다.


2019/01/09 - [Android/안드로이드 관련] - [안드로이드] 안드로이드 지문인식 변경점









'IT > Java언어' 카테고리의 다른 글

[JAVA] GC(가비지 컬렉터)의 동작원리  (0) 2019.12.12
[Java] String, StringBuilder, StringBuffer 란?  (0) 2019.12.08
effective java  (0) 2019.07.24
rxjava 책 추천 Rxjava 프로그래밍  (0) 2018.08.24