锁屏(Keyguard)2
7, LockPatternKeyguardView类 (自定义ViewGroup)
功能:作为LockScreen和UnLockScreen界面的载体,控制显示哪个界面。
其源代码释义如下:
public class LockPatternKeyguardView extends KeyguardViewBase { ... private View mLockScreen; private View mUnlockScreen; private boolean mScreenOn = false;//是否亮屏 enum Mode { //当前显示界面的Mode Lock 或者UnLock } enum UnlockMode { ...//开锁界面的几种不同Mode } //构造函数 public LockPatternKeyguardView( ...) { //KeyguardScreenCallback的实现对象 mKeyguardScreenCallback = new KeyguardScreenCallback() { ... }; ... } public void reset() { ...//重置显示界面 } private void recreateLockScreen() { ...//重新构建LockScreen } private void recreateUnlockScreen() { ...//重新构建UnlockScreen } private void recreateScreens() { ...//重新构建该视图 } public void verifyUnlock() { ... } public void cleanUp() { ... //清理资源对象 } private boolean isSecure() { ...//手机设置是否处于安全状态 } private void updateScreen(final Mode mode) { ...//根据参数(Lock/unLock),判断显示为LockScreen或者UnlockScreen界面 } View createLockScreen() { ...//创建lockScreen } View createUnlockScreenFor(UnlockMode unlockMode) { ...//根据不同的Unlock Mode , 创建不同的UnlockScreen } private Mode getInitialMode() { ...//得到初始化的状态Mode (lock or unlock). } /** Given the current state of things, what should the unlock screen be? */ private UnlockMode getUnlockMode() { ...//返回开锁的状态Unlock Mode } private void showTimeoutDialog() { ... //输入密码超过一定次数时,提示30s后在登录的对话框 } private void showAlmostAtAccountLoginDialog() { ... //显示Google 账户登录对话框 } }
8、KeyguardViewBase类 抽象类 (自定义ViewGroup)
功能:为LockPatternKeyguardView提供了一组通用的方法 。需要值得注意的方法就是他对某些KeyEvent的监听,当他消费监听到这些KeyEvent,我们的App就监听不到这些KeyEvent了 。常用的有KEYEVENT_VOLUME_UP/DOWN等。
public abstract class KeyguardViewBase extends FrameLayout { ... @Override public boolean dispatchKeyEvent(KeyEvent event) { ... if (interceptMediaKey(event)) { return true; } return super.dispatchKeyEvent(event); } private boolean interceptMediaKey(KeyEvent event) { final int keyCode = event.getKeyCode(); if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (keyCode) { ...//more keyevent case KeyEvent.KEYCODE_VOLUME_UP: case KeyEvent.KEYCODE_VOLUME_DOWN: { ... // Don't execute default volume behavior return true; //直接返回不在向下传递处理 } } } return false; } }
9、 KeyguardViewProperties.java 接口
功能:提供了创建界面的通用方法。
public interface KeyguardViewProperties { //创建一个KeyguardViewBase实例 , 实际是指LockPatternKeyguardView实例 KeyguardViewBase createKeyguardView(Context context, KeyguardUpdateMonitor updateMonitor, KeyguardWindowController controller); boolean isSecure(); }
其唯一实现类是是LockPatternKeyguardViewProperties类(稍后讲到)。
10、LockPatternKeyguardViewProperties类
源代码释义如下:
public class LockPatternKeyguardViewProperties implements KeyguardViewProperties { ... //创建一个LockPatternKeyguardView对象 public KeyguardViewBase createKeyguardView(Context context,KeyguardUpdateMonitor updateMonitor,KeyguardWindowController controller) { return new LockPatternKeyguardView(context, updateMonitor, mLockPatternUtils, controller); }
//=============================================
// OK ,我知道你看的很纠结了,具体需要时参考源代码看是最明智的。
//=============================================
我知道代码贴的太多了,没办法,谁让它理解起来就那么费劲呢 ? 你可别犯愁,真正核心的类可还没出来。。
KeyguardViewMediator核心类 ,该类是唯一实现了KeyguardViewCallback的类。
功能:该类提供了一些接口,由PhoneWindowManager)去访问控制Keyguard....
该类的初始化是在PolicyWindowManager的构造函数中创建的。如下:
public class PhoneWindowManager implements WindowManagerPolicy { ... /** {@inheritDoc} */ //由SystemServer调用 public void init(Context context, IWindowManager windowManager, LocalPowerManager powerManager) { ...//初始化该实例 mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager); } }
参照源代码,把一些重要的属性和方法的大意给分析下:
public class KeyguardViewMediator implements KeyguardViewCallback, KeyguardUpdateMonitor.SimStateCallback { private boolean mSystemReady; //启动成功 由SystemServer调用 /**Used to keep the device awake while to ensure the keyguard finishes opening before * we sleep.*/ //在需要显示锁屏界面时,保持屏幕在某个时间段内为暗屏状态 private PowerManager.WakeLock mShowKeyguardWakeLock; private KeyguardViewManager mKeyguardViewManager; //KeyguardViewManager实例 /** * External apps (like the phone app) can tell us to disable the keygaurd.*/ //是否允许其他App禁止锁屏 , 例如来电时 禁止锁屏 private boolean mExternallyEnabled = true; //处于锁屏状态 , 即显示锁屏 private boolean mShowing = false; // true if the keyguard is hidden by another window private boolean mHidden = false; //被其他窗口掩盖 , 例如来电时锁屏被掩盖 private boolean mScreenOn = false; // 是否亮屏 public KeyguardViewMediator(Context context, PhoneWindowManager callback, LocalPowerManager powerManager) { ... //构造相关实例对象 mKeyguardViewProperties = new LockPatternKeyguardViewProperties( new LockPatternUtils(mContext), mUpdateMonitor); mKeyguardViewManager = new KeyguardViewManager( context, WindowManagerImpl.getDefault(), this, mKeyguardViewProperties, mUpdateMonitor); //解锁成功后发送的Intent mUserPresentIntent = new Intent(Intent.ACTION_USER_PRESENT); mUserPresentIntent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); } /** Called to let us know the screen was turned off. * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or * {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}. */ //屏幕变灰暗 , 原因有如下:以及对应的逻辑处理。 // 1、OFF_BECAUSE_OF_USER : 用户按下POWER键 , 当前是否处于锁屏界面,若是(mShowing)则重置显示界面,否则重新显示锁屏界面 // 2、OFF_BECAUSE_OF_TIMEOUT : 屏幕超时,常见情况就是一段时间没有操作屏幕,手机处于灰暗状态。 处理行为: // 发送Action值为DELAYED_KEYGUARD_ACTION的广播,因为该类注册了该Intent广播,接受到时会调用doKeyguard()方法锁屏 // 3、OFF_BECAUSE_OF_PROX_SENSOR:接打电话时,距离感应太近导致暗屏,此时由于PowerManager那儿已经处理了暗屏,不需要做任何事 // 最后,如果以上逻辑都不成立,调用 doKeyguard()方法显示屏幕 public void onScreenTurnedOff(int why) { ... } /** * Let's us know the screen was turned on. */ public void onScreenTurnedOn() { synchronized (this) { ... notifyScreenOnLocked(); //通知亮屏 } } /** Enable the keyguard if the settings are appropriate. */ private void doKeyguard() { synchronized (this) { ... showLocked();//显示锁屏界面 } } //该方法的调用时机就是当按下POWER键时,系统会回调该方法 keyCode值一般为 26 public boolean onWakeKeyWhenKeyguardShowingTq(int keyCode) { //操作按键是否能唤醒屏幕 if (isWakeKeyWhenKeyguardShowing(keyCode)) { // give the keyguard view manager a chance to adjust the state of the // keyguard based on the key that woke the device before poking // the wake lock wakeWhenReadyLocked(keyCode);//开始唤醒屏幕咯 return true; } else { return false; } } /** {@inheritDoc} */ //在一定时间内保存屏幕为亮屏状态 public void pokeWakelock(int holdMs) { ... } //表示成功得分完成了解锁操作 public void keyguardDone(boolean authenticated, boolean wakeup) { synchronized (this) { //发送给Handler 进行异步处理 Message msg = mHandler.obtainMessage(KEYGUARD_DONE); msg.arg1 = wakeup ? 1 : 0; mHandler.sendMessage(msg); if (authenticated) { mUpdateMonitor.clearFailedAttempts(); //清除错误登录次数 } ... } } //Handler对象 , 异步处理 private Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { ... //异步处理 } } }; //异步处理完成开锁成功 private void handleKeyguardDone(boolean wakeup) { handleHide(); //释放该Keyguard对应的窗口 mWakeLock.release(); mContext.sendBroadcast(mUserPresentIntent); //解锁成功,发送Intent信息 } //显示锁屏界面 private void handleShow() { synchronized (KeyguardViewMediator.this) { ... mKeyguardViewManager.show(); mShowing = true; ... } } private void handleHide() { synchronized (KeyguardViewMediator.this) { //去除锁屏界面对应的窗口 mKeyguardViewManager.hide(); mShowing = false; ... } } //设置状态栏enable状态 , 例如:能否被下拉等 private void adjustStatusBarLocked() { ... // if the keyguard is shown, allow the status bar to open // only if the keyguard is insecure and is covered by another window boolean enable = !mShowing || (mHidden && !isSecure()); mStatusBarManager.disable(enable ?StatusBarManager.DISABLE_NONE : StatusBarManager.DISABLE_EXPAND); } } }
该类的很多方法都是由PhoneWindowManager调用访问的
基本上把一些重要的类及其相关的方法给走了一遍吧,对看源码的还是很有帮助的。因为我的理解还不是很深入,可能有偏颇的地方。希望以后能够组件完善起来。 阿门 !