Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android4.4的Keyguard心得

android4.4的Keyguard心得

編輯:關於Android編程

在總結鎖屏代碼之前,有兩個中心思想要銘記於心

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一般不會太牽涉代碼問題,只管分配,協調工作,客戶/供應鏈的溝通。在KeyguardViewMediatZ喎?/kf/ware/vc/" target="_blank" class="keylink">vci5qYXZh1tC1xG1FeHRlcm5hbGx5RW5hYmxlZLHkwb++zcrH19y84NPrv827p8y4xdC1xLPvwuujrMjnufu/zbuntdrI/be9zai5/UtleWd1YXJkTWFuYWdlci5kaWFibGVLZXlndWFyZCgpt723qL3708PPtc2zy/jGwbrzo6y0y7Hkwb+74dbDzqpmYWxzZaOstNO2+LK7u+G75tbGz7XNs8v4xsG958Pmo6xvdGhlcndpc2WjrL2ryM7O8bTzytbSu8um1rG907aquPjX3L6twO1LZXlndWFyZFZpZXdNYW5hZ2VyLmphdmEuvt/M5bT6wuvI58/Co7o8L3A+CjxwcmUgY2xhc3M9"brush:java;"> /** * Enable the keyguard if the settings are appropriate. */ private void doKeyguardLocked(Bundle options) { boolean isSimSecure = mUpdateMonitor.isSimPinSecure(); ///M: if another app is disabling us (except Sim Secure), then don't show if ((!mExternallyEnabled && !isSimSecure)|| PowerOffAlarmManager.isAlarmBoot()) { if (DEBUG) KeyguardUtils.xlogD(TAG, "doKeyguard: not showing because externally disabled"); return; } 。。。 showLocked(options); } private void handleShow(Bundle options) { 。。。 mKeyguardViewManager.show(options); 。。。 } 通過以上代碼,所有的任務都已經落實到KeyguardViewManager.java的頭上,接下來看看這個總經理是如何工作的  /**      * Show the keyguard.  Will handle creating and attaching to the view manager      * lazily.      */     public synchronized void show(Bundle options) {         if (DEBUG) Log.d(TAG, "show(); mKeyguardView=" + mKeyguardView);         boolean enableScreenRotation = KeyguardUtils.shouldEnableScreenRotation(mContext);         if (DEBUG) Log.d(TAG, "show() query screen rotation after");         /// M: Incoming Indicator for Keyguard Rotation @{         KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();         /// @}         maybeCreateKeyguardLocked(enableScreenRotation, false, options);                  if (DEBUG) Log.d(TAG, "show() maybeCreateKeyguardLocked finish");                  maybeEnableScreenRotation(enableScreenRotation);         // Disable common aspects of the system/status/navigation bars that are not appropriate or         // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED         // activities. Other disabled bits are handled by the KeyguardViewMediator talking         // directly to the status bar service.         int visFlags = View.STATUS_BAR_DISABLE_HOME;         if (shouldEnableTranslucentDecor()) {             mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS                                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;         }         if (DEBUG) Log.d(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");         mKeyguardHost.setSystemUiVisibility(visFlags);         mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);         mKeyguardHost.setVisibility(View.VISIBLE);         mKeyguardView.show();         mKeyguardView.requestFocus();         if (DEBUG) Log.d(TAG, "show() exit; mKeyguardView=" + mKeyguardView);     } 關鍵代碼所以全部貼出來分析分析吧, //有一點需要提前注意mKeyguardHost只是一個空View,mKeyguardView才是真正的KeyguardHostView boolean enableScreenRotation用來判斷是否允許屏幕旋轉, KeyguardUpdateMonitor.getInstance(mContext).setQueryBaseTime();此行代碼是為了重新設置query的時間,比如未接來電,未讀短信等,之所以重新set是為了仿照 iphone手機,繪制鎖屏時,查詢未讀信息/未接電話的數目是針對本次鎖屏後收到的未讀信息/未接電話

maybeCreateKeyguardLocked(enableScreenRotation, false, options); 我擦~終於到關鍵代碼了,此方法就是真正創建鎖屏的方法,來一睹芳容吧
    private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
            Bundle options) {
        if (mKeyguardHost != null) {
            mKeyguardHost.saveHierarchyState(mStateContainer);
        }

        if (mKeyguardHost == null) {
            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");

            mKeyguardHost = new ViewManagerHost(mContext);

            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;

            if (!mNeedsInput) {
                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
            }

            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
            final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
            lp.windowAnimations = R.style.Animation_LockScreen;
            lp.screenOrientation = enableScreenRotation ?
                    ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;

            if (ActivityManager.isHighEndGfx()) {
                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
                lp.privateFlags |=
                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
            }
            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
            /// M: Poke user activity when operating Keyguard
            //lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
            lp.setTitle("Keyguard");
            mWindowLayoutParams = lp;
            ///M: skip add KeyguardHost into viewManager in AT case
            if (!KeyguardViewMediator.isKeyguardInActivity) {
                mViewManager.addView(mKeyguardHost, lp);
            } else {
                if (DEBUG) Log.d(TAG, "skip add mKeyguardHost into mViewManager for testing");
            }
            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
        }

       /// M: If force and keyguardView is not null, we should relase memory hold by old keyguardview
        if (force && mKeyguardView != null) {
            mKeyguardView.cleanUp();
        }
        if (force || mKeyguardView == null) {
                mKeyguardHost.setCustomBackground(null);
                mKeyguardHost.removeAllViews();
                inflateKeyguardView(options);
                mKeyguardView.requestFocus();
        }
        updateUserActivityTimeoutInWindowLayoutParams();
        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);

        mKeyguardHost.restoreHierarchyState(mStateContainer);
    }
此處紅色代碼中通過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
等等,這些都是細節,後續博客中將繼續分析




  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved