近日需要设置密码并加密,因此仿写了Android的位置和安全设置有更改屏幕锁定的设置。先看效果图:

点击后,第一次是可设置密码。

设置成功密码后再点Button按钮将会出现:

由于时间紧,因此只研究了字母和数字设置的密码。

思路分析如下:

将密码加密后放置到一个文件里,如果读了来为空则认为没有设置密码,这样,你需要先设置密码,若不为空,则是要确认密码。因此需要一个设置密码的类ChooseMasterLockPassword,一个确认密码的类ConfirmMasterLockPassword,还有一个帮助类ChooseMasterLockSettingsHelper,和一个工具类LockPatternUtils(Android原来将这个类是放置在/frameworks/base/core/java/com/android/internal/widget下,我对它进行了改写,因为它原来是将数据保存到/data/system下面,权限不够的话就没法访问,并且这个类主要是为屏幕锁定服务,因此需要改写一下)。另外还有一个选择加密方式的类ChooseMasterLockGeneric,即选择密码为无还是pin加密或是密码加密。

主要代码如下:

[1] 先由Button点击进入到ChooseMasterLockGeneric:

ChooseMasterLockSettingsHelper helper = new ChooseMasterLockSettingsHelper(this);
helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) 来判断是否存在密码。

[2] 再在onPreferenceTreeClick中传入参数写入点击的响应代码:

updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);

如:清空密码:mChooseLockSettingsHelper.utils().clearMasterLock_KP();

设置密码:

Intent intent = new Intent().setClass(this, ChooseMasterLockPassword.class);
            intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
            intent.putExtra(ChooseMasterLockPassword.PASSWORD_MIN_KEY, minLength);
            intent.putExtra(ChooseMasterLockPassword.PASSWORD_MAX_KEY, maxLength);
            intent.putExtra(CONFIRM_CREDENTIALS, false);
            intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
            startActivity(intent);

启动到ChooseMasterLockPassword

[3]  如何保存密码:

String dataSystemDirectory = "/data/data/com.android.lock/";
// Added by Hao Jingjing at 2011-12-21
sLockMasterPasswordFilename_KP = dataSystemDirectory + LOCK_MASTERPASSWORD_FILE_KP;

通过:

public void saveMasterLockPassword_KP(String password) {
        // Compute the hash
        final byte[] hash = passwordToHash(password);
        try {
            // Write the hash to file
            RandomAccessFile raf = new RandomAccessFile(sLockMasterPasswordFilename_KP, "rw");
            // Truncate the file if pattern is null, to clear the lock
            if (password == null) {
                raf.setLength(0);
            } else {
                raf.write(hash, 0, hash.length);
            }
            raf.close();
        } catch (FileNotFoundException fnfe) {
            // Cant do much, unless we want to fail over to using the settings provider
            Log.e(TAG, "Unable to save lock pattern to " + sLockMasterPasswordFilename_KP);
        } catch (IOException ioe) {
            // Cant do much
            Log.e(TAG, "Unable to save lock pattern to " + sLockMasterPasswordFilename_KP);
        }
    }

进行保存。

列出主要代码如下:

src:

ChooseMasterLockGeneric.java:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.lock;

//import com.android.internal.widget.LockPatternUtils;

import android.app.admin.DevicePolicyManager;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;

public class ChooseMasterLockGeneric extends PreferenceActivity {
    private static final int MIN_PASSWORD_LENGTH = 4;
    private static final String KEY_UNLOCK_SET_NONE = "unlock_set_none";
    private static final String KEY_UNLOCK_SET_PIN = "unlock_set_pin";
    private static final String KEY_UNLOCK_SET_PASSWORD = "unlock_set_password";
    private static final String KEY_UNLOCK_SET_PATTERN = "unlock_set_pattern";
    private static final int CONFIRM_EXISTING_REQUEST = 100;
    private static final String PASSWORD_CONFIRMED = "password_confirmed";
    private static final String CONFIRM_CREDENTIALS = "confirm_credentials";

private ChooseMasterLockSettingsHelper mChooseLockSettingsHelper;
    private DevicePolicyManager mDPM;
    private boolean mPasswordConfirmed = false;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

mDPM = (DevicePolicyManager) getSystemService(Context.DEVICE_POLICY_SERVICE);
        mChooseLockSettingsHelper = new ChooseMasterLockSettingsHelper(this);

if (savedInstanceState != null) {
            mPasswordConfirmed = savedInstanceState.getBoolean(PASSWORD_CONFIRMED);
        }

if (!mPasswordConfirmed) {
            ChooseMasterLockSettingsHelper helper = new ChooseMasterLockSettingsHelper(this);
            if (!helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST, null, null)) {
                mPasswordConfirmed = true; // no password set, so no need to confirm
                updatePreferencesOrFinish();
            }
        } else {
            updatePreferencesOrFinish();
        }
    }

@Override
    public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
            Preference preference) {
        final String key = preference.getKey();
        boolean handled = true;
        if (KEY_UNLOCK_SET_NONE.equals(key)) {
            updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
        } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
            updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
        } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
            updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_NUMERIC);
        } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
            updateUnlockMethodAndFinish(DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC);
        } else {
            handled = false;
        }
        return handled;
    }

@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == CONFIRM_EXISTING_REQUEST && resultCode == RESULT_OK) {
            mPasswordConfirmed = true;
            updatePreferencesOrFinish();
        } else {
            setResult(RESULT_CANCELED);
            finish();
        }
    }

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        // Saved so we don't force user to re-enter their password if configuration changes
        outState.putBoolean(PASSWORD_CONFIRMED, mPasswordConfirmed);
    }

private void updatePreferencesOrFinish() {
        int quality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
        if (quality == -1) {
            // If caller didn't specify password quality, show the UI and allow the user to choose.
            quality = mChooseLockSettingsHelper.utils().getKeyguardStoredPasswordQuality();
            final PreferenceScreen prefScreen = getPreferenceScreen();
            if (prefScreen != null) {
                prefScreen.removeAll();
            }
            addPreferencesFromResource(R.xml.security_settings_picker);
            disableUnusablePreferences(mDPM.getPasswordQuality(null));
        } else {
            updateUnlockMethodAndFinish(quality);
        }
    }

/***
     * Disables preferences that are less secure than required quality.
     *
     * @param quality the requested quality.
     */
    private void disableUnusablePreferences(final int quality) {
        final Preference picker = getPreferenceScreen().findPreference("security_picker_category");
        final PreferenceCategory cat = (PreferenceCategory) picker;
        final int preferenceCount = cat.getPreferenceCount();
        for (int i = 0; i < preferenceCount; i++) {
            Preference pref = cat.getPreference(i);
            if (pref instanceof PreferenceScreen) {
                final String key = ((PreferenceScreen) pref).getKey();
                boolean enabled = true;
                if (KEY_UNLOCK_SET_NONE.equals(key)) {
                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
                } else if (KEY_UNLOCK_SET_PATTERN.equals(key)) {
                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
                } else if (KEY_UNLOCK_SET_PIN.equals(key)) {
                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
                } else if (KEY_UNLOCK_SET_PASSWORD.equals(key)) {
                    enabled = quality <= DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC;
                }
                if (!enabled) {
                    pref.setSummary(R.string.unlock_set_unlock_disabled_summary);
                    pref.setEnabled(false);
                }
            }
        }
    }

/**
     * Invokes an activity to change the user's pattern, password or PIN based on given quality
     * and minimum quality specified by DevicePolicyManager. If quality is
     * {@link DevicePolicyManager#PASSWORD_QUALITY_UNSPECIFIED}, password is cleared.
     *
     * @param quality the desired quality. Ignored if DevicePolicyManager requires more security.
     */
    void updateUnlockMethodAndFinish(int quality) {
        // Sanity check. We should never get here without confirming user's existing password first.
        if (!mPasswordConfirmed) {
            throw new IllegalStateException("Tried to update password without confirming first");
        }

// Compare minimum allowed password quality and launch appropriate security setting method
        int minQuality = mDPM.getPasswordQuality(null);
        if (quality < minQuality) {
            quality = minQuality;
        }
        if (quality >= DevicePolicyManager.PASSWORD_QUALITY_NUMERIC) {
            //设置密码
            int minLength = mDPM.getPasswordMinimumLength(null);
            if (minLength < MIN_PASSWORD_LENGTH) {
                minLength = MIN_PASSWORD_LENGTH;
            }
            final int maxLength = mDPM.getPasswordMaximumLength(quality);
            Intent intent = new Intent().setClass(this, ChooseMasterLockPassword.class);
            intent.putExtra(LockPatternUtils.PASSWORD_TYPE_KEY, quality);
            intent.putExtra(ChooseMasterLockPassword.PASSWORD_MIN_KEY, minLength);
            intent.putExtra(ChooseMasterLockPassword.PASSWORD_MAX_KEY, maxLength);
            intent.putExtra(CONFIRM_CREDENTIALS, false);
            intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
            startActivity(intent);
        } else if (quality == DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED) {
            //清空密码
            mChooseLockSettingsHelper.utils().clearMasterLock_KP();
            setResult(RESULT_OK);
        }
        finish();
    }
}

ChooseMasterLockPassword.java:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.lock;

//import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.content.Intent;
import android.inputmethodservice.KeyboardView;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.text.Selection;
import android.text.Spannable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;

public class ChooseMasterLockPassword extends Activity implements OnClickListener, OnEditorActionListener,
        TextWatcher {
    private static final String KEY_FIRST_PIN = "first_pin";
    private static final String KEY_UI_STAGE = "ui_stage";
    private TextView mPasswordEntry;
    private int mPasswordMinLength = 4;
    private int mPasswordMaxLength = 16;
    private LockPatternUtils mLockPatternUtils;
    private int mRequestedQuality = DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
    private ChooseMasterLockSettingsHelper mChooseLockSettingsHelper;
    private ChooseMasterLockPassword.Stage mUiStage = Stage.Introduction;
    private TextView mHeaderText;
    private String mFirstPin;
    private KeyboardView mKeyboardView;
    private PasswordEntryKeyboardHelper mKeyboardHelper;
    private boolean mIsAlphaMode;
    private Button mCancelButton;
    private Button mNextButton;
    public static final String PASSWORD_MIN_KEY = "lockscreen.password_min";
    public static final String PASSWORD_MAX_KEY = "lockscreen.password_max";
    private static Handler mHandler = new Handler();
    private static final int CONFIRM_EXISTING_REQUEST = 58;
    static final int RESULT_FINISHED = RESULT_FIRST_USER;
    private static final long ERROR_MESSAGE_TIMEOUT = 3000;

/**
     * Keep track internally of where the user is in choosing a pattern.
     */
    protected enum Stage {

Introduction(R.string.lockpassword_choose_your_password_header,
                R.string.lockpassword_choose_your_pin_header,
                R.string.lockpassword_continue_label),

NeedToConfirm(R.string.lockpassword_confirm_your_password_header,
                R.string.lockpassword_confirm_your_pin_header,
                R.string.lockpassword_ok_label),

ConfirmWrong(R.string.lockpassword_confirm_passwords_dont_match,
                R.string.lockpassword_confirm_pins_dont_match,
                R.string.lockpassword_continue_label);

/**
         * @param headerMessage The message displayed at the top.
         */
        Stage(int hintInAlpha, int hintInNumeric, int nextButtonText) {
            this.alphaHint = hintInAlpha;
            this.numericHint = hintInNumeric;
            this.buttonText = nextButtonText;
        }

public final int alphaHint;
        public final int numericHint;
        public final int buttonText;
    }

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLockPatternUtils = new LockPatternUtils(this);
        mRequestedQuality = getIntent().getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, mRequestedQuality);
        mPasswordMinLength = getIntent().getIntExtra(PASSWORD_MIN_KEY, mPasswordMinLength);
        mPasswordMaxLength = getIntent().getIntExtra(PASSWORD_MAX_KEY, mPasswordMaxLength);

final boolean confirmCredentials = getIntent().getBooleanExtra("confirm_credentials", true);
        int minMode = mLockPatternUtils.getRequestedPasswordQuality();
        if (mRequestedQuality < minMode) {
            mRequestedQuality = minMode;
        }
        int minLength = mLockPatternUtils.getRequestedMinimumPasswordLength();
        if (mPasswordMinLength < minLength) {
            mPasswordMinLength = minLength;
        }
        initViews();
        mChooseLockSettingsHelper = new ChooseMasterLockSettingsHelper(this);
        if (savedInstanceState == null) {
            updateStage(Stage.Introduction);
            if (confirmCredentials) {
                mChooseLockSettingsHelper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,
                        null, null);
            }
        }
    }

private void initViews() {
        setContentView(R.layout.choose_lock_password);
        // Disable IME on our window since we provide our own keyboard
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

mCancelButton = (Button) findViewById(R.id.cancel_button);
        mCancelButton.setOnClickListener(this);
        mNextButton = (Button) findViewById(R.id.next_button);
        mNextButton.setOnClickListener(this);

mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
        mPasswordEntry = (TextView) findViewById(R.id.password_entry);
        mPasswordEntry.setOnEditorActionListener(this);
        mPasswordEntry.addTextChangedListener(this);

mIsAlphaMode = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == mRequestedQuality
            || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == mRequestedQuality;
        mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
        mKeyboardHelper.setKeyboardMode(mIsAlphaMode ?
                PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);

mHeaderText = (TextView) findViewById(R.id.headerText);
        mKeyboardView.requestFocus();
    }

@Override
    protected void onResume() {
        super.onResume();
        updateStage(mUiStage);
        mKeyboardView.requestFocus();
    }

@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString(KEY_UI_STAGE, mUiStage.name());
        outState.putString(KEY_FIRST_PIN, mFirstPin);
    }

@Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        String state = savedInstanceState.getString(KEY_UI_STAGE);
        mFirstPin = savedInstanceState.getString(KEY_FIRST_PIN);
        if (state != null) {
            mUiStage = Stage.valueOf(state);
            updateStage(mUiStage);
        }
    }

//    @Override
//    protected void onActivityResult(int requestCode, int resultCode,
//            Intent data) {
//        super.onActivityResult(requestCode, resultCode, data);
//        switch (requestCode) {
//            case CONFIRM_EXISTING_REQUEST:
//                if (resultCode != Activity.RESULT_OK) {
//                    setResult(RESULT_FINISHED);
//                    finish();
//                }
//                break;
//        }
//    }

protected void updateStage(Stage stage) {
        mUiStage = stage;
        updateUi();
    }

/**
     * Validates PIN and returns a message to display if PIN fails test.
     * @param password the raw password the user typed in
     * @return error message to show to user or null if password is OK
     */
    private String validatePassword(String password) {
        if (password.length() < mPasswordMinLength) {
            return getString(mIsAlphaMode ?
                    R.string.lockpassword_password_too_short
                    : R.string.lockpassword_pin_too_short, mPasswordMinLength);
        }
        if (password.length() > mPasswordMaxLength) {
            return getString(mIsAlphaMode ?
                    R.string.lockpassword_password_too_long
                    : R.string.lockpassword_pin_too_long, mPasswordMaxLength);
        }
        boolean hasAlpha = false;
        boolean hasDigit = false;
        boolean hasSymbol = false;
        for (int i = 0; i < password.length(); i++) {
            char c = password.charAt(i);
            // allow non white space Latin-1 characters only
            if (c <= 32 || c > 127) {
                return getString(R.string.lockpassword_illegal_character);
            }
            if (c >= '0' && c <= '9') {
                hasDigit = true;
            } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
                hasAlpha = true;
            } else {
                hasSymbol = true;
            }
        }
        if (DevicePolicyManager.PASSWORD_QUALITY_NUMERIC == mRequestedQuality
                && (hasAlpha | hasSymbol)) {
            // This shouldn't be possible unless user finds some way to bring up soft keyboard
            return getString(R.string.lockpassword_pin_contains_non_digits);
        } else {
            final boolean alphabetic = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
                    == mRequestedQuality;
            final boolean alphanumeric = DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
                    == mRequestedQuality;
            final boolean symbolic = false; // not yet
            if ((alphabetic || alphanumeric) && !hasAlpha) {
                return getString(R.string.lockpassword_password_requires_alpha);
            }
            if (alphanumeric && !hasDigit) {
                return getString(R.string.lockpassword_password_requires_digit);
            }
            if (symbolic && !hasSymbol) {
                return getString(R.string.lockpassword_password_requires_symbol);
            }
        }
        return null;
    }

private void handleNext() {
        final String pin = mPasswordEntry.getText().toString();
        if (TextUtils.isEmpty(pin)) {
            return;
        }
        String errorMsg = null;
        if (mUiStage == Stage.Introduction) {
            errorMsg = validatePassword(pin);
            if (errorMsg == null) {
                mFirstPin = pin;
                updateStage(Stage.NeedToConfirm);
                mPasswordEntry.setText("");
            }
        } else if (mUiStage == Stage.NeedToConfirm) {
            if (mFirstPin.equals(pin)) {
                mLockPatternUtils.clearMasterLock_KP();
                mLockPatternUtils.saveMasterLockPassword_KP(pin);
                setResult(RESULT_OK);
                finish();
            } else {
                updateStage(Stage.ConfirmWrong);
                CharSequence tmp = mPasswordEntry.getText();
                if (tmp != null) {
                    Selection.setSelection((Spannable) tmp, 0, tmp.length());
                }
            }
        }
        if (errorMsg != null) {
            showError(errorMsg, mUiStage);
        }
    }

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.next_button:
                handleNext();
                break;

case R.id.cancel_button:
                finish();
                break;
        }
    }

private void showError(String msg, final Stage next) {
        mHeaderText.setText(msg);
        mHandler.postDelayed(new Runnable() {
            public void run() {
                updateStage(next);
            }
        }, ERROR_MESSAGE_TIMEOUT);
    }

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Check if this was the result of hitting the enter key
        if (actionId == EditorInfo.IME_NULL) {
            handleNext();
            return true;
        }
        return false;
    }

/**
     * Update the hint based on current Stage and length of password entry
     */
    private void updateUi() {
        String password = mPasswordEntry.getText().toString();
        final int length = password.length();
        if (mUiStage == Stage.Introduction && length > 0) {
            if (length < mPasswordMinLength) {
                String msg = getString(mIsAlphaMode ? R.string.lockpassword_password_too_short
                        : R.string.lockpassword_pin_too_short, mPasswordMinLength);
                mHeaderText.setText(msg);
                mNextButton.setEnabled(false);
            } else {
                String error = validatePassword(password);
                if (error != null) {
                    mHeaderText.setText(error);
                    mNextButton.setEnabled(false);
                } else {
                    mHeaderText.setText(R.string.lockpassword_press_continue);
                    mNextButton.setEnabled(true);
                }
            }
        } else {
            mHeaderText.setText(mIsAlphaMode ? mUiStage.alphaHint : mUiStage.numericHint);
            mNextButton.setEnabled(length > 0);
        }
        mNextButton.setText(mUiStage.buttonText);
    }

public void afterTextChanged(Editable s) {
        // Changing the text while error displayed resets to NeedToConfirm state
        if (mUiStage == Stage.ConfirmWrong) {
            mUiStage = Stage.NeedToConfirm;
        }
        updateUi();
    }

public void beforeTextChanged(CharSequence s, int start, int count, int after) {

}

public void onTextChanged(CharSequence s, int start, int before, int count) {

}
}

ChooseMasterLockSettingsHelper.java:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.lock;

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

//import com.android.internal.widget.LockPatternUtils;

public class ChooseMasterLockSettingsHelper {
    private LockPatternUtils mLockPatternUtils;
    private Activity mActivity;

public ChooseMasterLockSettingsHelper(Activity activity) {
        mActivity = activity;
        mLockPatternUtils = new LockPatternUtils(activity);
    }

public LockPatternUtils utils() {
        return mLockPatternUtils;
    }

/**
     * If a pattern, password or PIN exists, prompt the user before allowing them to change it.
     * @param message optional message to display about the action about to be done
     * @param details optional detail message to display
     * @return true if one exists and we launched an activity to confirm it
     * @see #onActivityResult(int, int, android.content.Intent)
     */
    protected boolean launchConfirmationActivity(int request,
            CharSequence message, CharSequence details) {
        boolean launched = false;
        launched = confirmPassword(request);
        return launched;
    }

/**
     * Launch screen to confirm the existing lock password.
     * @see #onActivityResult(int, int, android.content.Intent)
     * @return true if we launched an activity to confirm password
     */
    private boolean confirmPassword(int request) {
        if (!mLockPatternUtils.isLockMasterPasswordEnabled_KP()) return false;
        final Intent intent = new Intent();
        intent.setClassName("com.android.lock", "com.android.lock.ConfirmMasterLockPassword");
        mActivity.startActivityForResult(intent, request);
        return true;
    }

}

ConfirmMasterLockPassword.java:

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.lock;

//import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.PasswordEntryKeyboardHelper;
import com.android.internal.widget.PasswordEntryKeyboardView;

import android.app.Activity;
import android.app.admin.DevicePolicyManager;
import android.os.Bundle;
import android.os.Handler;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;

public class ConfirmMasterLockPassword extends Activity implements OnClickListener,
        OnEditorActionListener {
    private static final long ERROR_MESSAGE_TIMEOUT = 3000;
    private TextView mPasswordEntry;
    private LockPatternUtils mLockPatternUtils;
    private TextView mHeaderText;
    private Handler mHandler = new Handler();
    private PasswordEntryKeyboardHelper mKeyboardHelper;
    private PasswordEntryKeyboardView mKeyboardView;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mLockPatternUtils = new LockPatternUtils(this);
        initViews();
    }

private void initViews() {
        final int storedQuality = 131072;
        setContentView(R.layout.confirm_lock_password);
        // Disable IME on our window since we provide our own keyboard
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
                WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);

findViewById(R.id.cancel_button).setOnClickListener(this);
        findViewById(R.id.next_button).setOnClickListener(this);
        mPasswordEntry = (TextView) findViewById(R.id.password_entry);
        mPasswordEntry.setOnEditorActionListener(this);
        mKeyboardView = (PasswordEntryKeyboardView) findViewById(R.id.keyboard);
        mHeaderText = (TextView) findViewById(R.id.headerText);
        final boolean isAlpha = DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC == storedQuality
                || DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC == storedQuality;
        mHeaderText.setText(isAlpha ? R.string.lockpassword_confirm_your_password_header
                : R.string.lockpassword_confirm_your_pin_header);
        mKeyboardHelper = new PasswordEntryKeyboardHelper(this, mKeyboardView, mPasswordEntry);
        mKeyboardHelper.setKeyboardMode(isAlpha ? PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA
                : PasswordEntryKeyboardHelper.KEYBOARD_MODE_NUMERIC);
        mKeyboardView.requestFocus();
    }

@Override
    protected void onPause() {
        super.onPause();
        mKeyboardView.requestFocus();
    }

@Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        mKeyboardView.requestFocus();
    }

private void handleNext() {
        final String pin = mPasswordEntry.getText().toString();
        if (mLockPatternUtils.checkMasterPassword_KP(pin)) {
            setResult(RESULT_OK);
            finish();
        } else {
            showError(R.string.lockpattern_need_to_unlock_wrong);
        }
    }

public void onClick(View v) {
        switch (v.getId()) {
            case R.id.next_button:
                handleNext();
                break;

case R.id.cancel_button:
                setResult(RESULT_CANCELED);
                finish();
                break;
        }
    }

private void showError(int msg) {
        mHeaderText.setText(msg);
        mPasswordEntry.setText(null);
        mHandler.postDelayed(new Runnable() {
            public void run() {
                mHeaderText.setText(R.string.lockpassword_confirm_your_password_header);
            }
        }, ERROR_MESSAGE_TIMEOUT);
    }

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
        // Check if this was the result of hitting the enter key
        if (actionId == EditorInfo.IME_NULL) {
            handleNext();
            return true;
        }
        return false;
    }
}

LockPatternUtils.java:

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.lock;

import android.content.ContentResolver;
import android.content.Context;
import android.os.FileObserver;
import android.security.MessageDigest;
import android.util.Log;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Utilities for the lock patten and its settings.
 */
public class LockPatternUtils {

private static final String TAG = "LockPatternUtils";

private static final String SYSTEM_DIRECTORY = "/system/";
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    private static final String LOCK_MASTERPASSWORD_FILE_KP = "kpone_master_password.key";

/**
     * The maximum number of incorrect attempts before the user is prevented
     * from trying again for {@link #FAILED_ATTEMPT_TIMEOUT_MS}.
     */
    public static final int FAILED_ATTEMPTS_BEFORE_TIMEOUT = 5;

/**
     * The number of incorrect attempts before which we fall back on an alternative
     * method of verifying the user, and resetting their lock pattern.
     */
    public static final int FAILED_ATTEMPTS_BEFORE_RESET = 20;

/**
     * How long the user is prevented from trying again after entering the
     * wrong pattern too many times.
     */
    public static final long FAILED_ATTEMPT_TIMEOUT_MS = 30000L;

/**
     * The interval of the countdown for showing progress of the lockout.
     */
    public static final long FAILED_ATTEMPT_COUNTDOWN_INTERVAL_MS = 1000L;

public final static String PASSWORD_TYPE_KEY = "kphone_master.password_type";
    private final static String LOCK_PASSWORD_SALT_KEY = "kphone_master.password_salt";

private final Context mContext;
    private final ContentResolver mContentResolver;
//    private static String sLockPasswordFilename;
    
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    private static String sLockMasterPasswordFilename_KP;
    
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    private static final AtomicBoolean sMasterHaveNonZeroPasswordFile_KP = new AtomicBoolean(false);
    
    private static FileObserver sPasswordObserver;

public LockPatternUtils(Context context) {
        mContext = context;
        mContentResolver = context.getContentResolver();

//        String dataSystemDirectory =
//                android.os.Environment.getDataDirectory().getAbsolutePath() + SYSTEM_DIRECTORY;
        String dataSystemDirectory = "/data/data/com.android.lock/";
        // Added by Hao Jingjing at 2011-12-21
        sLockMasterPasswordFilename_KP = dataSystemDirectory + LOCK_MASTERPASSWORD_FILE_KP;
        sMasterHaveNonZeroPasswordFile_KP.set(new File(sLockMasterPasswordFilename_KP).length() > 0);
        // end by hjj
        
        int fileObserverMask = FileObserver.CLOSE_WRITE | FileObserver.DELETE |
                FileObserver.MOVED_TO | FileObserver.CREATE;
        sPasswordObserver = new FileObserver(dataSystemDirectory, fileObserverMask) {
                public void onEvent(int event, String path) {
                    // Added by Hao Jingjing at 2011-12-21
                    if(LOCK_MASTERPASSWORD_FILE_KP.equals(path)){
                        sMasterHaveNonZeroPasswordFile_KP.set(new File(sLockMasterPasswordFilename_KP).length() > 0);
                    }
                    // end by hjj
                }
            };
        sPasswordObserver.startWatching();
    }

public int getRequestedMinimumPasswordLength() {
        return 4;
    }
    
    public int getRequestedPasswordQuality() {
        return 131072;
    }

/**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    public boolean checkMasterPassword_KP(String password) {
        try {
            // Read all the bytes from the file
            RandomAccessFile raf = new RandomAccessFile(sLockMasterPasswordFilename_KP, "r");
            final byte[] stored = new byte[(int) raf.length()];
            int got = raf.read(stored, 0, stored.length);
            raf.close();
            if (got <= 0) {
                return true;
            }
            // Compare the hash from the file with the entered password's hash
            return Arrays.equals(stored, passwordToHash(password));
        } catch (FileNotFoundException fnfe) {
            return true;
        } catch (IOException ioe) {
            return true;
        }
    }
    
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    public boolean savedMasterPasswordExists_KP() {
        return sMasterHaveNonZeroPasswordFile_KP.get();
    }

/**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    public void saveMasterLockPassword_KP(String password) {
        // Compute the hash
        final byte[] hash = passwordToHash(password);
        try {
            // Write the hash to file
            RandomAccessFile raf = new RandomAccessFile(sLockMasterPasswordFilename_KP, "rw");
            // Truncate the file if pattern is null, to clear the lock
            if (password == null) {
                raf.setLength(0);
            } else {
                raf.write(hash, 0, hash.length);
            }
            raf.close();
        } catch (FileNotFoundException fnfe) {
            // Cant do much, unless we want to fail over to using the settings provider
            Log.e(TAG, "Unable to save lock pattern to " + sLockMasterPasswordFilename_KP);
        } catch (IOException ioe) {
            // Cant do much
            Log.e(TAG, "Unable to save lock pattern to " + sLockMasterPasswordFilename_KP);
        }
    }
    
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    public void clearMasterLock_KP() {
        saveMasterLockPassword_KP(null);
    }
    
    /**
     * @hide
     * Added by Hao Jingjing at 2011-12-21
     */
    public boolean isLockMasterPasswordEnabled_KP() {
        return savedMasterPasswordExists_KP();
    }
    
    /**
     * Used by device policy manager to validate the current password
     * information it has.
     */
    public int getActivePasswordQuality() {
        return 131072;
    }

/**
     * Retrieves the quality mode we're in.
     * {@see DevicePolicyManager#getPasswordQuality(android.content.ComponentName)}
     *
     * @return stored password quality
     */
    public int getKeyguardStoredPasswordQuality() {
        return (int) 131072;
    }

private String getSalt() {
        long salt = getLong(LOCK_PASSWORD_SALT_KEY, 0);
        if (salt == 0) {
            try {
                salt = SecureRandom.getInstance("SHA1PRNG").nextLong();
                setLong(LOCK_PASSWORD_SALT_KEY, salt);
                Log.v(TAG, "Initialized lock password salt");
            } catch (NoSuchAlgorithmException e) {
                // Throw an exception rather than storing a password we'll never be able to recover
                throw new IllegalStateException("Couldn't get SecureRandom number", e);
            }
        }
        return Long.toHexString(salt);
    }

/*
     * Generate a hash for the given password. To avoid brute force attacks, we use a salted hash.
     * Not the most secure, but it is at least a second level of protection. First level is that
     * the file is in a location only readable by the system process.
     * @param password the gesture pattern.
     * @return the hash of the pattern in a byte array.
     */
     public byte[] passwordToHash(String password) {
        if (password == null) {
            return null;
        }
        String algo = null;
        byte[] hashed = null;
        try {
            byte[] saltedPassword = (password + getSalt()).getBytes();
            byte[] sha1 = MessageDigest.getInstance(algo = "SHA-1").digest(saltedPassword);
            byte[] md5 = MessageDigest.getInstance(algo = "MD5").digest(saltedPassword);
            hashed = (toHex(sha1) + toHex(md5)).getBytes();
        } catch (NoSuchAlgorithmException e) {
            Log.w(TAG, "Failed to encode string because of missing algorithm: " + algo);
        }
        return hashed;
    }

private static String toHex(byte[] ary) {
        final String hex = "0123456789ABCDEF";
        String ret = "";
        for (int i = 0; i < ary.length; i++) {
            ret += hex.charAt((ary[i] >> 4) & 0xf);
            ret += hex.charAt(ary[i] & 0xf);
        }
        return ret;
    }

private long getLong(String secureSettingKey, long def) {
        //return android.provider.Settings.Secure.getLong(mContentResolver, secureSettingKey, def);
        return android.provider.Settings.System.getLong(mContentResolver, secureSettingKey, def);
    }

private void setLong(String secureSettingKey, long value) {
        //android.provider.Settings.Secure.putLong(mContentResolver, secureSettingKey, value);
        android.provider.Settings.System.putLong(mContentResolver, secureSettingKey, value);
    }

}

这些代码都是参考com.android.settings这个应用中的代码,相关res文件也在这个应用中。

仿写Android屏幕解锁小应用相关推荐

  1. 计算Android屏幕解锁组合数

    计算Android屏幕解锁组合数 晚饭时和同事聊到安卓屏幕解锁时会有多少种解锁方案,觉得很有趣,吃完饭开始想办法解题,花了大概2个小时解决.思路如下: 使用索引值0-9表示从左到右.从上到下的9个点, ...

  2. Android屏幕解锁图案破解

    标 题: [原创]Android屏幕解锁图案破解 作 者: gamehacker 时 间: 2013-03-27,14:29:58 链 接: http://bbs.pediy.com/showthre ...

  3. 【移动安全实战篇】————5、Android屏幕解锁图案破解

    Android手机上有一个屏幕解锁的应用相信大家都不陌生,在 Android 设备上,用户可以通过设置锁定图案作为密码对设备用户界面进行锁定,锁定界面如下图所示. 一般的Android手机的锁定界面由 ...

  4. android屏幕解锁新解

    最近因为一些事接触到android屏幕解锁这块,刚开始查询网上资料,绝大部分以keyguardLock 来进行获取屏幕锁和接触屏幕锁,其思路如下: // KeyguardManager keyguar ...

  5. android屏幕解锁新思路

    最近接了个私活,涉及到屏幕解锁,由于从来没接触过这块方面的知识,网上找了很多相关的内容,基本上都是以 private PowerManager.WakeLock wl; private Keyguar ...

  6. Android屏幕解锁和点亮

    有些场景需要程序自动点亮屏幕,解开屏幕锁,以方便用户即时操作,下面用代码来实现这一功能: 1.//得到键盘锁管理器对象 2.KeyguardManager  km= (KeyguardManager) ...

  7. android屏幕解锁图案,安卓手机图案屏幕锁解锁方法!!

    当你的安卓手机密码锁忘记了怎么办?今天一不小心把手机改了图案锁结果由于改的时候匆忙结果忘记了,在网上找了好多方法都无果,也有人说重新刷机就会好!!这个简直就是废话,刷机当然能好了!! 关键是解锁要解决 ...

  8. Android点亮屏幕或屏幕解锁和锁定

    1.Android屏幕常亮/点亮 //保持屏幕常亮 PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); ...

  9. 4个顶级的华为/小米/OPPO/Vivo手机屏幕解锁工具软件

    有好几次用户发现自己被锁定在他们的华为/小米/OPPO/Vivo设备之外,我们知道这可能是一种非常可怕的体验.在这种情况下,找到安卓手机解锁软件,重新获得手机中重要数据和文件的访问权限.看看这篇文章, ...

最新文章

  1. UVa10375 Choose and divide
  2. Oracle 10.2.0.4和10.2.0.5 中 OEM bug 8350262
  3. android 模拟点击localinstrumentation,Android Instrumentation模拟鼠标点击事件
  4. api 定位 微信小程序 精度_微信小程序开发知识点集锦
  5. select count(*)和select count(1)的区别(转载)
  6. Hadoop生态hive(一)介绍
  7. java ee jsp_EE JSP:Servlet的反向外套
  8. 不拥抱算法的张小龙,还能带着微信继续避免失败?
  9. Linux中,Tomcat安装
  10. ubuntu服务器系统不识别,U盘安装16.04server版 安装好后重启 无法进入系统
  11. [转载] python——连接Oracle数据库
  12. 用python做一个抖音上很火的罗盘时钟
  13. python django项目创建步骤
  14. 考勤机信息同步不到服务器,如何同步考勤机数据?
  15. Android 蓝牙知识
  16. 利用python处理Excel表格中的销售数据
  17. Map GIS绘制线文件以及线文件转区文件
  18. LED点阵屏实现文字滚动
  19. Webix - JavaScript UI 9.2.0
  20. 20145206《Java程序设计》实验二Java面向对象程序设计实验报告

热门文章

  1. 五百内的蓝牙耳机哪款好?2022年五百内超好用的蓝牙耳机推荐
  2. 各行业的企业家们如何制定运营战略?
  3. 无敌的服务注册中心Spring CloudAlibaba Nacos不进来看一看吗?
  4. 开发人员和运营人员将继续在2017年重访其在企业中的角色
  5. laravel7 学习(19)批量删除,软删除
  6. Baumer万兆网工业相机堡盟相机Gige网口连接PC如何实现最大帧率
  7. ubuntu解压rar文件一句命令轻松搞定
  8. 快递驿站(数组存储Java版)
  9. 携手航天·追求卓越|诚邀优秀企业加入航天采购平台供应商库
  10. Android 引入OpenCL详细步骤