android 5.1 keyguardhostview,android4.4的Keyguard心得

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

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

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

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

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

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

3672_0.png

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

从图中可以看到, 开机后首先从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

等等,这些都是细节,后续博客中将继续分析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值