美文网首页
代码锁屏 修改密码

代码锁屏 修改密码

作者: 钦_79f7 | 来源:发表于2019-12-18 11:28 被阅读0次
  • 自定义 MyAdminReceiver,继承自 DeviceAdminReceiver
  • xml目录下建立device-admin规则
  • 注册清单文件

代码

自定义 Receiver

class MyAdminReceiver : DeviceAdminReceiver() {

    override fun onEnabled(context: Context?, intent: Intent?) {
        super.onEnabled(context, intent)
        Logs.d("MyAdminReceiver.onEnabled() called with: context = [$context], intent = [$intent]")
    }

    override fun onDisabled(context: Context?, intent: Intent?) {
        super.onDisabled(context, intent)
        Logs.d("MyAdminReceiver.onDisabled() called with: context = [$context], intent = [$intent]")
    }

    override fun onPasswordChanged(context: Context?, intent: Intent?, user: UserHandle?) {
        super.onPasswordChanged(context, intent, user)
        Logs.d("MyAdminReceiver.onPasswordChanged() called with: context = [$context], intent = [$intent], user = [$user]")
    }

    override fun onPasswordFailed(context: Context?, intent: Intent?, user: UserHandle?) {
        super.onPasswordFailed(context, intent, user)
        Logs.d("MyAdminReceiver.onPasswordFailed() called with: context = [$context], intent = [$intent], user = [$user]")
    }

    override fun onPasswordSucceeded(context: Context?, intent: Intent?, user: UserHandle?) {
        super.onPasswordSucceeded(context, intent, user)
        Logs.d("MyAdminReceiver.onPasswordSucceeded() called with: context = [$context], intent = [$intent], user = [$user]")
    }

    override fun onPasswordExpiring(context: Context?, intent: Intent?, user: UserHandle?) {
        super.onPasswordExpiring(context, intent, user)
        Logs.d("MyAdminReceiver.onPasswordExpiring() called with: context = [$context], intent = [$intent], user = [$user]")
    }

    override fun onBugreportFailed(context: Context?, intent: Intent?, failureCode: Int) {
        super.onBugreportFailed(context, intent, failureCode)
        Logs.d("MyAdminReceiver.onBugreportFailed() called with: context = [$context], intent = [$intent], failureCode = [$failureCode]")
    }

    override fun onBugreportShared(context: Context?, intent: Intent?, bugreportHash: String?) {
        super.onBugreportShared(context, intent, bugreportHash)
        Logs.d("MyAdminReceiver.onBugreportShared() called with: context = [$context], intent = [$intent], bugreportHash = [$bugreportHash]")
    }

    override fun onBugreportSharingDeclined(context: Context?, intent: Intent?) {
        super.onBugreportSharingDeclined(context, intent)
        Logs.d("MyAdminReceiver.onBugreportSharingDeclined() called with: context = [$context], intent = [$intent]")
    }

    override fun onChoosePrivateKeyAlias(context: Context?, intent: Intent?, uid: Int, uri: Uri?, alias: String?): String? {
        Logs.d("MyAdminReceiver.onChoosePrivateKeyAlias() called with: context = [$context], intent = [$intent], uid = [$uid], uri = [$uri], alias = [$alias]")
        return super.onChoosePrivateKeyAlias(context, intent, uid, uri, alias)
    }

    override fun onDisableRequested(context: Context?, intent: Intent?): CharSequence? {
        Logs.d("MyAdminReceiver.onDisableRequested() called with: context = [$context], intent = [$intent]")
        return super.onDisableRequested(context, intent)
    }

    override fun onLockTaskModeEntering(context: Context?, intent: Intent?, pkg: String?) {
        Logs.d("MyAdminReceiver.onLockTaskModeEntering() called with: context = [$context], intent = [$intent], pkg = [$pkg]")
        super.onLockTaskModeEntering(context, intent, pkg)
    }

    override fun onLockTaskModeExiting(context: Context?, intent: Intent?) {
        super.onLockTaskModeExiting(context, intent)
        Logs.d("MyAdminReceiver.onLockTaskModeExiting() called with: context = [$context], intent = [$intent]")
    }

    override fun onNetworkLogsAvailable(context: Context?, intent: Intent?, batchToken: Long, networkLogsCount: Int) {
        super.onNetworkLogsAvailable(context, intent, batchToken, networkLogsCount)
        Logs.d("MyAdminReceiver.onNetworkLogsAvailable() called with: context = [$context], intent = [$intent], batchToken = [$batchToken], networkLogsCount = [$networkLogsCount]")
    }

    override fun onReceive(context: Context?, intent: Intent?) {
        super.onReceive(context, intent)
        Logs.d("MyAdminReceiver.onReceive() called with: context = [$context], intent = [$intent]")
    }


}

自定义 my_device_admin.xml

xml目录下创建文件 my_device_admin.xml

<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
    <uses-policies>
        <limit-password /> 设置密码规则(数字、图案、字母等)
        <watch-login /> 监听登录回调(失败、成功等)
        <force-lock /> 强制锁屏
        <reset-password /> 重置密码
        <wipe-data /> 清除数据
        <disable-camera /> 禁止相机
        <encrypted-storage /> 加密存储数据
    </uses-policies>
</device-admin>

清单文件注册

        <receiver
            android:name=".module.funs.admin.MyAdminReceiver"
            android:permission="android.permission.BIND_DEVICE_ADMIN">
            <meta-data
                android:name="android.app.device_admin"
                android:resource="@xml/my_device_admin" />

            <intent-filter>
                <action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
            </intent-filter>

        </receiver>

锁屏调用

  • 锁屏
DevicePolicyManager#lockNow
  • 重置密码

用来重置密码,但是需要 成为Owner

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    manager.resetPasswordWithToken(componentName,password, getPwdToken(),0)
}else {
    manager.resetPassword(password, 0)
}

API 24+ 即Android N 后,系统做了限制,无法针对已设置密码的设备 进行重置密码的操作,否则会抛异常

Admin cannot change current password

or

Android SecurityException: Admin does not own the profile
  • 激活组件
    fun activeDeviceAdmin() {
        val intent = Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN)
        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, componentName)
        intent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION, "--其他描述--")
        startActivityForResult(intent, 0)
    }

具体代码

    fun lockScreen(password: String) {
        val manager = ctx().getSystemService(Context.DEVICE_POLICY_SERVICE) as? DevicePolicyManager
                ?: return
        val componentName = ComponentName(ctx(), MyAdminReceiver::class.java)
        //判断设备管理器组件是否激活
        if (manager.isAdminActive(componentName)) {
            try {
            
                manager.setPasswordQuality(componentName, DevicePolicyManager.PASSWORD_QUALITY_NUMERIC)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    manager.resetPasswordWithToken(componentName,password, getPwdToken(),0)
                }
                // 用来重置密码,但是需要 成为Owner。
                // API 24+ 即Android N 后,系统做了限制,无法针对已设置密码的设备 进行重置密码的操作,否则会 抛错
//                manager.resetPassword(password, 0)
                // 调用锁屏 
                manager.lockNow()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        } else {
            //激活设备管理器组件
            activeDeviceAdmin()
        }
    }

源码

setResetPasswordToken

API 24,Android N

/**
* @param token 一种安全令牌,至少32字节长,必须由加密的强随机数生成器生成。
*/
public boolean setResetPasswordToken(ComponentName admin, byte[] token) {}

由配置文件或设备所有者调用,以提供一个令牌,该令牌可用于稍后通过{@link #resetPasswordWithToken}重置设备锁屏密码(如果由设备所有者调用),或托管配置文件挑战(如果由配置文件所有者调用)。

如果用户当前拥有锁定屏幕密码,则所提供的令牌将不能立即使用;它只在用户执行确认凭据操作之后才会激活,该操作可以由{@link KeyguardManager# createcon固件devicecredentialintent}触发。如果用户没有锁定屏幕密码,则立即激活令牌。在所有情况下,当前令牌的活动状态都可以由{@link #isResetPasswordTokenActive}检查。出于安全原因,未激活的令牌只存储在内存中,并且在设备重新启动后将丢失。在这种情况下,需要再次提供一个新的令牌。

一旦准备好并激活了令牌,即使用户更改或清除锁定屏幕密码,令牌也将保持有效。

这个令牌是高度敏感的,应该与用户凭证在同一级别上处理。特别是,永远不要将此令牌以明文形式存储在设备上。如果需要在用户解锁之前重置基于文件的加密设备上的密码,请不要将明文令牌存储在设备加密的存储中。请仔细考虑如何将密码令牌存储在服务器上,以及谁需要访问它们。令牌可能是合法访问请求的主体。

resetPasswordWithToken

public boolean resetPasswordWithToken(@NonNull ComponentName admin, String password,
            byte[] token, int flags) {}

由设备或配置文件所有者调用,强制对当前用户设置新设备解锁密码或托管配置文件挑战。这立即生效。

与{@link #resetPassword}不同,这个API甚至可以在用户或设备未锁定或解密之前更改密码。所提供的令牌必须事先通过{@link #setResetPasswordToken}和在活动状态{@link #isResetPasswordTokenActive}提供。

给定的密码必须满足{@link #getPasswordQuality(ComponentName)}和{@link #getPasswordMinimumLength(ComponentName)}返回的当前密码质量和长度约束;如果它不满足这些约束,那么它将被拒绝并返回false。注意,密码可能是更强的质量,例如,当请求的质量只是数字时,包含字母数字字符的密码。

如果当前密码约束允许,使用{@code null}或空密码调用将清除任何现有PIN、模式或密码。

相关文章

网友评论

      本文标题:代码锁屏 修改密码

      本文链接:https://www.haomeiwen.com/subject/sonynctx.html