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

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

相关推荐
白菜欣7 小时前
Linux — 进程控制
android·linux·运维
智者知已应修善业7 小时前
【ICL8038芯片正弦波三角波方波发生器电路】2024-1-5
驱动开发·经验分享·笔记·硬件架构·硬件工程
budingxiaomoli7 小时前
Spring IoC &DI
java·spring·ioc·di
Spider Cat 蜘蛛猫7 小时前
Springboot SSO系统设计文档
java·spring boot·后端
未若君雅裁7 小时前
MySQL高可用与扩展-主从复制读写分离分库分表
java·数据库·mysql
学习中.........7 小时前
从扰动函数的变化,感受红黑树带来的性能提升
java
计算机安禾8 小时前
【c++面向对象编程】第24篇:类型转换运算符:自定义隐式转换与explicit
java·c++·算法
weixin199701080169 小时前
【保姆级教程】淘宝/天猫商品详情 API(item_get)接入指南:Python/Java/PHP 调用示例与 JSON 返回值解析
java·python·php
环流_9 小时前
redis核心数据类型在java中的操作
java·数据库·redis
雨辰AI9 小时前
SpringBoot3 项目国产化改造完整流程|从 MySQL 到人大金仓落地
java·数据库·后端·mysql·政务