安卓11之adb命令清除锁屏密码

安卓11之adb命令清除锁屏密码

需求说明

客户设置密码后容易遗忘,反复刷机不符合需求,需要预留一个adb命令去直接清除掉锁屏密码。

为什么不直接删除对应文件

安卓11找不到对应的.key文件了,根据老的版本,大概8.0之前是有.key文件去管理锁屏密码的,但是现在没有了

修改

原理

制造假数据(空的数据)去覆盖掉,然后在通过方法去清除掉空数据

设置假数据去覆盖掉旧的密码

路径:

frameworks\base\core\java\com\android\internal\widget\LockPatternUtils.java

代码:

/**

* Save a new lockscreen credential.

*

*

This method will fail (returning {@code false}) if the previously saved credential

* provided is incorrect, or if the lockscreen verification is still being throttled.

*

* @param newCredential The new credential to save

* @param savedCredential The current credential

* @param userHandle the user whose lockscreen credential is to be changed

*

* @return whether this method saved the new password successfully or not. This flow will fail

* and return false if the given credential is wrong.

* @throws RuntimeException if password change encountered an unrecoverable error.

* @throws UnsupportedOperationException secure lockscreen is not supported on this device.

* @throws IllegalArgumentException if new credential is too short.

*/

public boolean setLockCredential(@NonNull LockscreenCredential newCredential,

@NonNull LockscreenCredential savedCredential, int userHandle) {

if (!hasSecureLockScreen()) {

throw new UnsupportedOperationException(

"This operation requires the lock screen feature.");

}

newCredential.checkLength();

try {

if (!getLockSettings().setLockCredential(newCredential, savedCredential, userHandle)) {

return false;

}

} catch (RemoteException e) {

throw new RuntimeException("Unable to save lock password", e);

}

onPostPasswordChanged(newCredential, userHandle);

return true;

}

这个类怎么用呐?

直接百度翻译注释:

这个方法是用来保存新的锁屏凭证

这个方法有三个参数,分别代表:

新的锁屏凭证,旧的锁屏凭证,要修改凭证的用户

这里提到了LockscreenCredential这个类,前面两个参数是基于这个修改的

路径:

frameworks\base\core\java\com\android\internal\widget\LockscreenCredential.java

新的锁屏凭证:

这里我们需要的是一个空的密码凭证,对应方法为:

/**

* Creates a LockscreenCredential object representing empty password.

*/

public static LockscreenCredential createNone() {

return new LockscreenCredential(CREDENTIAL_TYPE_NONE, new byte[0]);

}

很好,这里调用了自身的构造方法,返回一个基于自己的对象,这个构造方法怎么说

百度翻译注释结果:

创建表示给定模式的LockscreenCredential对象

第一个参数是一个类似标识符的东西,在这个类中通过对应标识去做不同的事情

private LockscreenCredential(int type, byte[] credential) {

Objects.requireNonNull(credential);

if (type == CREDENTIAL_TYPE_NONE) {

Preconditions.checkArgument(credential.length == 0);

} else {

// Do not allow constructing a CREDENTIAL_TYPE_PASSWORD_OR_PIN object.

Preconditions.checkArgument(type == CREDENTIAL_TYPE_PIN

|| type == CREDENTIAL_TYPE_PASSWORD

|| type == CREDENTIAL_TYPE_PATTERN);

Preconditions.checkArgument(credential.length > 0);

}

mType = type;

mCredential = credential;

}

看代码得知后面的参数是指这个的存放的长度,就相当于预留多少内存空间去存放,这里createNone给的是new byte[0],走if上面,不细究,喜欢看的自己去细看源码。

这样我们就大概可以知道直接LockscreenCredential.createNone()就可以拿到一个新的空的锁屏凭证了,(这里注一个小知识:被static修饰的方法可以直接调用,不需要new对象,且只能被继承,不能被重写)。

旧的锁屏凭证

旧的锁屏凭证这个就比较麻烦了,主要是有三种(除了无和滑动),这三种分别代表图案,PIN码和密码。

回到LockscreenCredential这个类,先说密码的锁屏凭证

/**

* Creates a LockscreenCredential object representing the given alphabetic password.

* If the supplied password is empty, create an empty credential object.

*/

public static LockscreenCredential createPasswordOrNone(@Nullable CharSequence password) {

if (TextUtils.isEmpty(password)) {

return createNone();

} else {

return createPassword(password);

}

}

首先是空的凭证和非空凭证的判断,接下来找非空的判断走法

/**

* Creates a LockscreenCredential object representing the given alphabetic password.

*/

public static LockscreenCredential createPassword(@NonNull CharSequence password) {

return new LockscreenCredential(CREDENTIAL_TYPE_PASSWORD,

charSequenceToByteArray(password));

}

传个密码就好了。嗯,当然,这就要知道安卓系统一般保存这种数据都是通过数据库的,既然可以写入,自然就可以拿到了,当然,如果没有怎么办,我们就自己做一个。

先拿密码和PIN码为例

路径:

vendor\mediatek\proprietary\packages\apps\MtkSettings\src\com\android\settings\password\ChooseLockPassword.java

没有这个路径怎么办,老办法找对应类就好了

Settings.System.putString(getContext().getContentResolver(), "lock_password", passwordText.toString());

这句代码加在handleNext();方法里面,

为什么??

看调用:

protected void onNextButtonClick(View view) {

handleNext();

}

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

// Check if this was the result of hitting the enter or "done" key

if (actionId == EditorInfo.IME_NULL

|| actionId == EditorInfo.IME_ACTION_DONE

|| actionId == EditorInfo.IME_ACTION_NEXT) {

handleNext();

return true;

}

return false;

}

这里干了啥,点击按键的监听,什么按键?

很显然,FooterButton,这里是通过导包拿的,应该是自定义的一个控件,主要说明,为什么在这里面调用,这个就是输入密码的时候的下一步按钮的事件监听;

好了,这里我们还需要导包

import android.provider.Settings;

这里我们已经加上了在输入密码和PIN码的,接下来就是图案密码了

byte[] pBytes = LockPatternUtils.patternToByteArray(pattern);

String res = new String(pBytes);

Settings.System.putString(getContext().getContentResolver(), "lock_password", res.toString());

加在onPatternDetected(List pattern);方法里面,这里也需要导包

和上面的密码和PIN码导的包一样

由于这两个类都是Activity,这样我们需要考虑到这个值是否会受到生命周期的影响,比如说在切换横竖屏的时候,由于这个值不是固定的xml文件中的存在,且没有对应id去控制,所以,我们需要在onSaveInstanceState()中去保存

if (mCurrentCredential != null) {

LockscreenCredential currentCredential_dup = mCurrentCredential.duplicate();

outState.putParcelable(KEY_CURRENT_CREDENTIAL, currentCredential_dup);

}

这样我们就创建好了一个旧的密码的存储方式,且保存了旧的凭证的临时数据。

我们可以通过下面的方式拿到密码,且知道图案密码的保存值也是被转化的password

String password = Settings.System.getString(mContext.getContentResolver(), "lock_password");

这样就可以拿到旧的锁屏凭证之密码凭证了。

PIN码的拿法和这个一致,只是方法里面的参数换成了CharSequence pin

我们拿到密码是针对锁屏所有的,所以传入的参数还是password,只是方法换成了

public static LockscreenCredential createPinOrNone(@Nullable CharSequence pin) {

if (TextUtils.isEmpty(pin)) {

return createNone();

} else {

return createPin(pin);

}

}

接下来就是图案密码了

/**

* Creates a LockscreenCredential object representing the given pattern.

*/

public static LockscreenCredential createPattern(@NonNull List pattern) {

return new LockscreenCredential(CREDENTIAL_TYPE_PATTERN,

LockPatternUtils.patternToByteArray(pattern));

}

这里用同样的方法去将password转化成需要的参数。

这里需要借助LockPatternUtils的byteArrayToPattern()方法,先将password转化成byte数组,以byte数组转化成pattern,最后通过createPattern()方法拿到旧的锁屏凭证之图案。

要修改凭证的用户

int userId = UserHandle.USER_SYSTEM;

这里直接拿系统用户就可以了

这个是UserHandle的类,由于文章篇幅过长,不做阐述,自己去看详细代码

http://t.csdn.cn/2KVw0

现在就已经完成了新的空密码替换旧的密码了,我们还需要让锁屏界面不显示,也就是切换成无的状态

这里用的是LockPatternUtils的setLockScreenDisabled(boolean disable, int userId);方法

/**

* Disable showing lock screen at all for a given user.

* This is only meaningful if pattern, pin or password are not set.

*

* @param disable Disables lock screen when true

* @param userId User ID of the user this has effect on

*/

public void setLockScreenDisabled(boolean disable, int userId) {

setBoolean(DISABLE_LOCKSCREEN_KEY, disable, userId);

}

以下就是清除锁屏密码的全部代码

//清除锁屏密码

public void clearLockscreen(){

String password = Settings.System.getString(mContext.getContentResolver(), "lock_password");

int userId = UserHandle.USER_SYSTEM;

int type = mLockPatternUtils.getCredentialTypeForUser(userId);

if(type == LockPatternUtils.CREDENTIAL_TYPE_PASSWORD){

mLockPatternUtils.setLockCredential(LockscreenCredential.createNone(),

LockscreenCredential.createPasswordOrNone(password), userId);

mLockPatternUtils.setLockScreenDisabled(true, userId);

ShutdownThread.reboot(mContext,"userrequested",false);

}else if(type == LockPatternUtils.CREDENTIAL_TYPE_PIN){

mLockPatternUtils.setLockCredential(LockscreenCredential.createNone(),

LockscreenCredential.createPinOrNone(password), userId);

mLockPatternUtils.setLockScreenDisabled(true, userId);

ShutdownThread.reboot(mContext,"userrequested",false);

}else if(type == LockPatternUtils.CREDENTIAL_TYPE_PATTERN){

byte[] pBytes = password.getBytes();

mLockPatternUtils.setLockCredential(LockscreenCredential.createNone(),

LockscreenCredential.createPattern(LockPatternUtils.byteArrayToPattern(pBytes)), userId);

mLockPatternUtils.setLockScreenDisabled(true, userId);

ShutdownThread.reboot(mContext,"userrequested",false);

}

}

这里用了ShutdownThread的reboot方法,这个方法是为了请求干净关机,等待子系统清理其

*状态等,必须从其UI所在的循环器线程调用。如果不使用这个方法会无效。

而type是为了筛选3种不同的密码实现方式。

方法已经给了,则adb命令可以通过广播去实现,这里不做具体阐述,注意在导包的时候可能由于不处在一个项目里面而失败,建议在PhoneWindowManager.java中实现。

✨ 相关作品

2024年全球最佳航空公司100强榜单,海航、南航上榜
谁知道365足球网站

2024年全球最佳航空公司100强榜单,海航、南航上榜

📅 10-23 👁️‍🗨️ 7889
歎的解释
谁知道365足球网站

歎的解释

📅 09-22 👁️‍🗨️ 7920
二面怎么准备
365bet中文版客户端

二面怎么准备

📅 10-11 👁️‍🗨️ 5345