android广播实现PIN码设置

摘要:本文通过广播的方式调用系统设置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 其他注意

广播需要在系统管理中添加,避免被拦截。

相关推荐
闲猫4 小时前
Spring AI 对接Deepseek ChatModel 聊天对话
java·前端·spring
自信的未来6 小时前
JSON 工具|Web Worker 工程化打包 + 语法自动修复 + 多语言代码生成实战
java·前端·json
Brookty6 小时前
【JavaEE】线程安全(一).4:写块串行保安全、CAS
java·开发语言·java-ee·多线程·线程安全
SRET6 小时前
Mineradio 沙盒隔离安装完全指南 | 一键安全运行 Electron 应用!!!
javascript·经验分享·安全·electron·aigc·音视频·ai编程
怕孤单的草丛7 小时前
缓存管理面临的主要问题
java·数据库·缓存
犀利豆9 小时前
AI in Harness(二)
java·人工智能·后端
沉静的小伙11 小时前
在微服务中使用领域事件
java·运维·微服务
程序员在囧途11 小时前
likeadmin-api API 算力超市怎么做供应商切换?统一鉴权、task_id 和 callback_url 才能稳交付
java·服务器·数据库·开放api·likeadmin-api·api算力超市
醇氧11 小时前
Spring 容器 Map 注入机制详解
java·后端·spring