Android4.2 keyguard源码架构,学习(一)!

来源:互联网 发布:mysql怎么分页 编辑:程序博客网 时间:2024/05/21 19:53

最近这两年爱上写博客,是因为它可以很好的帮我理顺思路,特别是问题有点复杂的时候,很容易就陷进去。

首先用hierarchyviewer.bat查看当前界面的结构,找到突破口,然后慢慢找。

MediatekGlowPadView.java

KeyguardViewManager.java

KeyguardSelectorView.java

KeyguardHostView.java

KeyguardViewMediator.java

SlidingChallengeLayout.java

 既然是java语言写的,那肯定得一面向对象得思路来分析,对象从小到大。MediatekGlowPadView对象首先是view的派生类,负责用来显示,并且监听touch事件。

官方解释:一个可重用widget,包含一个中心,外圈和波浪动画。

public class MediatekGlowPadView extends View implements OnTouchListener {
}
截图明了:




首先看下构造函数:

主要就是初始化一些参数,例如圈的半径之类的。这里记录一个基础性的问题:

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.GlowPadView);        mInnerRadius = a.getDimension(R.styleable.GlowPadView_innerRadius, mInnerRadius);
    prvandroid:innerRadius="@*android:dimen/glowpadview_inner_radius"

styleable后面首先要接style的类型,下划线然后接具体的属性(GlowPadView_innerRadius)。

对于此类中比较生疏的有:tween动画效果

另外例一下对分析这个对象有很大帮助的重要函数:switchToState()   onTouchEvent()    handleTrigger()。

    private void handleTrigger(LockScreenNewEventView newEventView) {        ///M: In case unlock blocks newly launched activity, we should direct ueser to unlock mode first        if (mOnTriggerListener != null) {            mOnTriggerListener.onTrigger(newEventView, -1);        }        Intent intent = new Intent();        int resourceId = newEventView.getResourceId();        switch (resourceId) {            case com.mediatek.internal.R.drawable.ic_newevent_smsmms:                intent.setComponent(new ComponentName(MMS_PACKAGE_NAME, MMS_CLASS_NAME));                launchActivity(intent);                break;            case com.mediatek.internal.R.drawable.ic_newevent_phone:                intent.setComponent(new ComponentName(CALL_LOG_PACKAGE_NAME, CALL_LOG_CLASS_NAME));                launchActivity(intent);                break;            case com.mediatek.internal.R.drawable.ic_newevent_email:                intent.setComponent(new ComponentName(EMAIL_PACKAGE_NAME, EMAIL_CLASS_NAME));                launchActivity(intent);                break;            default:                Xlog.d(TAG, "handleTrigger unknown resource id, resourceId=" + resourceId);        }    }

这里运用了典型的策略和机制分离思想。(可能有人会误解,上面代码中的实现机制是没有实际作用的,摆设),mOnTriggerListener.onTrigger(newEventView, -1)监听接口,实现是在KeyguardSelectorView.java文件中。


KeyguardSelectorView:这是整个主锁屏界面对象,不包含左右滑动的页面。除了上面的解锁图标外,还有一些其他显示信息,例如:sim信息,闹钟等


监听对象的实现:

    MediatekGlowPadView.OnTriggerListener mOnTriggerListener = new MediatekGlowPadView.OnTriggerListener() {        public void onTrigger(View v, int target) {            final int resId = mGlowPadView.getResourceIdForTarget(target);            switch (resId) {                case com.android.internal.R.drawable.ic_action_assist_generic:                    Intent assistIntent =                            ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))                            .getAssistIntent(mContext, UserHandle.USER_CURRENT);                    if (assistIntent != null) {                        mActivityLauncher.launchActivity(assistIntent, false, true, null, null);                    } else {                        Log.w(TAG, "Failed to get intent for assist activity");                    }                    mCallback.userActivity(0);                    break;                case com.android.internal.R.drawable.ic_lockscreen_camera:                    mActivityLauncher.launchCamera(null, null);                    mCallback.userActivity(0);                    break;                case com.android.internal.R.drawable.ic_lockscreen_phone:   Intent phoneIntent = new Intent();                     phoneIntent.setComponent(new ComponentName("com.android.contacts",                                                                          "com.android.contacts.activities.DialtactsActivity"));    mActivityLauncher.launchActivity(phoneIntent, false, false, null, null);                    mCallback.userActivity(0);                    break;                case com.android.internal.R.drawable.ic_lockscreen_sms:   Intent smsIntent = new Intent();                     smsIntent.setComponent(new ComponentName("com.android.mms",                                                                          "com.android.mms.ui.BootActivity"));    mActivityLauncher.launchActivity(smsIntent, false, false, null, null);                    mCallback.userActivity(0);                    break;                case com.android.internal.R.drawable.ic_lockscreen_unlock_phantom:                case com.android.internal.R.drawable.ic_lockscreen_unlock:                    mCallback.userActivity(0);                    mCallback.dismiss(false);                    break;                                    /// M: Add a special case for incoming indicator feature, when indicator view launches activity, go to unlockscreen                /// only if necessary, or you may see homescreen before activity is launched                case -1:                    mCallback.userActivity(0);                    if (isSecure()) {                        mCallback.dismiss(false);                    }                break;            }        }………………    }

构造函数:很简单,就是实例化一个锁屏图形,LockPatternUtils。

主要ui显示:

    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mGlowPadView = (MediatekGlowPadView) findViewById(R.id.glow_pad_view);        mGlowPadView.setOnTriggerListener(mOnTriggerListener);        updateTargets();        mSecurityMessageDisplay = new KeyguardMessageArea.Helper(this);        View bouncerFrameView = findViewById(R.id.keyguard_selector_view_frame);        mBouncerFrame = bouncerFrameView.getBackground();                /// M: If dm lock is on, we should also hide widget @{        boolean dmLocked = KeyguardUpdateMonitor.getInstance(getContext()).dmIsLocked();        mGlowPadView.setVisibility(dmLocked ? View.INVISIBLE : View.VISIBLE);        /// @}                /// M: Init medaitke newevent feature related views        if (Settings.System.getInt(getContext().getContentResolver(), INCOMING_INDICATOR_ON_LOCKSCREEN, 1) == 1) {            Log.d(TAG, "constructor infalte newevent feature related views");            mGlowPadView.setLockScreenView(this);            ViewGroup unLockPanel = (ViewGroup)findViewById(R.id.keyguard_unlock_panel);            final LayoutInflater inflater = LayoutInflater.from(mContext);            inflater.inflate(com.mediatek.internal.R.layout.keyguard_unread_event_view, unLockPanel, true);            UnReadEventView unReadEventView = (UnReadEventView)findViewById(com.mediatek.internal.R.id.unread_event_view);            /// M: Incoming Indicator for Keyguard Rotation @{            unReadEventView.setVisibility(dmLocked ? View.INVISIBLE : View.VISIBLE);            unReadEventView.updateQueryBaseTimeAndRefreshUnReadNumber(KeyguardUpdateMonitor.getInstance(mContext).getQueryBaseTime());            /// @}            setUnReadEventView(unReadEventView);            mGlowPadView.syncUnReadEventView(unReadEventView);        }    }

应用glow_pad_view.xml的布局,一般自定四个方向的解锁功能和图标,就从这里来找了。

开启监听。

另外这里总结一个现象,子界面的xml布局文件一般是在父界面调用。例如上面在KeyguardSelectorView中调用glow_pad_view.xml(对应MediatekGlowPadView)。

对应的Keyguard_selector_view.xml 布局文件:

<com.android.internal.policy.impl.keyguard.KeyguardSelectorView    xmlns:prvandroid="http://schemas.android.com/apk/prv/res/android"    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/keyguard_selector_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_maxWidth="500dp"    android:layout_maxHeight="@dimen/keyguard_security_height"    android:clipChildren="false"    android:clipToPadding="false"    android:orientation="vertical"    android:contentDescription="@string/keyguard_accessibility_slide_unlock">    <FrameLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_gravity="center"        android:clipChildren="false"        android:clipToPadding="false"        android:gravity="center">        <include layout="@layout/keyguard_message_area"            android:layout_width="match_parent"            android:layout_height="wrap_content" />        <View            android:id="@+id/keyguard_selector_view_frame"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_marginLeft="16dp"            android:layout_marginRight="16dp"            android:background="@*android:drawable/kg_bouncer_bg_white"/>        <FrameLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:layout_marginTop="20dp"            android:id="@+id/keyguard_unlock_panel">            <include layout="@layout/keyguard_glow_pad_container" />        </FrameLayout>        <include layout="@layout/keyguard_eca"            android:id="@+id/keyguard_selector_fade_container"            android:layout_width="match_parent"            android:layout_height="48dp"            android:layout_gravity="bottom|center_horizontal" />    </FrameLayout></com.android.internal.policy.impl.keyguard.KeyguardSelectorView>

上面XmL文件可以很直观的看到布局界面,其中keyguard_unlock_panel就是glow_pad_view.xml的应用。

因为我这里主要是为了了解锁屏的架构,所以对其他的布局不做分析。

因为keyguard_selector_view.xml在KeyguardHostView中调用,接下来分析这个文件。

KeyguardHostView:这个三个keyguard界面对象。包含appwidget


首先看一下整体布局,keyguard_host_view.xml,这里分为port和land,port是SlidingChallengeLayout,land是MultiPaneChallengeLayout,下面我们以port为例分析:

<com.android.internal.policy.impl.keyguard.KeyguardHostView    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:androidprv="http://schemas.android.com/apk/res/android"    android:id="@+id/keyguard_host_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center_horizontal"    android:orientation="vertical">    <com.android.internal.policy.impl.keyguard.SlidingChallengeLayout        android:id="@+id/sliding_layout"        android:layout_width="match_parent"        android:layout_height="match_parent">                <FrameLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            androidprv:layout_childType="mediatekLayerBackground">        </FrameLayout>        <FrameLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            androidprv:layout_childType="pageDeleteDropTarget">            <include layout="@layout/keyguard_widget_remove_drop_target"                android:id="@+id/keyguard_widget_pager_delete_target"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_gravity="top|center_horizontal" />        </FrameLayout>        <FrameLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            androidprv:layout_childType="widgets">            <include layout="@layout/keyguard_widget_pager"                android:id="@+id/app_widget_container"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:layout_gravity="center"/>        </FrameLayout>        <View android:layout_width="match_parent"              android:layout_height="match_parent"              androidprv:layout_childType="scrim"              android:background="#99000000" />                <FrameLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            androidprv:layout_childType="mediatekLayerForeground">        </FrameLayout>        <com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer            android:id="@+id/keyguard_security_container"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_maxHeight="@dimen/keyguard_security_height"            androidprv:layout_childType="challenge"            android:padding="0dp"            android:gravity="bottom|center_horizontal">            <com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper                android:id="@+id/view_flipper"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:clipToPadding="false"                android:paddingTop="@dimen/keyguard_security_view_margin"                android:gravity="center">            </com.android.internal.policy.impl.keyguard.KeyguardSecurityViewFlipper>        </com.android.internal.policy.impl.keyguard.KeyguardSecurityContainer>        <ImageButton              android:layout_width="match_parent"              android:layout_height="@dimen/kg_widget_pager_bottom_padding"              androidprv:layout_childType="expandChallengeHandle"              android:focusable="true"              android:background="@null"              android:src="@drawable/keyguard_expand_challenge_handle"              android:scaleType="center"              android:contentDescription="@string/keyguard_accessibility_expand_lock_area" />    </com.android.internal.policy.impl.keyguard.SlidingChallengeLayout></com.android.internal.policy.impl.keyguard.KeyguardHostView>


0 0
原创粉丝点击