锁屏(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调用访问的

    基本上把一些重要的类及其相关的方法给走了一遍吧,对看源码的还是很有帮助的。因为我的理解还不是很深入,可能有偏颇的地方。希望以后能够组件完善起来。 阿门 !

posted on 2012-08-20 18:08  zyuchao  阅读(695)  评论(0编辑  收藏  举报

导航