本文基于Android 7.0

在Android系统中,back键事件是有app自己处理的,而home是系统全局处理事件,因为在任何app界面,按下home结果都是一样的回到launcher。

先看下back事件

back键处理

Android事件处理过程大致为
  • 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,忽略掉的长按事件

如果非长按,则会调用activity的onKeyDown
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事件处理相关推荐

  1. Android开发之触摸事件处理机制详解

     android触碰消息传递机制 用户的每次触碰(onClick,onLongClick,onScroll,etc.)都是由一个ACTION_DOWN+n个ACTION_MOVE+1个ACTION ...

  2. android 横向滑动事件,android左右手势滑动事件处理

    建了个交流群:416157653,欢迎大家加入讨论 要实现手指在屏幕上左右滑动的事件需要实例化对象GestureDetector,new GestureDetector(MainActivity.th ...

  3. Android基于回调的事件处理

    基于回调的事件处理模型更加简单: 如果说事件监听机制是一种委托式的事件处理,那么回调机制则恰好与之相反:对于基于回调的时间处理模型来说,事件源和事件监听器是统一的,或者说事件监听器完全消失了.当用户在 ...

  4. Android——基于监听器的事件处理(转)

    事件,我们并不陌生! 所有的基于UI的应用程序,事件都变得不可或缺!试想一下,如果我们做的程序单击按钮和其它控件都没有反应,那么就如同一个人在这个世界上听不到声音一样! Android为我们提供了两种 ...

  5. Android开发2:事件处理及实现简单的对话框(Toast,AlertDialog,Snackbar,TextInputLayout的使用)...

    前言 啦啦啦~又要和大家一起学习Android开发啦,博主心里好激动哒~ 在上篇博文中,我们通过线性布局和基础组件的使用,完成了一个简单的学生课外体育积分电子认证系统的界面,本篇博文,将和大家一起熟悉 ...

  6. android事件处理主要方法,详解Android的两种事件处理机制

    UI编程通常都会伴随事件处理,Android也不例外,它提供了两种方式的事件处理:基于回调的事件处理和基于监听器的事件处理. 对于基于监听器的事件处理而言,主要就是为Android界面组件绑定特定的事 ...

  7. android Spinner点击事件处理

    使用Spinner处理item的点击事件出现的错误 代码: spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() { ...

  8. Android的MotionEvent和事件处理

    之前几篇文章我们讲解了自定义View和ViewGroup, 今天我们来看下View和ViewGroup常见的触摸事件和按键事件. MotionEvent MotionEvent对象是与用户触摸相关的时 ...

  9. Android中的Touch事件处理流程

    1.当触摸屏幕时,最先执行的是Activity中的      public boolean dispatchTouchEvent (MotionEvent ev) {         if (ev.g ...

最新文章

  1. 2021年春季学期-信号与系统-第五次作业参考答案-第十一移小题—MATLAB
  2. hibernate的实现原理
  3. php怎么改,php怎么修改图片
  4. (1-1)line-height的定义和行内框盒子模型
  5. ros(5)service client实现
  6. qq发文件大小上限_微信推出新功能!网友:终于不用转QQ了
  7. Mysql 电商常用的时间操作(当天,昨天,7天,30天,半年,全年,季度等等)...
  8. python编程100个小程序-(编程)10个Python练手小程序
  9. Java 多线程--- 创建线程、Thread类、synchronized
  10. Android书籍翻页效果需要用到的文件
  11. 《快速开发》通过Maven创建WebService项目Hello World!
  12. 转 linux shell 数组建立及使用技巧
  13. Kotlin 官方参考文档 中文版_kotlin-reference-chinese.pdf
  14. MySQL数据导出:ERROR 1 (HY000) 错误解决
  15. deprecated注释 原因
  16. 【U8】凭证上修改使用自定义项科目的辅助信息
  17. 用户如何制作360度全景图?360度全景图有什么用?
  18. golang学习(一)—— 简介
  19. 【论文翻译】PLOP: Learning without Forgetting for Continual Semantic Segmentation
  20. 触摸IC XTP2046 驱动笔记

热门文章

  1. 暴雪娱乐-魔兽世界:地下城的环境艺术
  2. 【Swagger】 SrpingBoot整合Swagger
  3. 运营商开始悄悄火拼5G价格战,19元套餐开始涌现
  4. 斐讯n1盒子装网易音乐命令版
  5. 关于win10X64 连接oracle
  6. 怎么解决服务器延迟问题
  7. PR软件——音频变音(机器音)
  8. 幸福三月丨盐城北大青鸟女神节快乐!
  9. 微软Office Powerpoint双击打不开后的修复办法
  10. 关于pcl1.11.0无法找到 pcl/io/openni_grabber.h的解决办法