一个服务如何监听触摸手势/事件?

我想知道像SwipePad和Wave Launcher这样的应用程序能够通过服务来检测触摸手势/事件。 这些应用程序即使不在自己的Activity中,也能够检测到触摸手势。 我已经遍布互联网,并没有find他们如何做到这一点。

我的主要问题是一个服务如何监听客户端/事件,就像一个普通的Activity可能会接收到MotionEvent,即使它不在原来的Activity或context中。 我基本上正在尝试构build一个应用程序,它将识别来自用户的特定触摸手势,而不pipe哪个活动位于顶部,并在该手势被识别时执行某些操作。 触摸重算将作为一个服务在后台运行的线程。

我有同样的问题,我终于明白了! 感谢这篇文章: 创build一个系统覆盖窗口(总是在最上面) 。 您需要使用警报窗口而不是叠加层(这也意味着您可以在Andoid ICS中使用它):

WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL|WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, PixelFormat.TRANSLUCENT); 

然后以这种方式附加一个GestureListener:

 GestureDetector gestureDetector = new GestureDetector(this, new AwesomeGestureListener()); View.OnTouchListener gestureListener = new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { return gestureDetector.onTouchEvent(event); } }; overlayView.setOnTouchListener(gestureListener); 

好极了!

有趣的问题。 我不知道他们是怎么做到的,我发现谷歌的post告诉我,没有全球触摸监听器。 但我有一个想法反正…

我发现这个职位的人成功显示一个服务的popupwindow。 如果我将popup透明和全屏,我敢肯定,我可以捕捉触摸,因为我被允许设置一个触摸拦截器 。

编辑 :请尝试,请报告结果,将有趣的知道这是否工作…

我在API 21和nexus 5上testing了这一点,并且当系统触发一个触摸事件时,我可以从服务中logging下来。 但是,MotionEvent对象中的数据(例如坐标)在OUTSIDE看起来是我的应用程序包时返回0.0。

两个来源整合 , 权限

我很好奇,为什么event.getX(),event.getY()和event.getPressure()返回0.0,而不是在服务所在的应用程序的活动。

编辑

这个解决scheme不会阻止其他听众接收由于该服务而受到的触摸事件

 public boolean onTouch(View v, MotionEvent e){ Log.d(LOG_TAG, "Touch event captured"); return false; 

通过返回false,它允许其他听众接收事件。

EDIT2

显然,如果当前活动和监听器不共享UID,操作系统中的input调度器将把坐标和压力设置为0,这里是源代码

我testing了一切可能的解决scheme,但没有任何工作,有些没有触发事件,他们冻结了屏幕。

所以我做了一些逆向工程,现在发布解决scheme

  WindowManager.LayoutParams params = new android.view.WindowManager.LayoutParams(0, 0, 0, 0, 2003, 0x40028, -3); View mView = new View(this); mView.setOnTouchListener(this); WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE); wm.addView(mView, params);