摘要:本文通过广播的方式调用系统设置PIN码的流程实现类似锁机的功能,可供开发人员在联网状态下后台推送消息进行锁机/解锁。有需要的同学可以参考PIN码的流程改为密码等其他形式。
1 定义一个广播接收器
广播action:android.intent.action.LOCKDEVICE
boolean extra: lock (true:锁机/false:解锁)
String extra: password (6位数字密码,后续代码会进行合法性检测)
java
<receiver android:name=".LockDeviceReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.LOCKDEVICE"/>
</intent-filter>
</receiver>
2 功能实现
代码部分注释为 android 9之前的实现方式。
java
import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
import static com.android.internal.widget.PasswordValidationError.RECENTLY_USED;
import android.app.admin.PasswordMetrics;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.UserHandle;
import android.util.Log;
import com.android.internal.widget.LockPatternChecker;
import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.PasswordValidationError;
import java.util.Collections;
import java.util.List;
/**
* Boot completed receiver. used to reset the app install state every time the
* device boots.
*
*/
public class LockDeviceReceiver extends BroadcastReceiver {
private static String TAG ="LockDeviceReceiver";
private byte[] mPasswordHistoryHashFactor;
private LockPatternUtils mLockPatternUtils;
private LockscreenCredential mChosenPassword;
private LockscreenCredential mCurrentCredential;
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if ("android.intent.action.LOCKDEVICE".equals(action)) {
boolean isLock = intent.getBooleanExtra("lock", false);
String password = intent.getStringExtra("password");
mLockPatternUtils = new LockPatternUtils(context);
if (isLock) {
lockDevice(context, password);
} else {
unlockDevice(context, password);
}
return;
}
}
private void lockDevice(Context context, String password) {
mChosenPassword = LockscreenCredential.createPin(password);
//int mRequestedQuality = mLockPatternUtils.computePasswordQuality(LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, password, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
if (password.length() == 6 && validatePassword(mChosenPassword)) {
//mLockPatternUtils.setCredentialRequiredToDecrypt(false);
//mLockPatternUtils.saveLockPassword(password, null, mRequestedQuality, UserHandle.myUserId());
final boolean success = mLockPatternUtils.setLockCredential(
mChosenPassword, LockscreenCredential.createNone(), UserHandle.myUserId());
Log.d(TAG, "lockDevice " + (success ? "success" : "unsuccess"));
} else {
Log.d(TAG, "invalid password!");
}
}
private void unlockDevice(Context context, String password) {
LockscreenCredential credential = LockscreenCredential.createPin(password);
LockPatternChecker.checkCredential(
mLockPatternUtils,
credential,
UserHandle.myUserId(),
new LockPatternChecker.OnCheckCallback() {
@Override
public void onChecked(boolean matched, int timeoutMs) {
if (matched) {
//mLockPatternUtils.setSeparateProfileChallengeEnabled(UserHandle.myUserId(), true, credential);
//mLockPatternUtils.clearLock(password, UserHandle.myUserId());
//mLockPatternUtils.setLockScreenDisabled(true, UserHandle.myUserId());
final boolean success = mLockPatternUtils.setLockCredential(
LockscreenCredential.createNone(), LockscreenCredential.createPinOrNone(password), UserHandle.myUserId());
mLockPatternUtils.setLockScreenDisabled(true, UserHandle.myUserId());
Log.d(TAG, "unlockDevice " + (success ? "success" : "unsuccess"));
} else {
Log.d(TAG, "Password do not match");
}
}
});
}
boolean validatePassword(LockscreenCredential credential) {
final byte[] password = credential.getCredential();
List<PasswordValidationError> mValidationErrors = PasswordMetrics.validatePassword(
new PasswordMetrics(CREDENTIAL_TYPE_NONE), PASSWORD_COMPLEXITY_NONE, true, password);
if (mValidationErrors.isEmpty() && mLockPatternUtils.checkPasswordHistory(
password, getPasswordHistoryHashFactor(), UserHandle.myUserId())) {
mValidationErrors =
Collections.singletonList(new PasswordValidationError(RECENTLY_USED));
}
return mValidationErrors.isEmpty();
}
private byte[] getPasswordHistoryHashFactor() {
if (mPasswordHistoryHashFactor == null) {
mPasswordHistoryHashFactor = mLockPatternUtils.getPasswordHistoryHashFactor(
mCurrentCredential != null ? mCurrentCredential
: LockscreenCredential.createNone(), UserHandle.myUserId());
}
return mPasswordHistoryHashFactor;
}
}
3 其他注意
广播需要在系统管理中添加,避免被拦截。