Seize the day

POST : Android Dev Study

안드로이드 지문 체크 하기

체크 리스트앱에 비밀번호를 설정해서 쓰는데, 매번 숫자 쳐넣기가 귀찮아서 OS에 등록한 지문을 체크하도록 개선 했다. 


지문은 안드로이드 6.0 Api 23(마시멜로) 부터 사용가능하다. 

https://github.com/googlesamples/android-FingerprintDialog/blob/master/Application/src/main/java/com/example/android/fingerprintdialog/FingerprintUiHelper.java 참고해서 

FingerprintUiHelper.kt를 구현

typealias FingerprintUiHelperCallback = () -> Unit

@TargetApi(Build.VERSION_CODES.M)
class FingerprintUiHelper(
private val fingerprintManager: FingerprintManager?,
private val icon: ImageView,
private val errorTextView: TextView
) : FingerprintManager.AuthenticationCallback() {

companion object {
private const val ERROR_TIMEOUT_MILLIS: Long = 1600
}

private var cancellationSignal: CancellationSignal? = null
private var selfCancelled: Boolean = false
private val isFingerprintAuthAvailable: Boolean
get() = fingerprintManager?.isHardwareDetected == true && fingerprintManager.hasEnrolledFingerprints()

private var resetErrorTextRunnable: Runnable = Runnable {
errorTextView.text = errorTextView.resources.getString(R.string.fingerprint_hint)
icon.setImageResource(R.drawable.ic_fp_40px)
}

var onAuthenticatedCallback: FingerprintUiHelperCallback = {}
var onErrorCallback: FingerprintUiHelperCallback = {}

fun startListening(): Boolean {
if (!isFingerprintAuthAvailable) {
return false
}
cancellationSignal = CancellationSignal()
selfCancelled = false
fingerprintManager
?.authenticate(null, cancellationSignal, 0 /* flags */, this, null)
icon.setImageResource(R.drawable.ic_fp_40px)

return true
}

fun stopListening() {
if (cancellationSignal != null) {
selfCancelled = true
cancellationSignal!!.cancel()
cancellationSignal = null
}
}

override fun onAuthenticationError(errMsgId: Int, errString: CharSequence) {
if (!selfCancelled) {
showError(errString)
icon.postDelayed({ onErrorCallback() }, ERROR_TIMEOUT_MILLIS)
}
}

override fun onAuthenticationHelp(helpMsgId: Int, helpString: CharSequence) {
showError(helpString)
}

override fun onAuthenticationFailed() {
showError(
icon.resources.getString(
R.string.fingerprint_not_recognized
)
)
}

override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
errorTextView.removeCallbacks(resetErrorTextRunnable)
icon.setImageResource(R.drawable.ic_fingerprint_success)
errorTextView.text = errorTextView.resources.getString(R.string.fingerprint_success)
onAuthenticatedCallback()
}

private fun showError(error: CharSequence) {
icon.setImageResource(R.drawable.ic_fingerprint_error)
errorTextView.text = error
errorTextView.removeCallbacks(resetErrorTextRunnable)
errorTextView.postDelayed(resetErrorTextRunnable, ERROR_TIMEOUT_MILLIS)
}
}

리소스나 스트링은 github을 참고하면 되기에 생략한다.


지문을 체크하는 View를 하나 만든다. 지문 체크 페이지의 특정 viewGroup에 addView하여 지문 기능을 Injection한다.

FingerprintAuthView.kt

@TargetApi(Build.VERSION_CODES.M)
class FingerprintAuthView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyleAttr, defStyleRes) {

private var fingerprintUiHelper: FingerprintUiHelper
private var layout: View = LayoutInflater.from(context).inflate(R.layout.fingerprint_auth_view, null)

init {
fingerprintUiHelper = FingerprintUiHelper(
context.getSystemService(FingerprintManager::class.java),
layout.findViewById(R.id.passcode_fingerprint_image),
layout.findViewById(R.id.passcode_fingerprint_status)
)
addView(
layout,
LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT)
)
layout.visibility = View.GONE
}

override fun onAttachedToWindow() {
super.onAttachedToWindow()
val isStarted = fingerprintUiHelper.startListening()
layout.visibility = if (isStarted) View.VISIBLE else View.GONE
}

override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
fingerprintUiHelper.stopListening()
}

fun setOnAuthenticated(callback: FingerprintUiHelperCallback) {
fingerprintUiHelper.onAuthenticatedCallback = callback;
}

fun setOnError(callback: FingerprintUiHelperCallback) {
fingerprintUiHelper.onErrorCallback = callback
}
}


AuthView를 injection해보자. 

PassCodeActivity.java

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& mMode == PassCodeMode.Confirm) {
LinearLayout linearLayout = findViewById(R.id.linearLayout1);
FingerprintAuthView authView = new FingerprintAuthView(this);
authView.setOnAuthenticated(new Function0<Unit>() {
@Override
public Unit invoke() {
finish();
return null;
}
});
linearLayout.addView(authView);
}

권한 추가도 잊지말것

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


top

posted at

2019. 1. 3. 00:07


CONTENTS

Seize the day
BLOG main image
김대정의 앱 개발 노트와 사는 이야기
RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글
카테고리 태그 구름사이트 링크