Android : 내 앱에만 암호 / PIN을 설정하는 방법은 무엇입니까?

Nov 19 2020

사용자가 백그라운드에서 앱을 열 때마다 앱에서 암호 / 암호 / 핀을 요청하도록 사용자에 대한 암호 / 암호 / 핀을 설정하여 보안 기능을 설정해야하는 앱을 개발 중입니다. 내가 좋아하는 몇 가지 기사 / 솔루션 읽기 이 있지만 저를 도움이되지 않았다. 앱을 열 때마다 암호 / 지문을 요구하는 일반 뱅킹 앱과 동일한 기능입니다.

공유 기본 설정에서 암호 / 핀을 저장하는 논리를 이미 설정했지만 언제 물어봐야할지 모르겠습니다. 때때로 앱의 homeScreen / MainActivity에서 사용자가 홈 버튼을 누르고 최근 앱에서 앱을 다시 열 때 앱이 다시 시작하기 위해 암호 / 핀을 요청해야하기 때문에 스플래시 화면을 암호 / 핀 활동으로 바꿀 수 없다는 것을 알고 있습니다. 앱 사용.

어떤 도움을 주시면 감사하겠습니다.

답변

SonTruong Nov 20 2020 at 11:59

이것은 흥미로운 질문입니다.이 질문에 대한 제 생각을 공유하고 해결책도 제시하겠습니다.

술어:

앱 잠금 유형 : 핀 / 비밀번호 / 비밀번호 / 비밀번호 등의 일반적인 이름 (다음 섹션에서는 핀 이름을 사용하여 설명합니다)

PinActivity : 사용자가 자신을 확인하기 위해 핀을 입력하는 화면

이야기:

사용자가 핀을 입력해야하는 앱의 경우 일반적으로 민감한 정보가 다른 사람에 의해 유출 / 도난되지 않도록해야합니다. 그래서 우리는 앱 활동을 두 그룹으로 분류 할 것입니다.

  • 일반 활동 : 일반적으로 사용자가 앱에 로그인하기 전에 SplashActivity, LoginActivity, RegistrationActivity, PinActivity 등과 같은 민감한 정보를 포함하지 않습니다.

  • 보안 활동 : 일반적으로 사용자가 로그인 한 후 MainActivity, HomeActivity, UserInfoActivity 등과 같은 민감한 정보를 포함합니다.

정황:

보안 활동을 위해서는 PinActivity를 표시하여 콘텐츠를보기 전에 사용자가 항상 핀을 입력하도록해야합니다. 이 활동은 다음 시나리오에서 표시됩니다.

  • [1] 사용자가 보안 활동을 열면 SplashActivity에서 MainActivity로와 같은 정상적인 활동이 형성됩니다.

  • [2] 사용자가 알림을 탭하여 보안 활동을 열 때 (예 : 알림을 탭하여 MainActivity를 여는 등)

  • [3] 사용자가 최근 화면에서 앱을 탭할 때

  • [4] 앱이 서비스, 방송 수신기 등과 같은 다른 장소에서 보안 활동을 시작하는 경우

이행:

케이스 [1] [2] 및 [4]의 경우 보안 활동을 시작하기 전에 원래 인 텐트에 추가 항목을 추가합니다. IntentUtils.kt라는 파일을 생성하겠습니다.

IntentUtils.kt

const val EXTRA_IS_PIN_REQUIRED = "EXTRA_IS_PIN_REQUIRED"

fun Intent.secured(): Intent {
    return this.apply {
        putExtra(EXTRA_IS_PIN_REQUIRED, true)
    }
}

일반 활동, 알림, 서비스 등에서이 클래스를 사용합니다.

startActivity(Intent(this, MainActivity::class.java).secured())

사례 [3]의 경우 2 개의 API를 사용합니다.

  • ProcessLifecycleOwner : 앱이 백그라운드로 전환되는지 여부를 감지합니다. 일반적인 시나리오는 사용자가 장치에서 홈 / 메뉴 키를 클릭하는 경우입니다.

  • ActivityLifecycleCallbacks : onActivityResumed (activity) 메서드를 사용 하여 활동이 재개되는지 여부를 감지합니다 .

먼저 기본 활동을 만듭니다. 모든 정상적인 활동 염은이 클래스에서 확장되어야합니다.

BaseActivity.kt

open class BaseActivity : AppCompatActivity() {
    
    // This method indicates that a pin is required if 
    // users want to see the content inside.
    open fun isPinRequired() = false
}

두 번째로 보안 활동을 작성합니다. 모든 보안 활동은이 클래스에서 확장되어야합니다.

SecuredActivity.kt

open class SecuredActivity : BaseActivity() {
    override fun isPinRequired() = true

    // This is useful when launch a secured activity with 
    // singleTop, singleTask, singleInstance launch mode
    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        setIntent(intent)
    }
}

세 번째로 Application에서 확장되는 클래스를 만듭니다. 모든 로직은이 클래스 안에 있습니다.

MyApplication.kt

class MyApplication : Application() {

    private var wasEnterBackground = false

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(ActivityLifecycleCallbacksImpl())
        ProcessLifecycleOwner.get().lifecycle.addObserver(LifecycleObserverImpl())
    }

    private fun showPinActivity() {
        startActivity(Intent(this, PinActivity::class.java))
    }

    inner class LifecycleObserverImpl : LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
        fun onEnterBackground() {
            wasEnterBackground = true
        }
    }

    inner class ActivityLifecycleCallbacksImpl : ActivityLifecycleCallbacks {

        override fun onActivityResumed(activity: Activity) {
            val baseActivity = activity as BaseActivity
            if (!wasEnterBackground) {
                // Handle case [1] [2] and [4]
                val removed = removeIsPinRequiredKeyFromActivity(activity)
                if (removed) {
                    showPinActivity()
                }
            } else {
                // Handle case [3]
                wasEnterBackground = false
                if (baseActivity.isPinRequired()) {
                    removeIsPinRequiredKeyFromActivity(activity)
                    showPinActivity()
                }
            }
        }

        private fun removeIsPinRequiredKeyFromActivity(activity: Activity): Boolean {
            val key = EXTRA_IS_PIN_REQUIRED
            if (activity.intent.hasExtra(key)) {
                activity.intent.removeExtra(key)
                return true
            }
            return false
        }

        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {}
        override fun onActivityStarted(activity: Activity) {}
        override fun onActivityPaused(activity: Activity) {}
        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
        override fun onActivityStopped(activity: Activity) {}
        override fun onActivityDestroyed(activity: Activity) {}
    }
}

결론:

이 솔루션은 이전에 언급 한 경우에 적합하지만 다음 시나리오는 테스트하지 않았습니다.

  • 시작시 보안 된 활동에는 시작 모드 singleTop | singleTask | singleInstance가 있습니다.
  • 메모리 부족에서 시스템이 응용 프로그램을 종료 할 때
  • 누군가가 접할 수있는 다른 시나리오 (있는 경우 의견 섹션에서 알려주십시오).