首先还是从ChooseLockGenericFragment开始分析,由上一篇链接 我们知道当第一次选择密码时,会执行helper.launchConfirmationActivity(CONFIRM_EXISTING_REQUEST,getString(R.string.unlock_set_unlock_launch_picker_title), true, mUserId)方法并返回false,从而执行updatePreferencesOrFinish(savedInstanceState != null);这个方法,我们来看下此方法,代码如下:
private void updatePreferencesOrFinish(boolean isRecreatingActivity) {
Intent intent = getActivity().getIntent();
int quality = intent.getIntExtra(LockPatternUtils.PASSWORD_TYPE_KEY, -1);
Log.d("faceid", "quality = " + quality+ " :isRecreatingActivity: "+isRecreatingActivity);
//由于没有设置过密码,此时quality为-1
if (quality == -1) {
// If caller didn't specify password quality, show UI and allow the user to choose.
quality = intent.getIntExtra(MINIMUM_QUALITY_KEY, -1);
quality = mController.upgradeQuality(quality);//quality:0
final boolean hideDisabledPrefs = intent.getBooleanExtra(
HIDE_DISABLED_PREFS, false);//hideDisabledPrefs false
final PreferenceScreen prefScreen = getPreferenceScreen();
if (prefScreen != null) {
prefScreen.removeAll();
}
addPreferences();//添加布局
removePreferencesForFaceid();
disableUnusablePreferences(quality, hideDisabledPrefs); //如果此时是人脸跳到此页面时hideDisabledPrefs为true,会disable 无和滑动两种锁屏方式
updatePreferenceText();//更新每个解锁方式的文字
updateCurrentPreference();//更新当前选中的解锁方式的文字状态
updatePreferenceSummaryIfNeeded();
} else if (!isRecreatingActivity) { //todo 为什么不走这里
// Don't start the activity again if we are recreated for configuration change
updateUnlockMethodAndFinish(quality, false, true /* chooseLockSkipped */);
}
}
当选择解锁方式时,点击任意一种都会执行onPreferenceTreeClick方法,我们来看下,如果我们选择patten,会执行甚麽,代码如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/password/ChooseLockGeneric.java/ChooseLockGenericFragment
@Override
public boolean onPreferenceTreeClick(Preference preference) {
final String key = preference.getKey();//此时key为:unlock_set_pattern
//isUnlockMethodSecure会判断key是否为none或者swipe,此时key为pattern,返回false
if (!isUnlockMethodSecure(key) && mLockPatternUtils.isSecure(mUserId)) {
......
} else if (KEY_SKIP_FINGERPRINT.equals(key)) {
......
} else {
//此时会执行setUnlockMethod(unlock_set_pattern)方法
return setUnlockMethod(key);
}
}
接着来看setUnlockMethod方法,代码如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/password/ChooseLockGeneric.java/ChooseLockGenericFragment
private boolean setUnlockMethod(String unlockMethod) {
EventLog.writeEvent(EventLogTags.LOCK_SCREEN_TYPE, unlockMethod);
//此时的unlockMethod为unlock_set_pattern,所以lock为PATTERN
ScreenLockType lock = ScreenLockType.fromKey(unlockMethod);
if (lock != null) {
switch (lock) {
case NONE:
case SWIPE:
......
return true;
case PATTERN:
case PIN:
case PASSWORD:
case MANAGED:
//所以会执行此方法
maybeEnableEncryption(lock.defaultQuality, false);
return true;
}
}
return false;
}
接着我们来看下maybeEnableEncryption(lock.defaultQuality, false);方法,方法如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/password/ChooseLockGeneric.java/ChooseLockGenericFragment
private void maybeEnableEncryption(int quality, boolean disabled) {
DevicePolicyManager dpm = (DevicePolicyManager) getSystemService(DEVICE_POLICY_SERVICE);
if (UserManager.get(getActivity()).isAdminUser()
&& mUserId == UserHandle.myUserId()
&& LockPatternUtils.isDeviceEncryptionEnabled()
&& !LockPatternUtils.isFileEncryptionEnabled()
&& !dpm.getDoNotAskCredentialsOnBoot()) {
//此时的quality为65535为图案
mEncryptionRequestQuality = quality;
//mEncryptionRequestDisabled为false
mEncryptionRequestDisabled = disabled;
//此时获取到的intent为ChooseLockPattern.java
Intent unlockMethodIntent = getIntentForUnlockMethod(quality);
//mForChangeCredRequiredForBoot为false
unlockMethodIntent.putExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_CHANGE_CRED_REQUIRED_FOR_BOOT,
mForChangeCredRequiredForBoot);
final Context context = getActivity();
// If accessibility is enabled and the user hasn't seen this dialog before, set the
// default state to agree with that which is compatible with accessibility
// (password not required).
final boolean accEn = AccessibilityManager.getInstance(context).isEnabled();
final boolean required = mLockPatternUtils.isCredentialRequiredToDecrypt(!accEn);
//此方法新建里个Intent,值为EncryptionInterstitial.class,并将unlockMethodIntent
//作为参数放到此intent中。
Intent intent = getEncryptionInterstitialIntent(context, quality, required,
unlockMethodIntent);
//mForFingerprint为:false
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT,
mForFingerprint);
//mHideDrawer为:false
intent.putExtra(EXTRA_HIDE_DRAWER, mHideDrawer);
startActivityForResult(
intent,
mIsSetNewPassword && mHasChallenge
? CHOOSE_LOCK_BEFORE_FINGERPRINT_REQUEST
: ENABLE_ENCRYPTION_REQUEST);
} else {
......
}
}
此时执行startActivityForResult跳转到EncryptionInterstitial.java,页面截图如下:
接着上面来看,由于EncryptionInterstitial继承SettingsActivity,所以打印log如下:
所以下面我们来看看EncryptionInterstitialFragment,代码如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/EncryptionInterstitial.java/EncryptionInterstitialFragment
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
/* M: fragment lifecycle should be same as Activity lifecycle */
Log.d(TAG, "EncryptionInterstitialFragment onViewCreated, isActivityFinishing: "
+ (getActivity().isFinishing()) + "isActivity Destroyed: "
+ (getActivity().isDestroyed()) + "Monkey user :" + Utils.isMonkeyRunning());
......
//右下方的是按钮,点击后会跳转到设置解锁图案页面
mRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_require_password);
//左下方的否按钮,点击会返回
mDontRequirePasswordToDecrypt = view.findViewById(R.id.encrypt_dont_require_password);
//获取intent里的参数,由前面可知为false
boolean forFingerprint = getActivity().getIntent().getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_FOR_FINGERPRINT, false);
Intent intent = getActivity().getIntent();
//65536,为图案
mRequestedPasswordQuality = intent.getIntExtra(EXTRA_PASSWORD_QUALITY, 0);
//此mUnlockMethodIntent为ChooseLockPattern.java
mUnlockMethodIntent = intent.getParcelableExtra(EXTRA_UNLOCK_METHOD_INTENT);
final int msgId;
switch (mRequestedPasswordQuality) {
case DevicePolicyManager.PASSWORD_QUALITY_SOMETHING:
//此时forFingerprint为false,所以msgId为:R.string.encryption_interstitial_message_pattern;
//即:"为了进一步保护此设备的安全,您可以将设备设为需要绘制解锁图案才能启动。在设备启动之前,
//无法接听电话、接收消息或通知(包括闹钟)。\n\n这样一来,即使设备丢失或被盗,
//其中的数据仍安全无虞。要将设备设为需要绘制解锁图案才能启动吗?"
msgId = forFingerprint ?
R.string.encryption_interstitial_message_pattern_for_fingerprint :
R.string.encryption_interstitial_message_pattern;
break;
......
}
TextView message = (TextView) getActivity().findViewById(R.id.encryption_message);
//为TextView 设置值
message.setText(msgId);
//为这两个按钮设置点击事件
mRequirePasswordToDecrypt.setOnClickListener(this);
mDontRequirePasswordToDecrypt.setOnClickListener(this);
......
}
接着我们看下这两个按钮的点击事件,方法如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/EncryptionInterstitial.java/EncryptionInterstitialFragment
@Override
public void onClick(View view) {
//点击右下角 是 按钮
if (view == mRequirePasswordToDecrypt) {
//log显示accEn为false
final boolean accEn = AccessibilityManager.getInstance(getActivity()).isEnabled();
if (accEn && !mPasswordRequired) {
......
} else {
//此时会执行到这里
//setRequirePasswordState方法就是将参数true赋值给mPasswordRequired
//此时mPasswordRequired = true
setRequirePasswordState(true);
startLockIntent();
}
} else {
setRequirePasswordState(false);
startLockIntent();
}
}
接着我们看下startLockIntent();方法,方法如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/
//com/android/settings/EncryptionInterstitial.java/EncryptionInterstitialFragment
protected void startLockIntent() {
//此时的mUnlockMethodIntent即为上面intent获取的参数
//此时mUnlockMethodIntent值为ChooseLockPattern.java
if (mUnlockMethodIntent != null) {
//mPasswordRequired为true
mUnlockMethodIntent.putExtra(EXTRA_REQUIRE_PASSWORD, mPasswordRequired);
//CHOOSE_LOCK_REQUEST 为100
startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);
} else {
Log.wtf(TAG, "no unlock intent to start");
finish();
}
}
此时将执行startActivityForResult(mUnlockMethodIntent, CHOOSE_LOCK_REQUEST);跳转到ChooseLockPattern.java进行图案密码的输入,页面截图如下:
我们首先看下onViewCreated生命周期,代码如下:
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//控件的一些初始化
......
//绘制图案密码的监听
mLockPatternView.setOnPatternListener(制图案密码的监听);
//为左下方和右下方按钮设置点击事件的监听
mFooterLeftButton.setOnClickListener(this);
mFooterRightButton.setOnClickListener(this);
//confirmCredentials为:false
final boolean confirmCredentials = getActivity().getIntent()
.getBooleanExtra(ChooseLockGeneric.CONFIRM_CREDENTIALS, true);
Intent intent = getActivity().getIntent();
//mCurrentPattern为:null
mCurrentPattern = intent.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);//null
//mHasChallenge为:false
mHasChallenge = intent.getBooleanExtra(
ChooseLockSettingsHelper.EXTRA_KEY_HAS_CHALLENGE, false);
//mChallenge为:false
mChallenge = intent.getLongExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE, 0);
//由于第一次进入,此时savedInstanceState为null
if (savedInstanceState == null) {
//confirmCredentials此时为false
if (confirmCredentials) {
......
} else {
//此时会执行updateStage
updateStage(Stage.Introduction);
}
} else {
......
}
}
首先我们看下stage是什么,其实stage 表示当用户选择一个patten时,用户此时的状态。
由下面可知,stage是一个枚举,分别有Introduction、NeedToConfirm、ChoiceConfirmed、FirstChoiceValid等几种状态,每种状态里面的参数如下所示,其实就是绘制密码界面所需要的一些控件的值。
接着我们来看下updateStage(Stage.Introduction);方法,看下第一次绘制时会执行什么,截图如下:
方法如下:
protected void updateStage(Stage stage) {
//第一次进入时stage为:Stage.Introduction
//定义一个变量保存之前的state
final Stage previousStage = mUiStage;
//当前的状态
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 {
//此时Introduction.headerMessage为:"绘制解锁图案"
mHeaderText.setText(stage.headerMessage);
}
//由上面可知,此时的mForFingerprint为false
int message = mForFingerprint ? stage.messageForFingerprint : stage.message;
//此时message为:"为了安全起见,请设置解锁图案",ID_EMPTY_MESSAGE = -1
if (message == ID_EMPTY_MESSAGE) {
mMessageText.setText("");
} else {
//所以会执行这里,赋值给mMessageText
mMessageText.setText(message);
}
//Introduction.footerMessage为ID_EMPTY_MESSAGE,即-1
if (stage.footerMessage == ID_EMPTY_MESSAGE) {
//执行这里,设置为空字符
mFooterText.setText("");
} else {
mFooterText.setText(stage.footerMessage);
}
if (stage == Stage.ConfirmWrong || stage == Stage.ChoiceTooShort) {
TypedValue typedValue = new TypedValue();
Theme theme = getActivity().getTheme();
theme.resolveAttribute(R.attr.colorError, typedValue, true);
mHeaderText.setTextColor(typedValue.data);
} else {
//为mHeaderText设置字体颜色
if (mDefaultHeaderColorList != null) {
mHeaderText.setTextColor(mDefaultHeaderColorList);
}
if (stage == Stage.NeedToConfirm && mForFingerprint) {
mHeaderText.setText("");
mTitleText.setText(R.string.lockpassword_draw_your_pattern_again_header);
}
}
//更新左下方按钮的状态
updateFooterLeftButton(stage, mFooterLeftButton);
//设置右下方按钮的文字
setRightButtonText(stage.rightMode.text);
//设置右下方按钮的是否可用,即是否可点击
setRightButtonEnabled(stage.rightMode.enabled);
// Introduction.patternEnabled为true
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);
boolean announceAlways = false;
switch (mUiStage) {
case Introduction:
//mUiStage为Introduction,执行这里,进行一个清除Pattern的动作,
mLockPatternView.clearPattern();
break;
case HelpScreen:
mLockPatternView.setPattern(DisplayMode.Animate, mAnimatePattern);
break;
case ChoiceTooShort:
mLockPatternView.setDisplayMode(DisplayMode.Wrong);
postClearPatternRunnable();
announceAlways = true;
break;
case FirstChoiceValid:
break;
case NeedToConfirm:
mLockPatternView.clearPattern();
break;
case ConfirmWrong:
mLockPatternView.setDisplayMode(DisplayMode.Wrong);
postClearPatternRunnable();
announceAlways = true;
break;
case ChoiceConfirmed:
break;
}
//当状态改变时,设置mHeaderText状态可以改变
if (previousStage != stage || announceAlways) {
mHeaderText.announceForAccessibility(mHeaderText.getText());
}
}
接着我们看下onResume方法,当用户交互时会调用此方法,方法如下:
@Override
public void onResume() {
super.onResume();
updateStage(mUiStage);
//一个后台fragment,用来跟踪保存和校验用户选择的密码(pattern/pin/password).
if (mSaveAndFinishWorker != null) {
setRightButtonEnabled(false);
//设置监听器,当两次密码输入完成保存成功后,激活监听器跳转到通知页面
mSaveAndFinishWorker.setListener(this);
}
}
可以看到,当用户进行交互,即绘制图案时,会不断的调用updateStage(mUiStage);来更新界面状态。且第一次进入时即mUiStage为Introduction时,会进行一个pattern的初始化动作,清除图案保证没有绘制过。
接下来我们看下绘制图案密码的监听mLockPatternView.setOnPatternListener
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() {
//开始绘制图案时调用
public void onPatternStart() {
mLockPatternView.removeCallbacks(mClearPatternRunnable);
patternInProgress();
}
//清除图案时调用
public void onPatternCleared() {
//mClearPatternRunnable为一个Runnable,调用了mLockPatternView.clearPattern();
mLockPatternView.removeCallbacks(mClearPatternRunnable);
}
//图案绘制完成时调用
public void onPatternDetected(List pattern) {
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
if (mChosenPattern == null) throw new IllegalStateException(
"null chosen pattern in stage 'need to confirm");
if (mChosenPattern.equals(pattern)) {
updateStage(Stage.ChoiceConfirmed);
} else {
updateStage(Stage.ConfirmWrong);
}
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
//此处的pattern为一个二维数组,Cell[][],即代表的是一个3x3的矩阵
//public static final int MIN_LOCK_PATTERN_SIZE = 4;
if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
updateStage(Stage.ChoiceTooShort);
} else {
mChosenPattern = new ArrayList(pattern);
updateStage(Stage.FirstChoiceValid);
}
} else {
throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
+ "entering the pattern.");
}
}
public void onPatternCellAdded(List pattern) {
//空实现
}
//开始绘制时由onPatternStart调用 ,主要作用为页面一些文字属性更新
private void patternInProgress() {
mHeaderText.setText(R.string.lockpattern_recording_inprogress);//"完成后松开手指"
if (mDefaultHeaderColorList != null) {
mHeaderText.setTextColor(mDefaultHeaderColorList);
}
mFooterText.setText("");
mFooterLeftButton.setEnabled(false);
mFooterRightButton.setEnabled(false);
if (mTitleHeaderScrollView != null) {
mTitleHeaderScrollView.post(new Runnable() {
@Override
public void run() {
mTitleHeaderScrollView.fullScroll(ScrollView.FOCUS_DOWN);
}
});
}
}
};
|
所以到这里便有了一个大概的思路,mChooseNewLockPatternListener监听用户行为,是否进行绘制图案,当开始绘制时,触发onPatternStart,onPatternStart又接着调用patternInProgress来更新UI,绘制过程中界面如下:
当绘制完成时,调用onPatternDetected,我们看下第一次绘制完成,此方法做了什么,方法如下:
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() {
......
//图案绘制完成时调用
public void onPatternDetected(List pattern) {
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
......
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
//第一次绘制时mUiStage为Introduction,所以会执行到这里
//当绘制完成时,pattern.size()为5
if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
updateStage(Stage.ChoiceTooShort);
} else {
//此时会执行到这里
mChosenPattern = new ArrayList(pattern);
updateStage(Stage.FirstChoiceValid);
}
} else {
throw new IllegalStateException("Unexpected stage " + mUiStage + " when "
+ "entering the pattern.");
}
}
......
};
接着调用updateStage(Stage.FirstChoiceValid);即上面的方法,可以看到,此时updateStage方法仅仅是做了一些更新UI的操作,比如设置buttun的状态和字体以及header的文字等,我们可以看下此时的页面,页面如下:
此时状态为Stage.FirstChoiceValid,当点击下一步时,执行onclick方法如下:
public void onClick(View v) {
if (v == mFooterLeftButton) {
handleLeftButton();
} else if (v == mFooterRightButton) {
handleRightButton();
}
}
handleRightButton();方法如下:
public void handleRightButton() {
//由于此时mUiStage为FirstChoiceValid,他的rightMode为Continue
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) {
......
} else if (mUiStage.rightMode == RightButtonMode.Ok) {
......
}
}
可以看到又执行updateStage(Stage.NeedToConfirm),在这个方法中便会调用mLockPatternView.clearPattern重置UI,让用户重新绘制。此时用户界面为:
当第二次绘制完成时,此时会再调用onPatternDetected,我们来看下此时的方法,方法如下:
public void onPatternDetected(List pattern) {
//由于上面调用了updateStage(Stage.NeedToConfirm),此方法里面会将mUiStage
//赋值为Stage.NeedToConfirm
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
if (mChosenPattern == null) throw new IllegalStateException(
"null chosen pattern in stage 'need to confirm");
//此时判断当前绘制的图案是否和上次绘制一样
if (mChosenPattern.equals(pattern)) {
//一样则会调用
updateStage(Stage.ChoiceConfirmed);
} else {
updateStage(Stage.ConfirmWrong);
}
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
......
} else {
......
}
}
可以看到会调用updateStage(Stage.ChoiceConfirmed);来更新UI,我们看下当两次绘制图案一样时,此时用户界面是什么,截图如下:
我们来看下当第一次绘制完密码时,调用onPatternDetected,我们看下此时代码:
public void onPatternDetected(List pattern) {
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
......
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
if (pattern.size() < LockPatternUtils.MIN_LOCK_PATTERN_SIZE) {
......
} else {
//新建一个ArrayList将绘制完成的pattern保存到此mChosenPattern
mChosenPattern = new ArrayList(pattern);
updateStage(Stage.FirstChoiceValid);
}
} else {
......
}
}
可以看到此时会新建一个ArrayList将第一次绘制完成的pattern保存到此mChosenPattern,用来做第二次绘制完成密码时的判断,即
protected LockPatternView.OnPatternListener mChooseNewLockPatternListener =
new LockPatternView.OnPatternListener() {
public void onPatternDetected(List pattern) {
if (mUiStage == Stage.NeedToConfirm || mUiStage == Stage.ConfirmWrong) {
if (mChosenPattern == null) throw new IllegalStateException(
"null chosen pattern in stage 'need to confirm");
if (mChosenPattern.equals(pattern)) {
updateStage(Stage.ChoiceConfirmed);
} else {
updateStage(Stage.ConfirmWrong);
}
} else if (mUiStage == Stage.Introduction || mUiStage == Stage.ChoiceTooShort){
......
} else {
......
}
}
};
可以看到调用mChosenPattern.equals(pattern)来进行判断两次绘制的是否一样。
接着来看,当绘制两次相同的密码后,我们点击确认按钮后,执行onclick方法,调用handleRightButton();方法如下:
public void handleRightButton() {
if (mUiStage.rightMode == RightButtonMode.Continue) {
.....
} else if (mUiStage.rightMode == RightButtonMode.Confirm) {
if (mUiStage != Stage.ChoiceConfirmed) {
throw new IllegalStateException("expected ui stage " + Stage.ChoiceConfirmed
+ " when button is " + RightButtonMode.Confirm);
}
startSaveAndFinish();
} else if (mUiStage.rightMode == RightButtonMode.Ok) {
......
}
}
可以看到此时调用startSaveAndFinish();来保存图案,方法如下:
// /vendor/mediatek/proprietary/package/apps/MTKSettings/src/com/android/
// /settings/password/ChooseLockPattern.java/ChooseLockPatternFragment
private void startSaveAndFinish() {
if (mSaveAndFinishWorker != null) {
Log.w(TAG, "startSaveAndFinish with an existing SaveAndFinishWorker.");
return;
}
setRightButtonEnabled(false);
mSaveAndFinishWorker = new SaveAndFinishWorker();
mSaveAndFinishWorker.setListener(this);
getFragmentManager().beginTransaction().add(mSaveAndFinishWorker,
FRAGMENT_TAG_SAVE_AND_FINISH).commit();
getFragmentManager().executePendingTransactions();
final boolean required = getActivity().getIntent().getBooleanExtra(
EncryptionInterstitial.EXTRA_REQUIRE_PASSWORD, true);
mSaveAndFinishWorker.start(mChooseLockSettingsHelper.utils(), required,
mHasChallenge, mChallenge, mChosenPattern, mCurrentPattern, mUserId);
}
首先为mSaveAndFinishWorker设置了一个监听器,接着调用mSaveAndFinishWorker.start开启一个AsyncTask异步线程,在子线程中调用saveAndVerifyInBackground()用来保存图案设置并返回一个intent,结束后触发监听器(mFinished = true;)然后调用startActivity(intent) 跳转到RedactionInterstitial.java,此时页面为如下截图: