android4.4的Keyguard心得

来源:互联网 发布:完美动力unity3d怎么样 编辑:程序博客网 时间:2024/05/29 09:24

在总结锁屏代码之前,有两个中心思想要铭记于心

A) KeyguardHostView就是我们最终所要展示的界面,所以不论用什么方法手段,都要将这个KeyguardHostView添加到窗口中,后续填充它,都是细节问题

B) 那么问题来了,通常我们将一个view添加到窗口中会用什么方法呢? 

        答案有两种 1 WindowManager.addView()  2 LayoutInflater.inflate(resID, parentView, true); 而在锁屏代码中这两种方法都有用到

-----------------------------------------------华丽丽的分割线-------------------------------------------------------------------

接下来用一张图来解释流程



-------------------------------又是可爱的分割线--------------------------------------------------------

从图中可以看到, 开机后首先从PhoneWindowManager的systemReady方法调用两个包装类(KeyguardServiceDelegate.java  KeyguardServiceWrapper.java)之后会调用到KeyguardService.java中的onSystemReady,进而调用锁屏代码的总调度使KeyguardViewMediator.java。它就是锁屏的CEO。做我们软件的都知道,CEO一般不会太牵涉代码问题,只管分配,协调工作,客户/供应链的沟通。在KeyguardViewMediator.java中的mExternallyEnabled变量就是总监与客户谈判的筹码,如果客户第三方通过KeyguardManager.diableKeyguard()方法禁用系统锁屏后,此变量会置为false,从而不会绘制系统锁屏界面,otherwise,将任务大手一甩直接丢给总经理KeyguardViewManager.java.具体代码如下:

[java] view plaincopy
  1. <span style="font-size:12px;">    /** 
  2.      * Enable the keyguard if the settings are appropriate. 
  3.      */  
  4.     private void doKeyguardLocked(Bundle options) {  
  5.         boolean isSimSecure = mUpdateMonitor.isSimPinSecure();  
  6.         ///M: if another app is disabling us (except Sim Secure), then don't show  
  7.         if ((!mExternallyEnabled && !isSimSecure)|| PowerOffAlarmManager.isAlarmBoot()) {  
  8.         if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: not showing because externally disabled");  
  9.             return;  
  10.         }  
  11.         。。。  
  12.         showLocked(options);  
  13.     }  
  14.   
  15.     private void handleShow(Bundle options) {  
  16.         。。。  
  17.         mKeyguardViewManager.show(options);  
  18.         。。。  
  19.     }  
  20.   
  21.   
  22. 通过以上代码,所有的任务都已经落实到KeyguardViewManager.java的头上,接下来看看这个总经理是如何工作的  
  23.   
  24.   
  25.   
  26.  /** 
  27.      * Show the keyguard.  Will handle creating and attaching to the view manager 
  28.      * lazily. 
  29.      */  
  30.     public synchronized void show(Bundle options) {  
  31.         if (DEBUG) Log.d(TAG, "show(); mKeyguardView=" + mKeyguardView);  
  32.   
  33.         boolean enableScreenRotation = KeyguardUtils.shouldEnableScreenRotation(mContext);  
  34.         if (DEBUG) Log.d(TAG, "show() query screen rotation after");  
  35.   
  36.         /// M: Incoming Indicator for Keyguard Rotation @{  
  37.         KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();  
  38.         /// @}  
  39.         <span style="color:#FF0000;">maybeCreateKeyguardLocked(enableScreenRotation, false, options);</span>  
  40.           
  41.         if (DEBUG) Log.d(TAG, "show() maybeCreateKeyguardLocked finish");  
  42.           
  43.         maybeEnableScreenRotation(enableScreenRotation);  
  44.   
  45.         // Disable common aspects of the system/status/navigation bars that are not appropriate or  
  46.         // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED  
  47.         // activities. Other disabled bits are handled by the KeyguardViewMediator talking  
  48.         // directly to the status bar service.  
  49.         int visFlags = View.STATUS_BAR_DISABLE_HOME;  
  50.         if (shouldEnableTranslucentDecor()) {  
  51.             mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS  
  52.                                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;  
  53.         }  
  54.         if (DEBUG) Log.d(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");  
  55.         mKeyguardHost.setSystemUiVisibility(visFlags);  
  56.   
  57.         mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);  
  58.         mKeyguardHost.setVisibility(View.VISIBLE);  
  59.         <span style="color:#FF0000;">mKeyguardView.show();</span>  
  60.         mKeyguardView.requestFocus();  
  61.         if (DEBUG) Log.d(TAG, "show() exit; mKeyguardView=" + mKeyguardView);  
  62.     }  
  63. 关键代码所以全部贴出来分析分析吧,   
  64. <span style="color:#009900;">//有一点需要提前注意mKeyguardHost只是一个空View,mKeyguardView才是真正的KeyguardHostView</span>  
  65. boolean enableScreenRotation用来判断是否允许屏幕旋转,  
  66. KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();此行代码是为了重新设置query的时间,比如未接来电,未读短信等,之所以重新set是为了仿照  
  67. iphone手机,绘制锁屏时,查询未读信息/未接电话的数目是针对本次锁屏后收到的未读信息/未接电话  
[java] view plaincopy
  1. maybeCreateKeyguardLocked(enableScreenRotation, false, options); 我擦~终于到关键代码了,此方法就是真正创建锁屏的方法,来一睹芳容吧  
  2.     private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,  
  3.             Bundle options) {  
  4.         if (mKeyguardHost != null) {  
  5.             mKeyguardHost.saveHierarchyState(mStateContainer);  
  6.         }  
  7.   
  8.         if (mKeyguardHost == null) {  
  9.             if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");  
  10.   
  11.             <span style="color:#990000;">mKeyguardHost = new ViewManagerHost(mContext);</span>  
  12.   
  13.             int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN  
  14.                     | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR  
  15.                     | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN  
  16.                     | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;  
  17.   
  18.             if (!mNeedsInput) {  
  19.                 flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;  
  20.             }  
  21.   
  22.             final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;  
  23.             final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;  
  24.             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(  
  25.                     stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);  
  26.             lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;  
  27.             lp.windowAnimations = R.style.Animation_LockScreen;  
  28.             lp.screenOrientation = enableScreenRotation ?  
  29.                     ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;  
  30.   
  31.             if (ActivityManager.isHighEndGfx()) {  
  32.                 lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;  
  33.                 lp.privateFlags |=  
  34.                         WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;  
  35.             }  
  36.             lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;  
  37.             /// M: Poke user activity when operating Keyguard  
  38.             //lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;  
  39.             lp.setTitle("Keyguard");  
  40.             mWindowLayoutParams = lp;  
  41.             ///M: skip add KeyguardHost into viewManager in AT case  
  42.             if (!KeyguardViewMediator.isKeyguardInActivity) {  
  43.                 <span style="color:#CC0000;">mViewManager.addView(mKeyguardHost, lp);</span>  
  44.             } else {  
  45.                 if (DEBUG) Log.d(TAG, "skip add mKeyguardHost into mViewManager for testing");  
  46.             }  
  47.             KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);  
  48.         }  
  49.   
  50.        /// M: If force and keyguardView is not null, we should relase memory hold by old keyguardview  
  51.         if (force && mKeyguardView != null) {  
  52.             mKeyguardView.cleanUp();  
  53.         }  
  54.         if (force || mKeyguardView == null) {  
  55.                 mKeyguardHost.setCustomBackground(null);  
  56.                 mKeyguardHost.removeAllViews();  
  57.                 <span style="color:#CC0000;">inflateKeyguardView(options);</span>  
  58.                 mKeyguardView.requestFocus();  
  59.         }  
  60.         updateUserActivityTimeoutInWindowLayoutParams();  
  61.         mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);  
  62.   
  63.         mKeyguardHost.restoreHierarchyState(mStateContainer);  
  64.     }  
此处红色代码中通过mViewManager.addView(mKeyguardHost, lp);将初始话的mKeyguardHost(空view)通过WindowManager.addView的方式添加到窗口之中
然后在通过inflateKeyguardView(options);方法将真正的KeyguardHostView也添加到mKeyguardHost中, 具体如何添加请看代码:

private void inflateKeyguardView(Bundle options) {
        /// M: add for power-off alarm @{
        int resId = R.id.keyguard_host_view;
        int layoutId = R.layout.keyguard_host_view;
        if(PowerOffAlarmManager.isAlarmBoot()){
            resId = R.id.power_off_alarm_host_view;
            layoutId = R.layout.mtk_power_off_alarm_host_view;
        }
        /// @}
        View v = mKeyguardHost.findViewById(resId);
        if (v != null) {
            mKeyguardHost.removeView(v);
        }
        /// M: Save new orientation
        mCreateOrientation = mContext.getResources().getConfiguration().orientation;
        mCreateScreenWidthDp = mContext.getResources().getConfiguration().screenWidthDp;
        mCreateScreenHeightDp = mContext.getResources().getConfiguration().screenHeightDp;
        
        final LayoutInflater inflater = LayoutInflater.from(mContext);
        View view = inflater.inflate(layoutId, mKeyguardHost, true);

        mKeyguardView = (KeyguardHostView) view.findViewById(resId);
        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
        mKeyguardView.setViewMediatorCallback(mViewMediatorCallback);
        mKeyguardView.initializeSwitchingUserState(options != null &&
                options.getBoolean(IS_SWITCHING_USER));
        
        // HACK
        // The keyguard view will have set up window flags in onFinishInflate before we set
        // the view mediator callback. Make sure it knows the correct IME state.
        if (mViewMediatorCallback != null) {
            // Start of cube26 code
            if (mLockscreenNotifications)
                mNotificationView.setViewMediator(mViewMediatorCallback);
            // End of cube26 code
            
            KeyguardPasswordView kpv = (KeyguardPasswordView) mKeyguardView.findViewById(
                    R.id.keyguard_password_view);

            if (kpv != null) {
                mViewMediatorCallback.setNeedsInput(kpv.needsInput());
            }
        }

        if (options != null) {
            int widgetToShow = options.getInt(LockPatternUtils.KEYGUARD_SHOW_APPWIDGET,
                    AppWidgetManager.INVALID_APPWIDGET_ID);
            if (widgetToShow != AppWidgetManager.INVALID_APPWIDGET_ID) {
                mKeyguardView.goToWidget(widgetToShow);
            }
        }
    }
红色标记处,通过LayoutInflater.inflate(resId, parentView, true)的方式将R.layout.keyguard_host_view添加到mKeyguardHost这个空view中
自此真正的KeyguardHostView已经添加到窗口中,并且通过各中layoutparam将其显示在最上层,后续的就是如何将其显示,使用何种方式显示,比如Slide,Swipe,Password
等等,这些都是细节,后续博客中将继续分析
[java] view plaincopy
  1.   
0 0
原创粉丝点击