Android10.0 锁屏分析——KeyguardPINVie
2022-09-06 本文已影响0人
孤街酒客0911
学习笔记:
PIN 解锁流程跟Android10.0 锁屏分析——KeyguardPatternView图案锁分析一样,这里就不过多讲解了。
在这里主要分析下 PIN 键盘的按钮事件。
1. 确认按钮
// KeyguardPinBasedInputView.java
@Override
protected void onFinishInflate() {
// 省略部分代码......
mOkButton = findViewById(R.id.key_enter);
if (mOkButton != null) {
mOkButton.setOnTouchListener(this);
mOkButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d(TAG, "mOkButton onClick");
if (mPasswordEntry.isEnabled()) {
Log.d(TAG, "mOkButton onClick verifyPasswordAndUnlock");
verifyPasswordAndUnlock();
}
}
});
mOkButton.setOnHoverListener(new LiftToActivateListener(getContext()));
}
// 省略部分代码......
}
在这里主要看verifyPasswordAndUnlock()方法,
// KeyguardAbsKeyInputView.java
protected void verifyPasswordAndUnlock() {
Log.d(TAG, "verifyPasswordAndUnlock mDismissing=" + mDismissing);
// 判断是否正在进行解锁,如果在则返回,
if (mDismissing) return; // already verified but haven't been dismissed; don't do it again.
// 创建一个表示给定数字 PIN 的 LockscreenCredential 对象。如果提供的密码为空,则创建一个空的凭证对象。
final LockscreenCredential password = getEnteredCredential();
// 禁止输入
setPasswordEntryInputEnabled(false);
if (mPendingLockCheck != null) {
mPendingLockCheck.cancel(false);
}
final int userId = KeyguardUpdateMonitor.getCurrentUser();
// 比对最小密码长度
if (password.size() <= MINIMUM_PASSWORD_LENGTH_BEFORE_REPORT) {
// to avoid accidental lockout, only count attempts that are long enough to be a
// real password. This may require some tweaking.
setPasswordEntryInputEnabled(true);
onPasswordChecked(userId, false /* matched */, 0, false /* not valid - too short */);
password.zeroize();
return;
}
if (LatencyTracker.isEnabled(mContext)) {
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL);
LatencyTracker.getInstance(mContext).onActionStart(ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
mKeyguardUpdateMonitor.setCredentialAttempted();
// 这里跟图案解锁流程一样,就不过多讲解。
mPendingLockCheck = LockPatternChecker.checkCredential(
mLockPatternUtils,
password,
userId,
new LockPatternChecker.OnCheckCallback() {
@Override
public void onEarlyMatched() {
if (LatencyTracker.isEnabled(mContext)) {
LatencyTracker.getInstance(mContext).onActionEnd(
ACTION_CHECK_CREDENTIAL);
}
onPasswordChecked(userId, true /* matched */, 0 /* timeoutMs */,
true /* isValidPassword */);
password.zeroize();
}
@Override
public void onChecked(boolean matched, int timeoutMs) {
Log.d(TAG, "verifyPasswordAndUnlock onChecked");
if (LatencyTracker.isEnabled(mContext)) {
LatencyTracker.getInstance(mContext).onActionEnd(
ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
setPasswordEntryInputEnabled(true);
mPendingLockCheck = null;
if (!matched) {
onPasswordChecked(userId, false /* matched */, timeoutMs,
true /* isValidPassword */);
}
password.zeroize();
}
@Override
public void onCancelled() {
Log.d(TAG, "verifyPasswordAndUnlock onCancelled");
// We already got dismissed with the early matched callback, so we cancelled
// the check. However, we still need to note down the latency.
if (LatencyTracker.isEnabled(mContext)) {
LatencyTracker.getInstance(mContext).onActionEnd(
ACTION_CHECK_CREDENTIAL_UNLOCKED);
}
password.zeroize();
}
});
}
2. 删除回退按钮
// KeyguardPinBasedInputView.java
@Override
protected void onFinishInflate() {
// 省略部分代码......
mDeleteButton = findViewById(R.id.delete_button);
mDeleteButton.setVisibility(View.VISIBLE);
mDeleteButton.setOnTouchListener(this);
mDeleteButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// check for time-based lockouts
if (mPasswordEntry.isEnabled()) {
mPasswordEntry.deleteLastChar();
}
}
});
mDeleteButton.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
// check for time-based lockouts
if (mPasswordEntry.isEnabled()) {
resetPasswordText(true /* animate */, true /* announce */);
}
doHapticKeyClick();
return true;
}
});
// 省略部分代码......
}
这里主要看mPasswordEntry.deleteLastChar()这句话,mPasswordEntry是PasswordTextView的对象。调用其方法deleteLastChar()进行字符串的删除回退。
// PasswordTextView.java
public void deleteLastChar() {
int length = mText.length();
CharSequence textbefore = getTransformedText();
if (length > 0) {
mText = mText.substring(0, length - 1);
CharState charState = mTextChars.get(length - 1);
charState.startRemoveAnimation(0, 0);
sendAccessibilityEventTypeViewTextChanged(textbefore, textbefore.length() - 1, 1, 0);
}
userActivity();
}
看到这里,在接着看数字按钮。
3. 数字按钮
数字按钮是一个自定义布局。
// NumPadKey.java
private View.OnClickListener mListener = new View.OnClickListener() {
@Override
public void onClick(View thisView) {
Log.d("jiangshufeng","yexiao:"+Character.forDigit(mDigit, 10));
if (mTextView == null && mTextViewResId > 0) {
final View v = NumPadKey.this.getRootView().findViewById(mTextViewResId);
if (v != null && v instanceof PasswordTextView) {
mTextView = (PasswordTextView) v;
}
}
if (mTextView != null && mTextView.isEnabled()) {
mTextView.append(Character.forDigit(mDigit, 10));
}
userActivity();
}
};
在该自定义布局里有点击事件的实现,mDigit其实就是数字键盘对应的数字,mTextView为PasswordTextView的对象,调用其append(char c)方法进行字符串的拼接。
PIN到此分析结束,如果要看解锁流程,即参考Android10.0 锁屏分析——KeyguardPatternView图案锁分析,两者是一样的。