android 怎么实现android 手势解锁锁业务逻辑

博客访问: 152923
博文数量: 22
博客积分: 445
博客等级: 下士
技术积分: 280
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 嵌入式
背景& &&& 先说说背景吧,这是本人从WinCE系统转到Android之后,接到的第一个任务就是修改Android原生的解锁界面,之前看了两个星期的书和网络博客,Java的也有、Android应用开发的也有、Linux开发的也有、Android框架介绍的也有。然后写了几个APK试了了一下,觉得自己有能力了,便充满自信地找到组长接任务。组长没有说什么,拿出一个竞争对手公司的样机,玩了几下拿个我,说道:这是竞争对手公司的方案,他们的解锁效果不错,很方便,你看看能不能也做出来。&& 说实话接到这个任务当时真的有点失望,心里面一直想,当初做WinCE做的几乎全是驱动,整天和寄存器、指针、协议打交道,现在转到Android,做这些应用的东西真的不太习惯。不过转头一想,不管什么东西,要做就要做好,慢慢来嘛,于是拿走样机回到工位上,安心开始研究。&& 样机解锁界面效果类似如下
& 其实这也是我后面做出的效果,样机因为没有ROOT不好调试截图,功能是将解锁的图标添加了最近运行的运用的图标,这样的话更方便用户去使用
锁屏功能分析
Android锁屏相关的代码在以下几个路径:
锁屏的具体实现:
其中的主要代码如下:
锁屏控件的View类
锁屏控件使用到的资源
Android上常用的锁屏方法有以下几种:默认锁屏方式(LockScreen)、SIM卡解锁方式(SimUnlockScreen)、图案解锁方式(PatternUnlockScreen)、密码解锁方式(PasswordUnlockScreen)、账号解锁方式(AccountUnlockScreen),这些解锁方式都有对应的源码实现,我们这里讨论的是最常用的默认解锁方式,在Android4.0之后,解锁控件变为“波纹解锁”,即如概述介绍的那样,通过控制中心的圆圈来实现解锁,这种解锁方式,实际上可以进一步增强。
1.1.1.Android启动后从窗口管理器运行到解锁界面的动作:
1.开机启动后执行到PhoneWindowManager.systemReady()。
2.调用KeyguardViewMediator.onSystemReady()进行待机锁屏及解锁逻辑。
3.KeyguardViewMediator是整个待机解锁屏业务的调度器,负责调度锁屏界面的相关动作及查询解锁屏状态。
1.1.2.KeyguardViewMediator的作用
1.查询锁屏状态,及当前处于锁屏状态还是已解锁状态,PhoneWindowManager持有KeyguardViewMediator的引用,当用户触摸屏幕或者按下某个键是,PhoneWindowManager会通过KeyguardViewMediator查询锁屏状态(锁定/解锁),进行不同的响应处理。如果处于锁定状态,系统输入事件会受到限制。
2.响应电源事件(黑/亮屏)。判断锁屏界面应该处于什么状态(显示或者重置)。手机黑屏后,锁屏界面马上就会显示出来,以便下一次亮屏后,马上就能显示锁屏界面,而不会出现闪烁或延时。
3.其他应用程序或者服务也可以请求禁止锁屏(通过调用KeyguardViewMediator的setKeyguardEnabled(boolean)方法)。例如接听来电界面。
KeyguardViewMediator类在WindowManagerPolicy(在手机系统中是PhoneWindowManager实例)初始化时被创建,并运行在它的线程上,锁屏的UI界面也是在这个线程上创建及显示的。KeyguardViewMediator类提供的状态查询api可以被诸如android.view.WindowManager、com.android.server.InputManager等其它线程调用,所以,KeyguardViewMediator类上的这些api方法都是线程同步的(synchronized)。
1.1.3.KeyguardViewMediator可以进行的调度操作
1) 点亮屏幕pokeWakelock();
2) 报告锁屏权限验证是否成功keyguardDone(boolean);
3) 响应SIM卡状态变化并对锁屏界面做相应的调整onSimStateChanged()。
4) 调度待机锁屏UI界面的管理,包括:
1.显示handleShow ()、
2.隐藏handleHide ()、
3.重置handleReset ()、
4.点亮屏幕handleWakeWhenReady()等。
KeyguardViewMediator实现这部分调度是通过持有一个KeyguardViewManager来实现的。总之KeyguardUpdateMonitor是所有会影响整个待机解/锁屏业务的事件的监控器。(除了作为监控器,它还发挥着类似上下文的作用,也许我们应该把这个类命名为(KeyguardContext)。它监控诸如时间改变、电池状态改变、时区改变、SIM卡状态变化、电话状态变化、电话信号变化等事件。它是一个观察者模式的被观察对象。观察者通过调用KeyguardUpdateMonitor的以下方法进行注册,观察自己感兴趣的变化。
&&& KeyguardUpdateMonitor的观察者包括KeyguardViewMediator、LockScreen、PatternUnlockScreen、AccountUnlockScreen、PasswordUnlockScreen、SimUnlockScreen等。观察者通过调用KeyguardUpdateMonitor的removeCallback(Object)取消观察。
KeyguardViewManager负责管理待机屏UI界面的创建、显示、隐藏、重置以及通过一个回调KeyguardViewCallback通知调度器KeyguardViewMediator进行相关的调度。
LockPatternKeyguardView(KeyguardViewBase)是所有锁屏和解锁UI界面的宿主。它有2个模式Mode.
LockScreen和Mode. UnlockScreen。它负责根据当前上下文环境切换当前应该显示的待机屏。
它提供一个回调给当前显示的待机屏并处理其回调,如果回调动作是自己处理不了的,则继续报告给KeyguardViewMediator进行处理。
锁屏界面就是LockScreen;解锁界面包括SIM卡解锁SimUnlockScreen、图案解锁PatternUnlockScreen、密码解锁PasswordUnlockScreen、帐号解锁AccountUnlockScreen
解锁成功后,锁屏流程转到KeyguardViewMediator的keyguardDone(boolean, boolean) 进行后续的流程(如转到Launcher桌面)。
解锁界面布局在LockScreen类的构造函数中进行,LockScreen构造函数内容如下:LockScreen(Context context, Configuration configuration, LockPatternUtils lockPatternUtils,&&&&&&&&&&&&KeyguardUpdateMonitor updateMonitor,&&&&&&&&&&&&KeyguardScreenCallback callback) {&&&&&&&&super(context);&&&&&&&&mLockPatternUtils = lockPatternUtils;&&&&&&&&mUpdateMonitor = updateMonitor;&&&&&&&&mCallback = callback;&&&&&&&&mEnableMenuKeyInLockScreen = shouldEnableMenuKey();&&&&&&&&mCreationOrientation = configuration.orientation;&&&&&&&&mKeyboardHidden = configuration.hardKeyboardHidden;&&&&&&&&if (LockPatternKeyguardView.DEBUG_CONFIGURATION) {&&&&&&&&&&&&Log.v(TAG, "***** CREATING LOCK SCREEN", new RuntimeException());&&&&&&&&&&&&Log.v(TAG, "Cur orient=" + mCreationOrientation&&&&&&&&&&&&&&&&&&&&+ " res orient=" + context.getResources().getConfiguration().orientation);&&&&&&&&}&&&&&&&&final LayoutInflater inflater = LayoutInflater.from(context);&&&&&&&&if (DBG) Log.v(TAG, "Creation orientation = " + mCreationOrientation);&&&&&&&&if (mCreationOrientation != Configuration.ORIENTATION_LANDSCAPE) {&&&&&&&&&&&&inflater.inflate(R.layout.keyguard_screen_tab_unlock, this, true);&&&&&&&&} else {&&&&&&&&&&&&inflater.inflate(R.layout.keyguard_screen_tab_unlock_land, this, true);&&&&&&&&}&&&&&&&&mStatusViewManager = new KeyguardStatusViewManager(this, mUpdateMonitor, mLockPatternUtils,&&&&&&&&&&&&&&&&mCallback, false);&&&&&&&&setFocusable(true);&&&&&&&&setFocusableInTouchMode(true);&&&&&&&&setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);&&&&&&&&mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);&&&&&&&&mSilentMode = isSilentMode();&&&&&&&&mUnlockWidget = findViewById(R.id.unlock_widget);&&&&&&&&if (mUnlockWidget instanceof SlidingTab) {&&&&&&&&&&&&SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;&&&&&&&&&&&&slidingTabView.setHoldAfterTrigger(true, false);&&&&&&&&&&&&slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);&&&&&&&&&&&&slidingTabView.setLeftTabResources(&&&&&&&&&&&&&&&&&&&&R.drawable.ic_jog_dial_unlock,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_target_green,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_bar_left_unlock,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_left_unlock);&&&&&&&&&&&&SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);&&&&&&&&&&&&slidingTabView.setOnTriggerListener(slidingTabMethods);&&&&&&&&&&&&mUnlockWidgetMethods = slidingTabMethods;&&&&&&&&} else if (mUnlockWidget instanceof WaveView) {&&&&&&&&&&&&WaveView waveView = (WaveView) mUnlockWidget;&&&&&&&&&&&&WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);&&&&&&&&&&&&waveView.setOnTriggerListener(waveViewMethods);&&&&&&&&&&&&mUnlockWidgetMethods = waveViewMethods;&&&&&&&&} else if (mUnlockWidget instanceof MultiWaveView) {&&&&&&&&&&&&MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;&&&&&&&&&&&&MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);&&&&&&&&&&&&multiWaveView.setOnTriggerListener(multiWaveViewMethods);&&&&&&&&&&&&mUnlockWidgetMethods = multiWaveViewMethods;&&&&&&&&} else {&&&&&&&&&&&&throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);&&&&&&&&}&&&&&&&&// Update widget with initial ring state&&&&&&&&mUnlockWidgetMethods.updateResources(context);&&&&&&&&if (DBG) Log.v(TAG, "*** LockScreen accel is "&&&&&&&&&&&&&&&&+ (mUnlockWidget.isHardwareAccelerated() ? "on":"off"));&&&&}
通过添加打印发现在480分辨率下采用的Layout文件为\layout-sw480dp\keyguard_screen_tab_unlock_land.xml,此文件的内容如下:<?xml version="1.0" encoding="utf-8"?><!--**** Copyright 2009, The Android Open Source Project**** Licensed under the Apache License, Version 2.0 (the "License")** you may not use this file except in compliance with the License.** You may obtain a copy of the License at****
http://www.apache.org/licenses/LICENSE-2.0**** Unless required by applicable law or agreed to in writing, software** distributed under the License is distributed on an "AS IS" BASIS,** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.** See the License for the specific language governing permissions and** limitations under the License.*/--><!-- This is the general lock screen which shows information about the&&state of the device, as well as instructions on how to get past it&&depending on the state of the device.--><LinearLayout xmlns:android="/apk/res/android"&&&&xmlns:tabunlock="/apk/res/com.android.tabunlock"&&&&android:layout_width="match_parent"&&&&android:layout_height="match_parent"&&&&android:orientation="horizontal"&&&&android:id="@+id/root">&&&&<!-- left side: status and music -->&&&&<RelativeLayout&&&&&&&&android:layout_height="match_parent"&&&&&&&&android:layout_weight="1"&&&&&&&&android:layout_width="0dip"&&&&&&&&android:gravity="center">&&&&&&&&<RelativeLayout android:id="@+id/transport_bg_protect"&&&&&&&&&&&&android:layout_width="512dip"&&&&&&&&&&&&android:layout_height="wrap_content">&&&&&&&&&&&&<!-- Music transport control underneath -->&&&&&&&&&&&&<include android:id="@+id/transport"&&&&&&&&&&&&&&&&layout="@layout/keyguard_transport_control"&&&&&&&&&&&&&&&&android:layout_row="0"&&&&&&&&&&&&&&&&android:layout_column="0"&&&&&&&&&&&&&&&&android:layout_rowSpan="3"&&&&&&&&&&&&&&&&android:layout_columnSpan="1"&&&&&&&&&&&&&&&&android:layout_gravity="fill"&&&&&&&&&&&&&&&&android:layout_width="match_parent"&&&&&&&&&&&&&&&&android:layout_height="512dip"&&&&&&&&&&&&&&&&/>&&&&&&&&&&&&<include layout="@layout/keyguard_screen_status_land"&&&&&&&&&&&&&&&&android:layout_width="match_parent"&&&&&&&&&&&&&&&&android:layout_height="wrap_content"&&&&&&&&&&&&&&&&android:layout_marginLeft="50dip"&&&&&&&&&&&&&&&&android:layout_marginTop="50dip"&&&&&&&&&&&&&&&&android:layout_marginBottom="82dip"&&&&&&&&&&&&&&&&android:layout_marginRight="64dip"&&&&&&&&&&&&&&&&android:layout_alignParentTop="true"&&&&&&&&&&&&&&&&android:layout_alignParentLeft="true"/>&&&&&&&&</RelativeLayout>&&&&</RelativeLayout>&&&&<!-- right side -->&&&&<RelativeLayout&&&&&&&&android:layout_height="match_parent"&&&&&&&&android:layout_weight="1"&&&&&&&&android:layout_width="0dip"&&&&&&&&android:gravity="center_horizontal|center_vertical">&&&&&&&&<TextView&&&&&&&&&&&&android:id="@+id/screenLocked"&&&&&&&&&&&&android:layout_width="wrap_content"&&&&&&&&&&&&android:layout_height="wrap_content"&&&&&&&&&&&&android:textAppearance="?android:attr/textAppearanceMedium"&&&&&&&&&&&&android:gravity="center"&&&&&&&&&&&&android:layout_marginTop="12dip"&&&&&&&&&&&&android:layout_alignParentLeft="true"&&&&&&&&&&&&android:layout_alignParentTop="true"&&&&&&&&&&&&android:drawablePadding="4dip"/>&&&&&&&&<com.android.internal.widget.multiwaveview.MultiWaveView&&&&&&&&&&&&android:id="@+id/unlock_widget"&&&&&&&&&&&&android:layout_width="match_parent"&&&&&&&&&&&&android:layout_height="match_parent"&&&&&&&&&&&&android:layout_rowSpan="7"&&&&&&&&&&&&android:layout_gravity="center_vertical|center_horizontal"&&&&&&&&&&&&android:targetDrawables="@array/lockscreen_targets_with_camera"&&&&&&&&&&&&android:targetDescriptions="@array/lockscreen_target_descriptions_with_camera"&&&&&&&&&&&&android:directionDescriptions="@array/lockscreen_direction_descriptions"&&&&&&&&&&&&android:handleDrawable="@drawable/ic_lockscreen_handle"&&&&&&&&&&&&android:waveDrawable="@drawable/ic_lockscreen_outerring"&&&&&&&&&&&&android:outerRadius="@dimen/multiwaveview_target_placement_radius"&&&&&&&&&&&&android:snapMargin="@dimen/multiwaveview_snap_margin"&&&&&&&&&&&&android:hitRadius="@dimen/multiwaveview_hit_radius"&&&&&&&&&&&&android:rightChevronDrawable="@drawable/ic_lockscreen_chevron_right"&&&&&&&&&&&&android:feedbackCount="3"&&&&&&&&&&&&android:vibrationDuration="20"&&&&&&&&&&&&android:horizontalOffset="0dip"&&&&&&&&&&&&android:verticalOffset="0dip"&&&&&&&&/>&&&&&&&&<!-- emergency call button shown when sim is PUKd and tab_selector is hidden -->&&&&&&&&<Button&&&&&&&&&&&&android:id="@+id/emergencyCallButton"&&&&&&&&&&&&android:layout_width="wrap_content"&&&&&&&&&&&&android:layout_height="wrap_content"&&&&&&&&&&&&android:layout_marginRight="80dip"&&&&&&&&&&&&android:layout_marginBottom="80dip"&&&&&&&&&&&&android:layout_alignParentRight="true"&&&&&&&&&&&&android:layout_alignParentBottom="true"&&&&&&&&&&&&android:drawableLeft="@drawable/ic_emergency"&&&&&&&&&&&&style="@style/Widget.Button.Transparent"&&&&&&&&&&&&android:drawablePadding="8dip"&&&&&&&&&&&&android:visibility="gone"/>&&&&</RelativeLayout>></LinearLayout>&& 从文件中可以看出,解锁界面的数字时钟、充电状态、波纹解锁等控件均在其中布局,对解锁控件的大小修改也是通过修改该文件进行的。
对于Android4.0默认的LockScreen,采用的是MultiWaveView控件,LockScreen中创建该控件的代码如下:mUnlockWidget = findViewById(R.id.unlock_widget);&&&&&&&&if (mUnlockWidget instanceof SlidingTab) {&&&&&&&&&&&&SlidingTab slidingTabView = (SlidingTab) mUnlockWidget;&&&&&&&&&&&&slidingTabView.setHoldAfterTrigger(true, false);&&&&&&&&&&&&slidingTabView.setLeftHintText(R.string.lockscreen_unlock_label);&&&&&&&&&&&&slidingTabView.setLeftTabResources(&&&&&&&&&&&&&&&&&&&&R.drawable.ic_jog_dial_unlock,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_target_green,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_bar_left_unlock,&&&&&&&&&&&&&&&&&&&&R.drawable.jog_tab_left_unlock);&&&&&&&&&&&&SlidingTabMethods slidingTabMethods = new SlidingTabMethods(slidingTabView);&&&&&&&&&&&&slidingTabView.setOnTriggerListener(slidingTabMethods);&&&&&&&&&&&&mUnlockWidgetMethods = slidingTabMethods;&&&&&&&&} else if (mUnlockWidget instanceof WaveView) {&&&&&&&&&&&&WaveView waveView = (WaveView) mUnlockWidget;&&&&&&&&&&&&WaveViewMethods waveViewMethods = new WaveViewMethods(waveView);&&&&&&&&&&&&waveView.setOnTriggerListener(waveViewMethods);&&&&&&&&&&&&mUnlockWidgetMethods = waveViewMethods;&&&&&&&&} else if (mUnlockWidget instanceof MultiWaveView) {&&&&&&&&&&&&MultiWaveView multiWaveView = (MultiWaveView) mUnlockWidget;&&&&&&&&&&&&MultiWaveViewMethods multiWaveViewMethods = new MultiWaveViewMethods(multiWaveView);&&&&&&&&&&&&multiWaveView.setOnTriggerListener(multiWaveViewMethods);&&&&&&&&&&&&mUnlockWidgetMethods = multiWaveViewMethods;&&&&&&&&} else {&&&&&&&&&&&&throw new IllegalStateException("Unrecognized unlock widget: " + mUnlockWidget);&&&&&&&&}
这是LockScreen的构造函数中的代码,函数根据R.id.unlock_widget定义的类型选择不同的控件类,其中第一种是Android2.3的滑动解锁类,第二种的简单的波纹解锁类,第三种才是我们使用的MultiWaveView类,函数并创建了一个MultiWaveViewMethods类,这个类实际上是为了更好地使用而进行的封装,它的代码如下:class MultiWaveViewMethods implements MultiWaveView.OnTriggerListener,&&&&&&&&&&&&UnlockWidgetCommonMethods {&&&&&&&&private final MultiWaveView mMultiWaveView;&&&&&&&&private boolean mCameraDisabled;&&&&&&&&MultiWaveViewMethods(MultiWaveView multiWaveView) {&&&&&&&&&&&&mMultiWaveView = multiWaveView;&&&&&&&&&&&&final boolean cameraDisabled = mLockPatternUtils.getDevicePolicyManager()&&&&&&&&&&&&&&&&&&&&.getCameraDisabled(null);&&&&&&&&&&&&if (cameraDisabled) {&&&&&&&&&&&&&&&&Log.v(TAG, "Camera disabled by Device Policy");&&&&&&&&&&&&&&&&mCameraDisabled = true;&&&&&&&&&&&&} else {&&&&&&&&&&&&&&&&// Camera is enabled if resource is initially defined for MultiWaveView&&&&&&&&&&&&&&&&// in the lockscreen layout file&&&&&&&&&&&&&&&&mCameraDisabled = mMultiWaveView.getTargetResourceId()&&&&&&&&&&&&&&&&&&&&&&&&!= R.array.lockscreen_targets_with_camera;&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public void updateResources() {&&&&&&&&&&&&int resId;&&&&&&&&&&&&if (mCameraDisabled) {&&&&&&&&&&&&&&&&// Fall back to showing ring/silence if camera is disabled by DPM...&&&&&&&&&&&&&&&&resId = mSilentMode ? R.array.lockscreen_targets_when_silent&&&&&&&&&&&&&&&&&&&&: R.array.lockscreen_targets_when_soundon;&&&&&&&&&&&&} else {&&&&&&&&&&&&&&&&resId = R.array.lockscreen_targets_with_camera;&&&&&&&&&&&&}&&&&&&&&&&&&mMultiWaveView.setTargetResources(resId);&&&&&&&&}&&&&&&&&public void onGrabbed(View v, int handle) {&&&&&&&&}&&&&&&&&public void onReleased(View v, int handle) {&&&&&&&&}&&&&&&&&public void onTrigger(View v, int target) {&&&&&&&&&&&&if (target == 0 || target == 1) { // 0 = unlock/portrait, 1 = unlock/landscape&&&&&&&&&&&&&&&&mCallback.goToUnlockScreen();&&&&&&&&&&&&} else if (target == 2 || target == 3) { // 2 = alt/portrait, 3 = alt/landscape&&&&&&&&&&&&&&&&if (!mCameraDisabled) {&&&&&&&&&&&&&&&&&&&&// Start the Camera&&&&&&&&&&&&&&&&&&&&Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);&&&&&&&&&&&&&&&&&&&&intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);&&&&&&&&&&&&&&&&&&&&mContext.startActivity(intent);&&&&&&&&&&&&&&&&&&&&mCallback.goToUnlockScreen();&&&&&&&&&&&&&&&&} else {&&&&&&&&&&&&&&&&&&&&toggleRingMode();&&&&&&&&&&&&&&&&&&&&mUnlockWidgetMethods.updateResources();&&&&&&&&&&&&&&&&&&&&mCallback.pokeWakelock();&&&&&&&&&&&&&&&&}&&&&&&&&&&&&}&&&&&&&&}&&&&&&&&public void onGrabbedStateChange(View v, int handle) {&&&&&&&&&&&&// Don't poke the wake lock when returning to a state where the handle is&&&&&&&&&&&&// not grabbed since that can happen when the system (instead of the user)&&&&&&&&&&&&// cancels the grab.&&&&&&&&&&&&if (handle != MultiWaveView.OnTriggerListener.NO_HANDLE) {&&&&&&&&&&&&&&&&mCallback.pokeWakelock();&&&&&&&&&&&&}&&&&&&&&}这个类有两个方法特别重要,一个是更新MultiWaveView的资源,即public void updateResources(),另一个是对解锁后的响应,即public void onTrigger(View
v, int target),这方法传入的第二个参数为解锁选择的图标编号,图标是从右向左逆时针编号的,即最右边的图标编号为0,在此函数中即可进行解锁的处理,选择是进入主界面还是启动其他的Activity。Android4.0默认target = 0对应的是进入主界面,
target = 2或者target = 3启动Camera,其解锁界面的图标是每次都是使用固定的资源,在完成解锁后按下Power键或者系统再次进入锁定状态,LockScreen都会再构造一次,会重新布局并加载资源,因此可以使每次解锁界面都不一样。
在Android中可以通过ActivityManager获取到最近运行的Activity,详细的用法如下:
),返回ActivityManager.RecentTaskInfo对象,其定义如下:
其中的baseIntent为启动最近运行任务的Intent,通过它我们可以很方便地获取Activity的图标并启动最近运行的Activity。
相关的代码如下:
2.1.1.获取Activity图标的方法
通过PackManager我们可以很方便地获取到Activity的图标,对应的代码如下:
这个文件中包含了大量Android中的配置信息,其中也有和显示分辨率相关的,修改的方法如下:
1.通过ADB将文件获取到主机任意文件夹。
2.用编辑软件打开build.prop,找到如下行
修改为=160或者直接删除掉这一行(这样就使用默认160)。
修改以下位置的源文件:
重载setTargetResources方法,重载后的方法如下:public void setTargetResources(ArrayList<Drawable> drawables)&&&&&{&&&&&&&Resources res = getContext().getResources();&&&&&&&int count = drawables.size();&&&&&&&ArrayList<TargetDrawable> targetDrawables = new ArrayList<TargetDrawable>(count);&&&&&&&&for (int i = 0; i < count; i++) {&&&&&&&&&&&&Drawable drawable = drawables.get(i);&&&&&&&&&&&&targetDrawables.add(new TargetDrawable(res, drawable));&&&&&&&&&&&&&&Log.v(TAG,"Add a Drawable");&&&&&&&&}&&&&&&&&mTargetDrawables = targetDrawables;&&&&&&&&updateTargetPositions();&&&&&}重载后的方法支持直接传入图片链表。这个方法是提供给LockScreen调用的
重载其中的MultiWaveViewMethods类的updateResources方法,重载后的方法如下:public void updateResources(Context context)
&&&&&&&&&{
&&&&&&&&&&&&&&ArrayList<Drawable> drawableAl = new ArrayList();&&&&&&&&&&&&&&final ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
&&&&&&&&&&&&&&final PackageManager pm = context.getPackageManager();
&&&&&&&&&&&&&&drawableAl.add(getView().getResources().getDrawable(R.drawable.ic_lockscreen_unlock));&&&&&&&&&&&&&&List<ActivityManager.RecentTaskInfo> recentLs = am.getRecentTasks(7, ActivityManager.RECENT_IGNORE_UNAVAILABLE);&&&&&&&&&&&&&&for(int i=0;i<recentLs.size();i++)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&try&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&drawableAl.add(pm.getActivityIcon(recentLs.get(i).baseIntent));&&&&&&&&&&&&&&&&&&&&&&&mIntentList.add(recentLs.get(i).baseIntent);&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&catch(Exception e)&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&Log.v(TAG,"Catch Exception");&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&&&&&&&mMultiWaveView.setTargetResources(drawableAl);&&&&&&&&&}重载后的updateResources函数实际上先获取最近运行的任务列表,再获取任务图标,最后用获取的图标设置MultiWaveView控件。
修改解锁响应onTigger:public void onTrigger(View v, int target) {&&&&&&&&&&&&&&Log.v(TAG,"onTrigger = " + target);&&&&&&&&&&&&&&if(target ==0)&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&mCallback.goToUnlockScreen();&&&&&&&&&&&&&&}&&&&&&&&&&&&&&else&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&if(mIntentList.get(target-1)!=null)&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&Intent intent = mIntentList.get(target-1);&&&&&&&&&&&&&&&&&&&&&&&mContext.startActivity(intent);&&&&&&&&&&&&&&&&&&&&&&&mCallback.goToUnlockScreen();&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&}&&&&&&&&}这样解锁事件的响应被修改成0号图标解锁,其余启动对应的Activity。
启动应用程序的功能实现了,但是解锁圆圈的大小还是太大,特别是在更改dpi之后,圆圈几乎占据了半个显示屏,显得并不雅观。
实际上,解锁圆圈的资源就是/framework/cors/res/res/drawable-xxx中的unlock_ring.png,对于不同分辨率的设备,会采用不同的大小。我们可以通过修改位图的大小来进行更改,但在实际测试中修改了所有的unlock_ring.png,也未见解锁图标变小。
&&& 决定采用代码配合更改图案大小的功能,如图:
mOuterRing为外圆圈的资源,mOuterRadius为解锁圆圈的活动半径,修改代码后直接从图片获取,这样将采用drawable-sw480dp-mdpi下的图片,通过PhotoShop等软件将圆圈图片缩小,最终显示出的圆圈就变小了。
屏幕的知识(摘自网上)&
density表示每英寸有多少个显示点(逻辑值),它的单位是dpi:dot per inch,通常屏幕大时,density就大,屏幕小时,density就小,通常:
屏幕实际分辨率为240px*400px时,density=120
屏幕实际分辨率为320px*533px,density=160
屏幕实际分辨率为480px*800px,density=240
是整个屏是多少点,比如800x480,它是软件的显示单位,实际上会因为不同的显示屏的像素大小不同,造成density不同。
res/xxx-hdpi&&&&&&&&& 当density为240时,使用此目录下的资源
res/xxx-mdpi&&&&&&&&& 当density为160时,使用此目录下的资源
res/xxx-ldpi&&&&&&&&& 当density为120时,使用此目录下的资源
res/xxx&&&&&&&&&&&&&&& 不常后缀,为默认设置,同xxx-mdpi
文件中定义大小的单位)
a)dp=dip=dx (Density independent pixel)
基于屏幕密度的抽象单位,设备无关的点,用于说明与密度无关的尺寸和位置。这些单位是相对于一个160dpi的屏幕,所有一个dp是160dpi屏幕上的一个点。
b)px (Pixel)
px指软件的单位点,设备相关的点
public static String getDisplayMetrics(Context cx) {&&String str = "";&&DisplayMetrics dm = new DisplayMetrics();&&dm = cx.getApplicationContext().getResources().getDisplayMetrics();&&int screenWidth = dm.widthPixels;&&int screenHeight = dm.heightPixels;&&float density = dm.density;&&float xdpi = dm.xdpi;&&float ydpi = dm.ydpi;&&str += "The absolute width:" + String.valueOf(screenWidth) + "pixels\n";&&str += "The absolute heightin:" + String.valueOf(screenHeight)&&&&&&+ "pixels\n";&&str += "The logical density of the display.:" + String.valueOf(density)&&&&&&+ "\n";&&str += "X dimension :" + String.valueOf(xdpi) + "pixels per inch\n";&&str += "Y dimension :" + String.valueOf(ydpi) + "pixels per inch\n";&&return str;}TextView tv1;@Overrideprotected void onCreate(Bundle savedInstanceState) {&&super.onCreate(savedInstanceState);&&setContentView(R.layout.layout_test2);&&tv1 = (TextView) findViewById(R.id.TextView01);&&tv1.post(new Runnable(){&&&&public void run()&&&&{&&&&&&processLayout();&&&&}&&});}private void processLayout(){&&Rect rect= new Rect();&&Window window= getWindow();&&tv1.getWindowVisibleDisplayFrame(rect);&&//状态栏高度&&int statusBarHeight= rect.top;&&int contentViewTop= window.findViewById(Window.ID_ANDROID_CONTENT).getTop();&&//标题栏高度&&int titleBarHeight= contentViewTop - statusBarHeight;&&//测试结果:ok之后 100多 ms 才运行了&&Log.v("test", "=-init-= statusBarHeight="+statusBarHeight+&&" contentViewTop="+contentViewTop+&&" titleBarHeight="+titleBarHeight);
&&& 也算是费了一些功夫,总算是把First Task完成得差不多了,毕业一年以来都是在做WinCE驱动,虽然在大学里面学过一点Linux的知识,但是初次转到Android还是有点不适应,好在有网络这个好东西,Android学习才不是那么难,但是感觉也不能太依靠网络。从长期来看,在消费电子这一块,智能系统的进化将会越来越快,这对我等的考验会越来越大。但是当今世界就是一个不断学习的世界,今后要多把自己的学习总结出来,这样进步才会更快。
阅读(20465) | 评论(12) | 转发(4) |
相关热门文章
给主人留下些什么吧!~~
楼主太不给力了,等我做完了 也没回复我
在一个是还没搞清楚他的图片是如何加载上去的?是通过TargetDrawable来实现的么?另外参考了launcher上的未读短信的设计,但是还没看懂,他哪个是否具有参考的价值
lz,你好,我研究了这解锁好几天,想增加一个短信解锁和电话解锁,同时要增加未读短信和未接电话的条数,该如何来修改这自定义控件?如果方便的话通过email交流,我的email是,相当的感谢
如果大哥有时间 麻烦指点下。
小弟我弄了代码,一个人弄。感觉很多迷茫
有个疑问了,原代码是解锁界面是一个CAM按钮一个解锁按钮,我在onTrigger 把cam 的intent 修改掉,指向ACTION_CALL_BUTTON。然后模拟器的动作就是崩溃,是不是我没有添加权限?还是别的原因
请登录后评论。

我要回帖

更多关于 业务逻辑实现 的文章

 

随机推荐