Android9.0在鎖屏界面Keyguard輸錯5次密碼後倒計時30秒時重啓手機不顯示倒計時

最近解了一個bug,覺得很有意思,拿出來和大家分享一下。
鎖屏密碼輸錯五次後出現倒計時,重啓設備不顯示倒計時。
首先,以圖案解鎖爲例,圖案解鎖的初始化和邏輯比對都在KeyguardPatternView.java中
倒計時方法用的是該類中的handleAttemptLockout(long elapsedRealtimeDeadline)方法,傳入一個獲取的系統休眠時間,該時間是設備啓動至現在的時間,再加上你所設置的休眠時間。

long mDeadline = mLockPatternUtils.setLockoutAttemptDeadline(
                           KeyguardUpdateMonitor.getCurrentUser(), 30000);//傳入的handleAttemptLockout的
                           //elapsedRealtimeDeadline就是這樣設置的,30000爲休眠的30秒

休眠方法知道了,我的整體思路是我在SettingsProvider裏存了一個值默認0,然後在倒計時的時候將這個值置爲1,倒計時結束再置爲0,在KeyguardPatternView.java的每次啓動方法中去讀取這個值,如果是0就什麼都不做,如果是1就開始倒計時。

OK,萬事具備,只欠東風,就是一個KeyguardPatternView.java的每次啓動都會運行的方法,剛開始我嘗試在KeyguardPatternView的構造方法中去做這些事,結果一直在報 mLockPatternView空指針,大家可以觀察handleAttemptLockout方法

private void handleAttemptLockout(long elapsedRealtimeDeadline) {
    mLockPatternView.clearPattern();//需要清除當前圖像
    mLockPatternView.setEnabled(false);//設置不可點擊
    final long elapsedRealtime = SystemClock.elapsedRealtime();
    final long secondsInFuture = (long) Math.ceil(
            (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
    if (mCountdownTimer != null) {
        mCountdownTimer.cancel();
    }
    mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {

handleAttemptLockout方法需要清除當前圖像,並且設置不可點擊,所以我們需要在mLockPatternView創建好後去執行這些方法,後來我又嘗試在KeyguardPatternView.java的onFinishInflate()方法,但是發現它並不是每次的執行,所以也不行,最後我終於找到每次都會執行的方法就是KeyguardPatternView.java的 reset()方法,該方法每次加載PatternView都會執行

具體代碼實現如下:
 @Override
 public void reset() {
    // reset lock pattern
    mLockPatternView.setInStealthMode(!mLockPatternUtils.isVisiblePatternEnabled(
            KeyguardUpdateMonitor.getCurrentUser()));
    mLockPatternView.enableInput();
    mLockPatternView.setEnabled(true);
    mLockPatternView.clearPattern();
    //add for count time at 2019-5-14 start 這裏開始
    Log.v(TAG, "reset() COUNT_DOWNTIME_UNLOCK ="+Settings.System.getInt(mContext.getContentResolver(),Settings.System.COUNT_DOWNTIME_UNLOCK,0)+"mLockPatternView = "+mLockPatternView);

    if (Settings.System.getInt(mContext.getContentResolver(),Settings.System.COUNT_DOWNTIME_UNLOCK,0) == 1 && mLockPatternView != null){//這裏去讀取存入值
     long mDeadline = mLockPatternUtils.setLockoutAttemptDeadline(
                           KeyguardUpdateMonitor.getCurrentUser(), 30000);這裏去設置休眠時間
     Log.v(TAG, "reset(inside)  handleAttemptLockout(mDeadline)"+mDeadline);
     }
    //add  for count time at 2019-5-14 end這裏結束
    // if the user is currently locked out, enforce it.
    long deadline = mLockPatternUtils.getLockoutAttemptDeadline(
            KeyguardUpdateMonitor.getCurrentUser());
    if (deadline != 0) {
        handleAttemptLockout(deadline);//這裏執行休眠方法
    } else {
        displayDefaultSecurityMessage();
    }
}

接着需要修改倒計時handleAttemptLockout(deadline)方法,在倒計時的時候設爲1,停止的時候設置爲0

   private void handleAttemptLockout(long elapsedRealtimeDeadline) {
    mLockPatternView.clearPattern();
    mLockPatternView.setEnabled(false);
    final long elapsedRealtime = SystemClock.elapsedRealtime();
    final long secondsInFuture = (long) Math.ceil(
            (elapsedRealtimeDeadline - elapsedRealtime) / 1000.0);
    if (mCountdownTimer != null) {
        mCountdownTimer.cancel();
    }
    mCountdownTimer = new CountDownTimer(secondsInFuture * 1000, 1000) {

        @Override
        public void onTick(long millisUntilFinished) {//倒計時執行的地方
            final int secondsRemaining = (int) Math.round(millisUntilFinished / 1000.0);
            mSecurityMessageDisplay.setMessage(mContext.getResources().getQuantityString(
                            R.plurals.kg_too_many_failed_attempts_countdown,
                            secondsRemaining, secondsRemaining));
                    //add for count time unlock start
                    Log.v(TAG, "handleAttemptLockout  secondsRemaining = "+secondsRemaining);
                    if(secondsRemaining == 30){
                        Settings.System.putInt(mContext.getContentResolver(),Settings.System.COUNT_DOWNTIME_UNLOCK,1);
                        //在這裏置爲1
                        }

        }

        @Override
        public void onFinish() {//倒計時結束的地方
            mLockPatternView.setEnabled(true);
            displayDefaultSecurityMessage();
            Settings.System.putInt(mContext.getContentResolver(),Settings.System.COUNT_DOWNTIME_UNLOCK,0);
            //在這裏置爲0
            //add for count time unlock at 2019-end
        }

    }.start();
}

這樣就結束了,因爲password和pin碼都繼承自KeyguardAbsKeyInputView.java,所以我們只需要在KeyguardAbsKeyInputView.java做同樣的修改就OK了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章