FileDocCategorySizeDatePackage
ChooseLockPattern.javaAPI DocAndroid 1.5 API18369Wed May 06 22:42:48 BST 2009com.android.settings

ChooseLockPattern

public class ChooseLockPattern extends android.app.Activity implements View.OnClickListener
If the user has a lock pattern set already, makes them confirm the existing one. Then, prompts the user to choose a lock pattern: - prompts for initial pattern - asks for confirmation / restart - saves chosen password when confirmed

Fields Summary
static final int
RESULT_FINISHED
Used by the choose lock pattern wizard to indicate the wizard is finished, and each activity in the wizard should finish.

Previously, each activity in the wizard would finish itself after starting the next activity. However, this leads to broken 'Back' behavior. So, now an activity does not finish itself until it gets this result.

static final int
INFORMATION_MSG_TIMEOUT_MS
private static final int
WRONG_PATTERN_CLEAR_TIMEOUT_MS
private static final int
ID_EMPTY_MESSAGE
protected android.widget.TextView
mHeaderText
protected com.android.internal.widget.LockPatternView
mLockPatternView
protected android.widget.TextView
mFooterText
private android.widget.TextView
mFooterLeftButton
private android.widget.TextView
mFooterRightButton
protected List
mChosenPattern
protected com.android.internal.widget.LockPatternUtils
mLockPatternUtils
private final List
mAnimatePattern
The patten used during the help screen to show how to draw a pattern.
protected LockPatternView.OnPatternListener
mChooseNewLockPatternListener
The pattern listener that responds according to a user choosing a new lock pattern.
private Stage
mUiStage
private Runnable
mClearPatternRunnable
private static final String
KEY_UI_STAGE
private static final String
KEY_PATTERN_CHOICE
Constructors Summary
Methods Summary
protected voidconfirmPattern()
Launch screen to confirm the existing lock pattern.

see
#onActivityResult(int, int, android.content.Intent)

        final Intent intent = new Intent();
        intent.setClassName("com.android.settings", "com.android.settings.ConfirmLockPattern");
        startActivityForResult(intent, 55);
    
protected voidonActivityResult(int requestCode, int resultCode, android.content.Intent data)

see
#confirmPattern

        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode != 55) {
            return;
        }

        if (resultCode != Activity.RESULT_OK) {
            setResult(RESULT_FINISHED);
            finish();
        }
        updateStage(Stage.Introduction);
    
public voidonClick(android.view.View v)

        if (v == mFooterLeftButton) {
            if (mUiStage.leftMode == LeftButtonMode.Retry) {
                mChosenPattern = null;
                mLockPatternView.clearPattern();
                updateStage(Stage.Introduction);
            } else if (mUiStage.leftMode == LeftButtonMode.Cancel) {
                // They are canceling the entire wizard
                setResult(RESULT_FINISHED);
                finish();
            } else {
                throw new IllegalStateException("left footer button pressed, but stage of " +
                    mUiStage + " doesn't make sense");
            }
        } else if (v == mFooterRightButton) {

            if (mUiStage.rightMode == RightButtonMode.Continue) {
                if (mUiStage != Stage.FirstChoiceValid) {
                    throw new IllegalStateException("expected ui stage " + Stage.FirstChoiceValid
                            + " when button is " + RightButtonMode.Continue);
                }
                updateStage(Stage.NeedToConfirm);
            } else if (mUiStage.rightMode == RightButtonMode.Confirm) {
                if (mUiStage != Stage.ChoiceConfirmed) {
                    throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
                            + " when button is " + RightButtonMode.Confirm);
                }
                saveChosenPatternAndFinish();
            } else if (mUiStage.rightMode == RightButtonMode.Ok) {
                if (mUiStage != Stage.HelpScreen) {
                    throw new IllegalStateException("Help screen is only mode with ok button, but " +
                            "stage is " + mUiStage);
                }
                mLockPatternView.clearPattern();
                mLockPatternView.setDisplayMode(DisplayMode.Correct);
                updateStage(Stage.Introduction);
            }
        }
    
protected voidonCreate(android.os.Bundle savedInstanceState)


    
        
        super.onCreate(savedInstanceState);

        mLockPatternUtils = new LockPatternUtils(getContentResolver());

        requestWindowFeature(Window.FEATURE_NO_TITLE);

        setupViews();
        
        // make it so unhandled touch events within the unlock screen go to the
        // lock pattern view.
        final LinearLayoutWithDefaultTouchRecepient topLayout
                = (LinearLayoutWithDefaultTouchRecepient) findViewById(
                R.id.topLayout);
        topLayout.setDefaultTouchRecepient(mLockPatternView);

        if (savedInstanceState == null) {
            // first launch
            updateStage(Stage.Introduction);
            if (mLockPatternUtils.savedPatternExists()) {
                confirmPattern();
            } 
        } else {
            // restore from previous state
            final String patternString = savedInstanceState.getString(KEY_PATTERN_CHOICE);
            if (patternString != null) {
                mChosenPattern = LockPatternUtils.stringToPattern(patternString);
            }
            updateStage(Stage.values()[savedInstanceState.getInt(KEY_UI_STAGE)]);
        }
    
public booleanonKeyDown(int keyCode, android.view.KeyEvent event)

        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            if (mUiStage == Stage.HelpScreen) {
                updateStage(Stage.Introduction);
                return true;
            }
        }
        if (keyCode == KeyEvent.KEYCODE_MENU && mUiStage == Stage.Introduction) {
            updateStage(Stage.HelpScreen);
            return true;
        }

        return super.onKeyDown(keyCode, event);
    
protected voidonSaveInstanceState(android.os.Bundle outState)

        super.onSaveInstanceState(outState);

        outState.putInt(KEY_UI_STAGE, mUiStage.ordinal());
        if (mChosenPattern != null) {
            outState.putString(KEY_PATTERN_CHOICE, LockPatternUtils.patternToString(mChosenPattern));
        }
    
private voidpostClearPatternRunnable()

        mLockPatternView.removeCallbacks(mClearPatternRunnable);
        mLockPatternView.postDelayed(mClearPatternRunnable, WRONG_PATTERN_CLEAR_TIMEOUT_MS);
    
private voidsaveChosenPatternAndFinish()

        final boolean lockVirgin = !mLockPatternUtils.isPatternEverChosen();

        mLockPatternUtils.saveLockPattern(mChosenPattern);
        mLockPatternUtils.setLockPatternEnabled(true);

        if (lockVirgin) {
            mLockPatternUtils.setVisiblePatternEnabled(true);
            mLockPatternUtils.setTactileFeedbackEnabled(false);
        }
        
        setResult(RESULT_FINISHED);
        finish();
    
protected voidsetupViews()
Keep all "find view" related stuff confined to this function since in case someone needs to subclass and customize.

        setContentView(R.layout.choose_lock_pattern);
        
        mHeaderText = (TextView) findViewById(R.id.headerText);

        mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
        mLockPatternView.setOnPatternListener(mChooseNewLockPatternListener);
        mLockPatternView.setTactileFeedbackEnabled(mLockPatternUtils.isTactileFeedbackEnabled());        

        mFooterText = (TextView) findViewById(R.id.footerText);

        mFooterLeftButton = (TextView) findViewById(R.id.footerLeftButton);
        mFooterRightButton = (TextView) findViewById(R.id.footerRightButton);

        mFooterLeftButton.setOnClickListener(this);
        mFooterRightButton.setOnClickListener(this);
    
protected voidupdateStage(com.android.settings.ChooseLockPattern$Stage stage)
Updates the messages and buttons appropriate to what stage the user is at in choosing a view. This doesn't handle clearing out the pattern; the pattern is expected to be in the right state.

param
stage


        mUiStage = stage;

        // header text, footer text, visibility and 
        // enabled state all known from the stage
        if (stage == Stage.ChoiceTooShort) {
            mHeaderText.setText(
                    getResources().getString(
                            stage.headerMessage,
                            LockPatternUtils.MIN_LOCK_PATTERN_SIZE));
        } else {
            mHeaderText.setText(stage.headerMessage);
        }
        if (stage.footerMessage == ID_EMPTY_MESSAGE) {
            mFooterText.setText("");
        } else {
            mFooterText.setText(stage.footerMessage);
        }

        if (stage.leftMode == LeftButtonMode.Gone) {
            mFooterLeftButton.setVisibility(View.GONE);
        } else {
            mFooterLeftButton.setVisibility(View.VISIBLE);
            mFooterLeftButton.setText(stage.leftMode.text);
            mFooterLeftButton.setEnabled(stage.leftMode.enabled);
        }

        mFooterRightButton.setText(stage.rightMode.text);
        mFooterRightButton.setEnabled(stage.rightMode.enabled);

        // same for whether the patten is enabled
        if (stage.patternEnabled) {
            mLockPatternView.enableInput();
        } else {
            mLockPatternView.disableInput();
        }

        // the rest of the stuff varies enough that it is easier just to handle
        // on a case by case basis.
        mLockPatternView.setDisplayMode(DisplayMode.Correct);

        switch (mUiStage) {
            case Introduction:
                mLockPatternView.clearPattern();
                break;
            case HelpScreen:
                mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
                break;
            case ChoiceTooShort:
                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
                postClearPatternRunnable();
                break;
            case FirstChoiceValid:
                break;
            case NeedToConfirm:
                mLockPatternView.clearPattern();
                break;
            case ConfirmWrong:
                mLockPatternView.setDisplayMode(DisplayMode.Wrong);
                postClearPatternRunnable();
                break;
            case ChoiceConfirmed:
                break;
        }