首页 >Android频道 >【Android研究院之应用开发】 > Android研究院之应用程序屏幕锁定详解(二十四)
2012
08-13

Android研究院之应用程序屏幕锁定详解(二十四)

最近在一个视频项目中遇到了很多屏幕锁定的问题,小马自己也在学习,网上找了下也没太详细的例子,看的资料书上也没有有关屏幕锁定程序的介绍,从之前写的文章中抽过来放研究院中,希望能帮助更多想了解或学习屏幕锁的朋友们学习研究,自己照着官方文档学习下,现在做好了,小马废话不多说,先发下截图,看下效果,需要注意的地方小马会加注释,有问题的朋友可以直接留言,我们共同学习交流,共同提高进步!直接看效果图:

一:未设置密码时进入系统设置的效果图如下:

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 1

二:运行DEMO,进入应用时:

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 2

三:设置密码方式预览:

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 3

四:只设置密码保护时的效果图

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 4

五:密码解密效果图

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 5

六:设置九宫格加密时的效果图

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 6

七:九宫格解密时的效果图

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 7

八:解密成功后,进入我们手机系统的图

Android研究院之应用程序屏幕锁定详解(二十四) - 雨松MOMO程序研究院 - 8

下面来简单的看下源码吧,此处讲下,这个小DEMO也是小马临时学习下的,有讲的不明白的地方请朋友直接批评指出,有错肯定改的,吼吼..看代码:

主控制类:

package com.xiaoma.policymanager.demo; 

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
mport android.content.SharedPreferences;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
mport android.widget.Spinner;
import android.widget.TextView; 

/**
* @Title: PolicySetupActivity.java
* @Package com.xiaoma.policymanager.demo
* @Description: 屏幕锁实现测试
* @author MZH
*/
public class PolicySetupActivity extends Activity {
    private static final int REQ_ACTIVATE_DEVICE_ADMIN = 10;
    private static final String SCREEN_ID_KEY = "LAYOUT_ID"; 

    /**存储配置信息的SP文件名*/
    private static final String APP_PREF = "APP_PREF";
    /**有未知屏幕ID时返回此标识*/
   private static final int UNKNOWN_SCREEN_ID = -1; 

    /**声明组件*/
    private Spinner mPasswordQualityInputField;
    private EditText mPasswordLengthInputField;
    private EditText mPasswordMinUppercaseInputField; 

    /**获取配置操作类对象*/
    private Policy mPolicy;
    /**当前屏幕ID*/
    private int mCurrentScreenId; 

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mPolicy = new Policy(this);
    } 

    @Override
    protected void onResume() {
        super.onResume();
        /**获取本地SP文件中屏幕锁的配置信息*/
        SharedPreferences prefs = getSharedPreferences(APP_PREF, MODE_PRIVATE);
        final int savedScreenId = prefs.getInt(SCREEN_ID_KEY, UNKNOWN_SCREEN_ID);
        /**如果获取到的ID为空,则跳转到设置页*/
        if (savedScreenId == UNKNOWN_SCREEN_ID || !mPolicy.isAdminActive()) {
            setScreenContent(R.layout.activity_policy_setup);
        /**跳转到配置详情页*/
        } else {
            setScreenContent(savedScreenId);
        }
    } 

   /**
     * 设置屏幕方法实现,详细的可以自己看下,小马也是边参照官方文档,边学习的
     * 有好想法..有问题的朋友们可以留言.我们一起学习
     * @param screenId
     */
    private void setScreenContent(final int screenId) {
        /**记录当前屏幕ID,并预先存入本地SP配置文件中*/
        mCurrentScreenId = screenId;
        setContentView(mCurrentScreenId);
        getSharedPreferences(APP_PREF, MODE_PRIVATE).edit().putInt(
                SCREEN_ID_KEY, mCurrentScreenId).commit();
        switch (mCurrentScreenId) {
        case R.layout.activity_policy_setup:
            initPolicySetupScreen();
            initNavigation();
            break;
        case R.layout.activity_view_policy:
            initViewPolicyScreen();
            initNavigation();
            break;
        }
    } 

    /**
     * 关闭页面时将当前配置写入本地SP文件中
     */
    @Override
    protected void onPause() {
        super.onPause();
        if (mCurrentScreenId == R.layout.activity_policy_setup) writePolicy();
    } 

   @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQ_ACTIVATE_DEVICE_ADMIN && resultCode == RESULT_OK) {
            // User just activated the application as a device administrator.
            setScreenContent(mCurrentScreenId);
        } else {
            super.onActivityResult(requestCode, resultCode, data);
        }
    } 

    /**
     * 重载返回键方法,如果已当前屏幕为已设置密码页,则展示详情
     */
    @Override
    public void onBackPressed() {
        if (mCurrentScreenId == R.layout.activity_view_policy) {
            setScreenContent(R.layout.activity_policy_setup);
            return;
        }
        super.onBackPressed();
    } 

    /**
     * 初始化化设置页
     */
    private void initPolicySetupScreen() {
        mPasswordQualityInputField = (Spinner) findViewById(R.id.policy_password_quality);
        mPasswordLengthInputField = (EditText) findViewById(R.id.policy_password_length);
        mPasswordMinUppercaseInputField = (EditText) findViewById(R.id.policy_password_uppercase);
        ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,
                R.array.password_types, android.R.layout.simple_spinner_item);
        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        mPasswordQualityInputField.setAdapter(adapter);
        mPasswordQualityInputField.setOnItemSelectedListener(
                new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
                LinearLayout passwordMinUppercaseView =
                        (LinearLayout) findViewById(R.id.password_uppercase_view);
                // The minimum number of upper case field is only applicable for password
                // qualities: alpha, alphanumeric, or complex.
                if (pos > 2)
                    passwordMinUppercaseView.setVisibility(View.VISIBLE);
                else
                    passwordMinUppercaseView.setVisibility(View.GONE);
            } 

            public void onNothingSelected(AdapterView<?> parent) {}
        }); 

        /**阅读先前配置的相关信息*/
        mPolicy.readFromLocal();
        mPasswordQualityInputField.setSelection(mPolicy.getPasswordQuality());
        if (mPolicy.getPasswordLength() > 0) {
            mPasswordLengthInputField.setText(String.valueOf(mPolicy.getPasswordLength()));
        } else {
            mPasswordLengthInputField.setText("");
        } 

        if (mPolicy.getPasswordMinUpperCase() > 0) {
            mPasswordMinUppercaseInputField.setText(
                    String.valueOf(mPolicy.getPasswordMinUpperCase()));
        } else {
            mPasswordMinUppercaseInputField.setText("");
        }
    } 

    /**
     * 初始化查看详情页
     */
    private void initViewPolicyScreen() {
        TextView passwordQualityView = (TextView) findViewById(R.id.policy_password_quality);
        TextView passwordLengthView = (TextView) findViewById(R.id.policy_password_length); 

        // Read previously saved policy and populate on the UI.
        mPolicy.readFromLocal();
        int passwordQualitySelection = mPolicy.getPasswordQuality();
        passwordQualityView.setText(
                getResources().getStringArray(R.array.password_types)[passwordQualitySelection]);
        passwordLengthView.setText(String.valueOf(mPolicy.getPasswordLength()));
        if (passwordQualitySelection > 2) {
            LinearLayout passwordMinUppercaseView =
                    (LinearLayout) findViewById(R.id.password_uppercase_view);
            passwordMinUppercaseView.setVisibility(View.VISIBLE);
            ((TextView) findViewById(R.id.policy_password_uppercase)).setText(
                    String.valueOf(mPolicy.getPasswordMinUpperCase()));
        }
    } 

    /**
     * 设置导航信息
     */
    private void initNavigation() {
        if (!mPolicy.isAdminActive()) {
            // Activates device administrator.
            setupNavigation(R.string.setup_message_activate,
                    R.string.setup_action_activate,
                    mActivateButtonListener);
        } else if (mCurrentScreenId == R.layout.activity_policy_setup) {
            setupNavigation(R.string.setup_message_set_policy,
                    R.string.setup_action_set_policy,
                    new View.OnClickListener() {
                        public void onClick(View view) {
                            writePolicy();
                            mPolicy.configurePolicy();
                            setScreenContent(R.layout.activity_view_policy);
                        }
                    });
        }
        else if (!mPolicy.isActivePasswordSufficient()) {
            // Launches password set-up screen in Settings.
            setupNavigation(R.string.setup_message_enforce_policy,
                    R.string.setup_action_enforce_policy,
                    mEnforcePolicyListener);
        } else {
            // Grants access to secure content.
            setupNavigation(R.string.setup_message_go_secured,
                    R.string.setup_action_go_secured,
                    new View.OnClickListener() {
                        public void onClick(View view) {
                            startActivity(new Intent(view.getContext(), SecureActivity.class));
                        }
                    });
        }
    } 

    /**
     * 监听器实现,这个小马不多讲了.
     */
    private View.OnClickListener mActivateButtonListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // First, persist the policy.  Then, launch intent to trigger the system screen
            // requesting user to confirm the activation of the device administrator.
            writePolicy();
            Intent activateDeviceAdminIntent =
                new Intent(DevicePolicyManager.ACTION_ADD_DEVICE_ADMIN);
            activateDeviceAdminIntent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN,
                    mPolicy.getPolicyAdmin());
            // It is good practice to include the optional explanation text to explain to
            // user why the application is requesting to be a device administrator.  The system
            // will display this message on the activation screen.
            activateDeviceAdminIntent.putExtra(DevicePolicyManager.EXTRA_ADD_EXPLANATION,
                    getResources().getString(R.string.device_admin_activation_message));
            startActivityForResult(activateDeviceAdminIntent, REQ_ACTIVATE_DEVICE_ADMIN);
        }
    }; 

    /**
     * 监听器实现,这个小马也不多讲了.
     */
    private View.OnClickListener mEnforcePolicyListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            writePolicy();
            // The device administration API does not "fix" the password if it is
            // determined that the current password does not conform to what is requested
            // by the policy.  The caller is responsible for triggering the password set up
            // screen via the below intent.
            Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
            startActivity(intent);
        }
    }; 

    /**
     * 设置激活按钮不同状态时的文本信息
     * @param messageResId
     * @param buttonTextResId
     * @param listener
     */
    private void setupNavigation(int messageResId, int buttonTextResId,
            View.OnClickListener listener) {
        TextView setupMessage = (TextView) findViewById(R.id.setup_message);
        setupMessage.setText(messageResId);
        Button actionBtn = (Button) findViewById(R.id.setup_action_btn);
        actionBtn.setText(buttonTextResId);
        actionBtn.setOnClickListener(listener);
    } 

    // 在关闭此页时,将配置信息写入本地SP文件中.
    private void writePolicy() {
        int passwordQuality = (int) mPasswordQualityInputField.getSelectedItemId(); 

        int passwordLength = 0;
        try {
            passwordLength = Integer.valueOf(mPasswordLengthInputField.getText().toString());
        } catch (NumberFormatException nfe) {}  // Defaults to 0. 

        int passwordMinUppercase = 0;
        try {
            passwordMinUppercase =
                    Integer.valueOf(mPasswordMinUppercaseInputField.getText().toString());
        } catch (NumberFormatException nfe) {}  // Defaults to 0. 

        mPolicy.saveToLocal(passwordQuality, passwordLength, passwordMinUppercase);
    }
}

配置操作类:

package com.xiaoma.policymanager.demo; 

import android.app.Activity;
import android.app.admin.DeviceAdminReceiver;
import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build; 

/**
* @Title: Policy.java
* @Package com.xiaoma.policymanager.demo
* @Description: 用来获取相关安全配置信息的类
* @author MZH
*/
public class Policy {
    public static final int REQUEST_ADD_DEVICE_ADMIN = 1; 

    /**保存屏幕锁相关参数的SP文件名*/
    private static final String APP_PREF = "APP_PREF";
    /**下面三个是往SP中存储时的Key*/
    private static final String KEY_PASSWORD_LENGTH = "PW_LENGTH";
    private static final String KEY_PASSWORD_QUALITY = "PW_QUALITY";
    private static final String KEY_PASSWORD_MIN_UPPERCASE = "PW_MIN_UPPERCASE"; 

    /**
     * 下面是可允许输入密码的类型,此处的类型必须与string.xml文件中定义的arrays.xml中的相匹配
     */
    final static int[] PASSWORD_QUALITY_VALUES = new int[] {
        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED,
        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING,
        DevicePolicyManager.PASSWORD_QUALITY_NUMERIC,
        DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC,
        DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC,
        DevicePolicyManager.PASSWORD_QUALITY_COMPLEX
    }; 

    private int mPasswordQuality;
    private int mPasswordLength;
    private int mPasswordMinUpperCase;
    private Context mContext;
    private DevicePolicyManager mDPM;
    private ComponentName mPolicyAdmin; 

    /**
     * 构造器,在new此类对象时,获取系统级管理员对象 DevicePolicyManager
     * @param context
     */
    public Policy(Context context) {
        mContext = context;
        mPasswordQuality = -1;
        mPasswordLength = 0;
        mPasswordMinUpperCase = 0;
        mDPM = (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
        mPolicyAdmin = new ComponentName(context, PolicyAdmin.class);
    } 

    /**
     * 保存设备参数
     */
    public void saveToLocal(int passwordQuality, int passwordLength, int passwordMinUppercase) {
        SharedPreferences.Editor editor =
                mContext.getSharedPreferences(APP_PREF, Context.MODE_PRIVATE).edit();
        if (mPasswordQuality != passwordQuality) {
            editor.putInt(KEY_PASSWORD_QUALITY, passwordQuality);
            mPasswordQuality = passwordQuality;
        }
        if (mPasswordLength != passwordLength) {
            editor.putInt(KEY_PASSWORD_LENGTH, passwordLength);
            mPasswordLength = passwordLength;
        }
        if (mPasswordMinUpperCase != passwordMinUppercase) {
            editor.putInt(KEY_PASSWORD_MIN_UPPERCASE, passwordMinUppercase);
            mPasswordMinUpperCase = passwordMinUppercase;
        }
        editor.commit();
    } 

    /**
     * 从本地SP文件中获取密码配置参数
     */
    public void readFromLocal() {
        SharedPreferences prefs = mContext.getSharedPreferences(APP_PREF, Context.MODE_PRIVATE);
        mPasswordQuality = prefs.getInt(KEY_PASSWORD_QUALITY, -1);
        mPasswordLength = prefs.getInt(KEY_PASSWORD_LENGTH, -1);
        mPasswordMinUpperCase = prefs.getInt(KEY_PASSWORD_MIN_UPPERCASE, -1);
    } 

    /**
     * 获取密码.
     *
     * @return
     */
    public int getPasswordQuality() { return mPasswordQuality; } 

    /**
     * 获取密码长度.
     *
     * @return
     */
    public int getPasswordLength() { return mPasswordLength; } 

    /**
     * 获取字母密码.
     *
     * @return
     */
    public int getPasswordMinUpperCase() { return mPasswordMinUpperCase; } 

    /**
     * 获取设备管理的 ComponentName 对象.
     *
     * @return
     */
    public ComponentName getPolicyAdmin() { return mPolicyAdmin; } 

    /**
     * 判断设备是否被激活.
     *
     * @return
     */
    public boolean isAdminActive() {
        return mDPM.isAdminActive(mPolicyAdmin);
    } 

    public boolean isActivePasswordSufficient() {
        return mDPM.isActivePasswordSufficient();
    } 

    /**
     * 判断设备是否加安全
     * @return
     */
    public boolean isDeviceSecured() {
        return isAdminActive() && isActivePasswordSufficient();
    } 

    /**
     * 在声明的mDPM对象中进行配置.
     */
    public void configurePolicy() {
        mDPM.setPasswordQuality(mPolicyAdmin, PASSWORD_QUALITY_VALUES[mPasswordQuality]);
        mDPM.setPasswordMinimumLength(mPolicyAdmin, mPasswordLength);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            mDPM.setPasswordMinimumUpperCase(mPolicyAdmin, mPasswordMinUpperCase);
        }
    } 

    /**
     * 下面这个类用来监听各种不同类型的设备管理事件,比如:改变密码..错误密码等等
     */
    public static class PolicyAdmin extends DeviceAdminReceiver { 

        @Override
        public void onDisabled(Context context, Intent intent) {
            // Called when the app is about to be deactivated as a device administrator.
            super.onDisabled(context, intent);
            SharedPreferences prefs = context.getSharedPreferences(APP_PREF, Activity.MODE_PRIVATE);
            /**清除以前在SP文件下保存的所有值*/
            prefs.edit().clear().commit();
        }
    }
}

权限验证类:

package com.xiaoma.policymanager.demo; 

import android.app.Activity;
import android.content.Intent; 

/**
* @Title: SecureActivity.java
* @Package com.xiaoma.policymanager.demo
* @Description: 权限验证类实现
* @author MZH
*/
public class SecureActivity extends Activity { 

    @Override
    protected void onResume() {
        super.onResume();
        // Check to see if the device is properly secured as per the policy.  Send user
        // back to policy set up screen if necessary.
        Policy policy = new Policy(this);
        policy.readFromLocal();
        if (!policy.isDeviceSecured()) {
            Intent intent = new Intent();
            intent.setClass(this, PolicySetupActivity.class);
            intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP |
                            Intent.FLAG_ACTIVITY_CLEAR_TASK);
            startActivity(intent);
            finish();
        }
        setContentView(R.layout.activity_secure);
    }
}

一起学习,一起进步,如有小马讲不好的地方,请朋友直接批评指点..小马定感谢…谢谢..加油加油!

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Android研究院之应用程序屏幕锁定详解(二十四)》有 12 条评论

  1. Cloud说:

    楼主太强大了、我顶一个、学习ING,谢谢、

  2. 叶文说:

    咦,这篇的源码在哪里下载呢?

  3. 龚江鹏说:

    为什么没有早一点看到呢?

  4. 感谢小马的分享哈。。 哇咔咔

留下一个回复

你的email不会被公开。 必填项已用 * 标注。