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了

你可能感兴趣的:(技术总结)