Android home和back事件处理
本文基于Android 7.0
在Android系统中,back键事件是有app自己处理的,而home是系统全局处理事件,因为在任何app界面,按下home结果都是一样的回到launcher。
先看下back事件
back键处理
- Native层 –> ViewRootImpl层 –> DecorView层 –> Activity层 –> ViewGroup层 –> View层
从ViewRootImpl层开始看下back事件
frameworks/base/core/java/android/view/ViewRootImpl.java
private int processKeyEvent(QueuedInputEvent q) {final KeyEvent event = (KeyEvent)q.mEvent;// Deliver the key to the view hierarchy.if (mView.dispatchKeyEvent(event)) {return FINISH_HANDLED;}...return FORWARD;}
这里的mView是DecorView,直接调用DecorView的dispatchKeyEvent分发事件
frameworks/base/core/java/com/android/internal/policy/DecorView.java
public boolean dispatchKeyEvent(KeyEvent event) {...if (!mWindow.isDestroyed()) {final Window.Callback cb = mWindow.getCallback();final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event): super.dispatchKeyEvent(event);if (handled) {return true;}}...}
分发back事件时mWindow还玩destroy,因此会调用Callback的dispatchKeyEvent分发,这里Callback为Activity。
frameworks/base/core/java/android/app/Activity.java
public boolean dispatchKeyEvent(KeyEvent event) {...return event.dispatch(this, decor != null? decor.getKeyDispatcherState() : null, this);}
调用了KeyEvent的dispatch继续分发
frameworks/base/core/java/android/view/KeyEvent.java
public final boolean dispatch(Callback receiver, DispatcherState state,Object target) {switch (mAction) {case ACTION_DOWN: {mFlags &= ~FLAG_START_TRACKING;if (DEBUG) Log.v(TAG, "Key down to " + target + " in " + state+ ": " + this);boolean res = receiver.onKeyDown(mKeyCode, this);if (state != null) {if (res && mRepeatCount == 0 && (mFlags&FLAG_START_TRACKING) != 0) {if (DEBUG) Log.v(TAG, " Start tracking!");state.startTracking(this, target);} else if (isLongPress() && state.isTracking(this)) {try {if (receiver.onKeyLongPress(mKeyCode, this)) {if (DEBUG) Log.v(TAG, " Clear from long press!");state.performedLongPress(this);res = true;}} catch (AbstractMethodError e) {}}}return res;}case ACTION_UP:if (DEBUG) Log.v(TAG, "Key up to " + target + " in " + state+ ": " + this);if (state != null) {state.handleUpEvent(this);}return receiver.onKeyUp(mKeyCode, this);case ACTION_MULTIPLE:final int count = mRepeatCount;final int code = mKeyCode;if (receiver.onKeyMultiple(code, count, this)) {return true;}if (code != KeyEvent.KEYCODE_UNKNOWN) {mAction = ACTION_DOWN;mRepeatCount = 0;boolean handled = receiver.onKeyDown(code, this);if (handled) {mAction = ACTION_UP;receiver.onKeyUp(code, this);}mAction = ACTION_MULTIPLE;mRepeatCount = count;return handled;}return false;}return false;}
主要看下ACTION_DOWN事件,这里receiver是activity。如果是长按,则会调用activity的onKeyLongPress
frameworks/base/core/java/android/app/Activity.java
public boolean onKeyLongPress(int keyCode, KeyEvent event) {return false;}
可以看到直接返回false,忽略掉的长按事件
frameworks/base/core/java/android/app/Activity.javapublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {if (getApplicationInfo().targetSdkVersion>= Build.VERSION_CODES.ECLAIR) {event.startTracking();} else {onBackPressed();}return true;}...}}
可以看到按下back键会调用onBackPressed()方法,该方法最终会调用到finish()方法。
frameworks/base/core/java/android/app/Activity.javapublic void onBackPressed() {if (mActionBar != null && mActionBar.collapseActionView()) {return;}if (!mFragments.getFragmentManager().popBackStackImmediate()) {finishAfterTransition();}}public void finishAfterTransition() {if (!mActivityTransitionState.startExitBackTransition(this)) {finish();}}
home事件
home事件是不经过app统一由系统处理的,在PhoneWindowManager端拦截掉了
frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
// First we always handle the home key here, so applications// can never break it, although if keyguard is on, we do let// it handle it, because that gives us the correct 5 second// timeout.
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
if (keyCode == KeyEvent.KEYCODE_HOME) {...// If we have released the home key, and didn't do anything else// while it was pressed, then it is time to go home!if (!down) {cancelPreloadRecentApps();mHomePressed = false;...handleShortPressOnHome();return -1;}...}
private void handleShortPressOnHome() {// Turn on the connected TV and switch HDMI input if we're a HDMI playback device.getHdmiControl().turnOnTv();// If there's a dream running then use home to escape the dream// but don't actually go home.if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {mDreamManagerInternal.stopDream(false /*immediate*/);return;}// Go home!launchHomeFromHotKey();}
launchHomeFromHotKey就回到launcher了。
Android home和back事件处理相关推荐
- Android开发之触摸事件处理机制详解
android触碰消息传递机制 用户的每次触碰(onClick,onLongClick,onScroll,etc.)都是由一个ACTION_DOWN+n个ACTION_MOVE+1个ACTION ...
- android 横向滑动事件,android左右手势滑动事件处理
建了个交流群:416157653,欢迎大家加入讨论 要实现手指在屏幕上左右滑动的事件需要实例化对象GestureDetector,new GestureDetector(MainActivity.th ...
- Android基于回调的事件处理
基于回调的事件处理模型更加简单: 如果说事件监听机制是一种委托式的事件处理,那么回调机制则恰好与之相反:对于基于回调的时间处理模型来说,事件源和事件监听器是统一的,或者说事件监听器完全消失了.当用户在 ...
- Android——基于监听器的事件处理(转)
事件,我们并不陌生! 所有的基于UI的应用程序,事件都变得不可或缺!试想一下,如果我们做的程序单击按钮和其它控件都没有反应,那么就如同一个人在这个世界上听不到声音一样! Android为我们提供了两种 ...
- Android开发2:事件处理及实现简单的对话框(Toast,AlertDialog,Snackbar,TextInputLayout的使用)...
前言 啦啦啦~又要和大家一起学习Android开发啦,博主心里好激动哒~ 在上篇博文中,我们通过线性布局和基础组件的使用,完成了一个简单的学生课外体育积分电子认证系统的界面,本篇博文,将和大家一起熟悉 ...
- android事件处理主要方法,详解Android的两种事件处理机制
UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...
- android Spinner点击事件处理
使用Spinner处理item的点击事件出现的错误 代码: spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() { ...
- Android的MotionEvent和事件处理
之前几篇文章我们讲解了自定义View和ViewGroup, 今天我们来看下View和ViewGroup常见的触摸事件和按键事件. MotionEvent MotionEvent对象是与用户触摸相关的时 ...
- Android中的Touch事件处理流程
1.当触摸屏幕时,最先执行的是Activity中的 public boolean dispatchTouchEvent (MotionEvent ev) { if (ev.g ...
最新文章
- 2021年春季学期-信号与系统-第五次作业参考答案-第十一移小题—MATLAB
- hibernate的实现原理
- php怎么改,php怎么修改图片
- (1-1)line-height的定义和行内框盒子模型
- ros(5)service client实现
- qq发文件大小上限_微信推出新功能!网友:终于不用转QQ了
- Mysql 电商常用的时间操作(当天,昨天,7天,30天,半年,全年,季度等等)...
- python编程100个小程序-(编程)10个Python练手小程序
- Java 多线程--- 创建线程、Thread类、synchronized
- Android书籍翻页效果需要用到的文件
- 《快速开发》通过Maven创建WebService项目Hello World!
- 转 linux shell 数组建立及使用技巧
- Kotlin 官方参考文档 中文版_kotlin-reference-chinese.pdf
- MySQL数据导出:ERROR 1 (HY000) 错误解决
- deprecated注释 原因
- 【U8】凭证上修改使用自定义项科目的辅助信息
- 用户如何制作360度全景图?360度全景图有什么用?
- golang学习(一)—— 简介
- 【论文翻译】PLOP: Learning without Forgetting for Continual Semantic Segmentation
- 触摸IC XTP2046 驱动笔记