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 其他注意

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

相关推荐
云和数据.ChenGuang2 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
摇滚侠3 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 12
java·数据库·笔记
tongyiixiaohuang3 小时前
WMS已发货状态反写金蝶云星空:单策略实战教程
android
好的佩奇4 小时前
Dart 之类修饰符
android·flutter·dart
silvamux_5 小时前
10款模型写种草笔记:可发布性、返工来源与成本数据缺口复盘
java·数据库·笔记
总线通信小百科5 小时前
车载以太网模块、交换机与媒体转换器:三类设备怎么选?
经验分享·车载以太网
alexhilton6 小时前
用Konsist与Lint强制执行设计系统契约
android·kotlin·android jetpack
步行cgn6 小时前
StringHttpMessageConverter 详解:Spring MVC 中字符串读写的默认转换器
java·spring·mvc
摇滚侠6 小时前
《On Java 中文版 基础卷》阅读笔记 实现隐藏 11
java·笔记·python
小蒜学长6 小时前
基于Spring Boot+Vue3的在线医疗咨询系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·在线问诊·在线医疗咨询系统