失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > AndroidICS4.0----LockScreen锁屏流程【Android源码解析九】

AndroidICS4.0----LockScreen锁屏流程【Android源码解析九】

时间:2020-04-12 21:17:37

相关推荐

AndroidICS4.0----LockScreen锁屏流程【Android源码解析九】

先来说说LockScreen分类;

一、无锁屏;

二、锁屏:

1、UnLockScreen:

图案锁、 PIN锁, 密码锁;

2、LockScreen:

波纹锁;

转载请表明出处:/wdaming1986/article/details/7753206

有图有真相------>

接着我们来看看LockScreen的时序图:

综上所述:

1、createUnlockScreenFor()方法创建的是UnLockScreen界面,代码如下:

View createUnlockScreenFor(UnlockMode unlockMode) {View unlockView = null;if (DEBUG) Log.d(TAG,"createUnlockScreenFor(" + unlockMode + "): mEnableFallback=" + mEnableFallback);if (unlockMode == UnlockMode.Pattern) {PatternUnlockScreen view = new PatternUnlockScreen(mContext,mConfiguration,mLockPatternUtils,mUpdateMonitor,mKeyguardScreenCallback,mUpdateMonitor.getFailedAttempts());view.setEnableFallback(mEnableFallback);unlockView = view;} else if (unlockMode == UnlockMode.SimPuk) {unlockView = new SimPukUnlockScreen(mContext,mConfiguration,mUpdateMonitor,mKeyguardScreenCallback,mLockPatternUtils, MSimTelephonyManager.getDefault().getDefaultSubscription());} else if (unlockMode == UnlockMode.SimPin) {unlockView = new SimUnlockScreen(mContext,mConfiguration,mUpdateMonitor,mKeyguardScreenCallback,mLockPatternUtils);} else if (unlockMode == UnlockMode.Account) {try {unlockView = new AccountUnlockScreen(mContext,mConfiguration,mUpdateMonitor,mKeyguardScreenCallback,mLockPatternUtils);} catch (IllegalStateException e) {Log.i(TAG, "Couldn't instantiate AccountUnlockScreen"+ " (IAccountsService isn't available)");// TODO: Need a more general way to provide a// platform-specific fallback UI here.// For now, if we can't display the account login// unlock UI, just bring back the regular "Pattern" unlock mode.// (We do this by simply returning a regular UnlockScreen// here. This means that the user will still see the// regular pattern unlock UI, regardless of the value of// mUnlockScreenMode or whether or not we're in the// "permanently locked" state.)return createUnlockScreenFor(UnlockMode.Pattern);}} else if (unlockMode == UnlockMode.Password) {unlockView = new PasswordUnlockScreen(mContext,mConfiguration,mLockPatternUtils,mUpdateMonitor,mKeyguardScreenCallback);} else {throw new IllegalArgumentException("unknown unlock mode " + unlockMode);}initializeTransportControlView(unlockView);initializeFaceLockAreaView(unlockView); // Only shows view if FaceLock is enabledmUnlockScreenMode = unlockMode;return unlockView;}

2、createLockScreen()就是创建LockScreen界面:

View createLockScreen() {/*View lockView = new LockScreen(mContext,mConfiguration,mLockPatternUtils,mUpdateMonitor,mKeyguardScreenCallback);initializeTransportControlView(lockView);return lockView;*/long lockscreenType = 0;try{lockscreenType = android.provider.Settings.Secure.getLong(mContext.getContentResolver(), "lockscreen.disabled");}catch(Exception e){e.printStackTrace();}View lockView = null;lockView = new LockScreen(mContext,mConfiguration,mLockPatternUtils,mUpdateMonitor,mKeyguardScreenCallback); initializeTransportControlView(lockView);return lockView;}

我们来看看锁屏界面的流程:

step 1:创建LockScreen.java类——>先看看构造函数:

LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,KeyguardUpdateMonitor updateMonitor,KeyguardScreenCallback callback) {super(context);mLockPatternUtils = lockPatternUtils;mUpdateMonitor = updateMonitor;mCallback = callback;mEnableMenuKeyInLockScreen = shouldEnableMenuKey();mCreationOrientation = configuration.orientation;mKeyboardHidden = configuration.hardKeyboardHidden;if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());Log.v(TAG, "Cur orient=" + mCreationOrientation+ " res orient=" + context.getResources().getConfiguration().orientation);}final LayoutInflater inflater = LayoutInflater.from(context);if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);} else {inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);}if (TelephonyManager.getDefault().isMultiSimEnabled()) {mStatusViewManager = new MSimKeyguardStatusViewManager(this, mUpdateMonitor,mLockPatternUtils, mCallback, false);} else {mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor,mLockPatternUtils, mCallback, false);}setFocusable(true);setFocusableInTouchMode(true);setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);// modify by wangxianming in -06-22if (mAudioManager != null) {mSilentMode = isSilentMode();}mUnlockWidget = findViewById(R.id.unlock_widget);if (mUnlockWidget instanceof SlidingTab) {SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;slidingTabView.setHoldAfterTrigger(true, false);slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);slidingTabView.setLeftTabResources(R.drawable.ic_jog_dial_unlock,R.drawable.jog_tab_target_green,R.drawable.jog_tab_bar_left_unlock,R.drawable.jog_tab_left_unlock);SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);slidingTabView.setOnTriggerListener(slidingTabMethods);mUnlockWidgetMethods = slidingTabMethods;} else if (mUnlockWidget instanceof WaveView) {WaveView waveView = (WaveView) mUnlockWidget;WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);waveView.setOnTriggerListener(waveViewMethods);mUnlockWidgetMethods = waveViewMethods;} else if (mUnlockWidget instanceof MultiWaveView) {MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);multiWaveView.setOnTriggerListener(multiWaveViewMethods);mUnlockWidgetMethods = multiWaveViewMethods;} else {throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);}// Update widget with initial ring statemUnlockWidgetMethods.updateResources();if (DBG) Log.v(TAG, "*** LockScreen accel is "+ (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));}

Step 2:在Step 1步骤中根据横竖屏来加载横竖屏的布局:

if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);} else {inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);}

Step 3:来看看竖屏的布局文件的代码:

<GridLayoutxmlns:android="/apk/res/android"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"><!-- 锁屏界面加载数字时钟 --><com.android.internal.widget.DigitalClock android:id="@+id/time"android:layout_marginTop="@dimen/keyguard_lockscreen_status_line_clockfont_top_margin"android:layout_marginBottom="12dip"android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"android:layout_gravity="right"><!-- Because we can't have multi-tone fonts, we render two TextViews, one ontop of the other. Hence the redundant layout... --><TextView android:id="@+id/timeDisplayBackground"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:ellipsize="none"android:textSize="@dimen/keyguard_lockscreen_clock_font_size"android:textAppearance="?android:attr/textAppearanceMedium"android:layout_marginBottom="6dip"android:textColor="@color/lockscreen_clock_background"/><TextView android:id="@+id/timeDisplayForeground"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:ellipsize="none"android:textSize="@dimen/keyguard_lockscreen_clock_font_size"android:textAppearance="?android:attr/textAppearanceMedium"android:layout_marginBottom="6dip"android:textColor="@color/lockscreen_clock_foreground"android:layout_alignLeft="@id/timeDisplayBackground"android:layout_alignTop="@id/timeDisplayBackground"/></com.android.internal.widget.DigitalClock><LinearLayoutandroid:orientation="horizontal"android:layout_gravity="right"android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"><!-- 锁屏界面加载日期 --><TextViewandroid:id="@+id/date"android:layout_width="wrap_content"android:layout_height="wrap_content"android:singleLine="true"android:ellipsize="marquee"android:textAppearance="?android:attr/textAppearanceMedium"android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"/><!-- 锁屏界面加载闹钟状态 --><TextViewandroid:id="@+id/alarm_status"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginLeft="16dip"android:singleLine="true"android:ellipsize="marquee"android:textAppearance="?android:attr/textAppearanceMedium"android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"android:drawablePadding="4dip"/></LinearLayout><!-- 锁屏界面加载充电状态 --><TextViewandroid:id="@+id/status1"android:layout_gravity="right"android:layout_marginRight="@dimen/keyguard_lockscreen_status_line_font_right_margin"android:singleLine="true"android:ellipsize="marquee"android:textAppearance="?android:attr/textAppearanceMedium"android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"android:drawablePadding="4dip"/><Space android:layout_gravity="fill" /><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="302dip"><!-- 锁屏界面加载波纹的锁屏 --><com.android.internal.widget.multiwaveview.MultiWaveViewandroid:id="@+id/unlock_widget"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentBottom="true"android:targetDrawables="@array/lockscreen_targets_with_camera"android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"android:directionDescriptions="@array/lockscreen_direction_descriptions"android:handleDrawable="@drawable/ic_lockscreen_handle"android:waveDrawable="@drawable/ic_lockscreen_outerring"android:outerRadius="@dimen/multiwaveview_target_placement_radius"android:snapMargin="@dimen/multiwaveview_snap_margin"android:hitRadius="@dimen/multiwaveview_hit_radius"android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"android:horizontalOffset="0dip"android:verticalOffset="60dip"android:feedbackCount="3"android:vibrationDuration="20"/><!-- 锁屏界面加载运营商状态 --><TextViewandroid:id="@+id/carrier"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_marginBottom="12dip"android:gravity="center_horizontal"android:singleLine="true"android:ellipsize="marquee"android:textAppearance="?android:attr/textAppearanceMedium"android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"android:textColor="?android:attr/textColorSecondary"/></RelativeLayout><LinearLayoutandroid:orientation="horizontal"android:layout_width="match_parent"style="?android:attr/buttonBarStyle"android:gravity="center"android:weightSum="2"><!-- 锁屏界面加载紧急拨号按钮 --><Button android:id="@+id/emergencyCallButton"android:layout_gravity="center_horizontal"android:layout_width="0dip"android:layout_height="wrap_content"android:layout_weight="1"style="?android:attr/buttonBarButtonStyle"android:textSize="@dimen/keyguard_lockscreen_status_line_font_size"android:text="@*android:string/lockscreen_emergency_call"android:drawableLeft="@*android:drawable/lockscreen_emergency_button"android:drawablePadding="0dip"android:visibility="gone"/></LinearLayout></GridLayout>

Step 4:在Step 3中重点看com.android.internal.widget.multiwaveview.MultiWaveView这个自定义的view,这个view是处理ICS4.0锁屏的拖拽的功能,具体代码如下:

public MultiWaveView(Context context, AttributeSet attrs) {super(context, attrs);Resources res = context.getResources();。。。 。。。加载资源。。。 。。。}

通过onMeasure()来计算自定义view的大小:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {final int minimumWidth = getSuggestedMinimumWidth();final int minimumHeight = getSuggestedMinimumHeight();int viewWidth = resolveMeasured(widthMeasureSpec, minimumWidth);int viewHeight = resolveMeasured(heightMeasureSpec, minimumHeight);setMeasuredDimension(viewWidth, viewHeight);}

通过onLayout()来加载布局:

protected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);final int width = right - left;final int height = bottom - top;float newWaveCenterX = mHorizontalOffset + Math.max(width, mOuterRing.getWidth() ) / 2;float newWaveCenterY = mVerticalOffset + Math.max(height, mOuterRing.getHeight()) / 2;if (newWaveCenterX != mWaveCenterX || newWaveCenterY != mWaveCenterY) {if (mWaveCenterX == 0 && mWaveCenterY == 0) {performInitialLayout(newWaveCenterX, newWaveCenterY);}mWaveCenterX = newWaveCenterX;mWaveCenterY = newWaveCenterY;mOuterRing.setX(mWaveCenterX);mOuterRing.setY(Math.max(mWaveCenterY, mWaveCenterY));updateTargetPositions();}if (DEBUG) dump();}

Step 5:来看看触摸屏幕时的事件处理onTouchEvent()代码如下:

@Overridepublic boolean onTouchEvent(MotionEvent event) {final int action = event.getAction();boolean handled = false;switch (action) {case MotionEvent.ACTION_DOWN:handleDown(event);handled = true;break;case MotionEvent.ACTION_MOVE:handleMove(event);handled = true;break;case MotionEvent.ACTION_UP:handleMove(event);handleUp(event);handled = true;break;case MotionEvent.ACTION_CANCEL:handleMove(event);handled = true;break;}invalidate();return handled ? true : super.onTouchEvent(event);}

通过handleMove()来处理移动事件:

private void handleMove(MotionEvent event) {if (!mDragging) {trySwitchToFirstTouchState(event);return;}int activeTarget = -1;final int historySize = event.getHistorySize();for (int k = 0; k < historySize + 1; k++) {float x = k < historySize ? event.getHistoricalX(k) : event.getX();float y = k < historySize ? event.getHistoricalY(k) : event.getY();float tx = x - mWaveCenterX;float ty = y - mWaveCenterY;float touchRadius = (float) Math.sqrt(dist2(tx, ty));final float scale = touchRadius > mOuterRadius ? mOuterRadius / touchRadius : 1.0f;float limitX = mWaveCenterX + tx * scale;float limitY = mWaveCenterY + ty * scale;boolean singleTarget = mTargetDrawables.size() == 1;if (singleTarget) {// Snap to outer ring if there's only one targetfloat snapRadius = mOuterRadius - mSnapMargin;if (touchRadius > snapRadius) {activeTarget = 0;x = limitX;y = limitY;}} else {// If there's more than one target, snap to the closest one less than hitRadius away.float best = Float.MAX_VALUE;final float hitRadius2 = mHitRadius * mHitRadius;for (int i = 0; i < mTargetDrawables.size(); i++) {// Snap to the first target in rangeTargetDrawable target = mTargetDrawables.get(i);float dx = limitX - target.getX();float dy = limitY - target.getY();float dist2 = dx*dx + dy*dy;if (target.isValid() && dist2 < hitRadius2 && dist2 < best) {activeTarget = i;best = dist2;}}x = limitX;y = limitY;}if (activeTarget != -1) {switchToState(STATE_SNAP, x,y);float newX = singleTarget ? limitX : mTargetDrawables.get(activeTarget).getX();float newY = singleTarget ? limitY : mTargetDrawables.get(activeTarget).getY();moveHandleTo(newX, newY, false);TargetDrawable currentTarget = mTargetDrawables.get(activeTarget);if (currentTarget.hasState(TargetDrawable.STATE_FOCUSED)) {currentTarget.setState(TargetDrawable.STATE_FOCUSED);mHandleDrawable.setAlpha(0.0f);}} else {switchToState(STATE_TRACKING, x, y);moveHandleTo(x, y, false);mHandleDrawable.setAlpha(1.0f);}}// Draw handle outside parent's boundsinvalidateGlobalRegion(mHandleDrawable);if (mActiveTarget != activeTarget && activeTarget != -1) {dispatchGrabbedEvent(activeTarget);if (AccessibilityManager.getInstance(mContext).isEnabled()) {String targetContentDescription = getTargetDescription(activeTarget);announceText(targetContentDescription);}}mActiveTarget = activeTarget;}

以上主要工作是绘制拖拽的参数以及绘制出来。通过invalidate()来主动刷屏幕;

在onDraw()方法中实现绘制图形,代码如下:

@Overrideprotected void onDraw(Canvas canvas) {mOuterRing.draw(canvas);for (TargetDrawable target : mTargetDrawables) {if (target != null) {target.draw(canvas);}}for (TargetDrawable target : mChevronDrawables) {if (target != null) {target.draw(canvas);}}mHandleDrawable.draw(canvas);}

在handleMove()方法中——>trySwitchToFirstTouchState(event);——>switchToState()——>doFinish();

——>setGrabbedState() ————>mOnTriggerListener.onGrabbedStateChange(this, mGrabbedState);

设置回调。

Step 6:LockScreen.java中有个内部类,监听这个移动事件的状态,——> 代码如下:

class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,UnlockWidgetCommonMethods {private final MultiWaveView mMultiWaveView;private boolean mCameraDisabled;MultiWaveViewMethods(MultiWaveView multiWaveView) {mMultiWaveView = multiWaveView;final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager().getCameraDisabled(null);if (cameraDisabled) {Log.v(TAG, "Camera disabled by Device Policy");mCameraDisabled = true;} else {// Camera is enabled if resource is initially defined for MultiWaveView// in the lockscreen layout filemCameraDisabled = mMultiWaveView.getTargetResourceId()!= R.array.lockscreen_targets_with_camera;}}public void updateResources() {int resId;if (mCameraDisabled) {// Fall back to showing ring/silence if camera is disabled by DPM...resId = mSilentMode ? R.array.lockscreen_targets_when_silent: R.array.lockscreen_targets_when_soundon;} else {resId = R.array.lockscreen_targets_with_camera;}mMultiWaveView.setTargetResources(resId);}public void onGrabbed(View v, int handle) {}public void onReleased(View v, int handle) {}public void onTrigger(View v, int target) {if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscapemCallback.goToUnlockScreen();} else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscapeif (!mCameraDisabled) {// Start the CameraIntent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);mContext.startActivity(intent);mCallback.goToUnlockScreen();} else {toggleRingMode();mUnlockWidgetMethods.updateResources();mCallback.pokeWakelock();}}}public void onGrabbedStateChange(View v, int handle) {// Don't poke the wake lock when returning to a state where the handle is// not grabbed since that can happen when the system (instead of the user)// cancels the grab.if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {mCallback.pokeWakelock();}}public View getView() {return mMultiWaveView;}public void reset(boolean animate) {mMultiWaveView.reset(animate);}public void ping() {mMultiWaveView.ping();}}

重点看public void onTrigger()这个方法,用于处理拖拽启动那个activity,一个启动camera,一个正常解锁。

锁屏的大概这个流程就是这个样子了,大家应该会一目了然了。由于时间仓促,难免有点纰漏,希望大家指正错误,如有不解的地方,欢迎留言探讨!!!

如果觉得《AndroidICS4.0----LockScreen锁屏流程【Android源码解析九】》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。