2011-07-15 15 views
58

Me pregunto cómo aplicaciones como SwipePad y Wave Launcher son capaces de detectar gestos táctiles/eventos simplemente a través de un servicio. Estas aplicaciones pueden detectar gestos táctiles aunque no estén en su propia Actividad. He buscado en Internet y no he encontrado cómo pueden hacerlo.¿Cómo puede un servicio escuchar gestos/eventos táctiles?

Mi pregunta principal es cómo un servicio puede escuchar eventos/invitaciones táctiles de la misma forma que una actividad normal puede recibir MotionEvents aunque no esté en la actividad o el contexto original. Básicamente estoy intentando construir una aplicación que reconfigure un gesto táctil particular de un usuario sin importar qué Actividad esté en la parte superior y haga algo cuando ese gesto sea reconcidado. La recontextualización táctil será un hilo ejecutándose en segundo plano como un servicio.

+1

SwipePad parece que podría usar ventanas de alerta de sistema transparentes para las áreas tocables en lugar de la pantalla completa. – Sam

Respuesta

5

Interesante pregunta. No sé cómo lo hicieron y encontré publicaciones en el grupo de Google que me dicen que no hay un oyente táctil global. Pero tengo una idea de todos modos ...

Encontré this post donde alguien tiene éxito para mostrar una ventana emergente de un servicio. Si quisiera que esa ventana emergente fuera transparente y de pantalla completa, estoy seguro de que podría capturar los toques, ya que puedo configurar touch interceptor.

Editar: Por favor, informar de los resultados al intentar eso, sería interesante saber si esto funciona ...

+0

Esto parece un método interesante. He visto que PopupWindows se usaba antes para cosas similares, pero tendré que intentarlo. Por el momento, me siento frustrado por lo difícil que es obtener eventos táctiles de un servicio. Pasará un tiempo antes de que tenga la oportunidad de probar esto, ¡pero les contaré cómo funciona! – Brian

+0

Acabo de probar esto, y ni siquiera pude obtener el cuadro de diálogo de alerta para mostrar. El método 'show' arrojó una' BadTokenException'. – Sam

+0

El mensaje de excepción es 'No se puede agregar ventana; el token null no es válido; ¿se está ejecutando tu actividad? ' – Sam

18

tenía este mismo problema y al final me he dado cuenta que fuera! Gracias a esta publicación: Creating a system overlay window (always on top). Es necesario utilizar una ventana de alerta en lugar de una superposición (y esto también significa que se puede utilizar en 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); 

A continuación, sólo adjuntar un GestureListener de esta manera:

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); 

Yay!

+0

Esto interferirá con la capacidad de los usuarios de hacer clic en los botones de la actividad que creen que están viendo – ChuckKelly

+0

@ChuckKelly sí interferirá –

+3

Estoy tratando de escuchar los grifos de un servicio, el servicio se adjunta con una Actividad. La actividad se usa como de costumbre, pero el servicio sigue registrando los grifos. cuando se utiliza TYPE_SYSTEM_OVERLAY funciona muy bien en Android 2.3 pero en 4.1 no se invoca onTouchEvent. Cuando se utiliza TYPE_SYSTEM_ALERT onTouchEvent se invoca, pero el evento táctil no se pasa a la actividad y deja de responder. Por favor, ayuda –

2

Probé todas las soluciones posibles, pero no funcionó nada, no funcionó el evento táctil que congelaron la pantalla.

Así que he hecho un poco de ingeniería inversa y la solución ahora publicar que trabaja

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); 
+0

Esto parece estar funcionando solo para la primera vista/actividad. No para actividades subsecuentes creadas. Recibo la siguiente advertencia: W/ViewRootImpl: evento de caída debido a que no hay foco en la ventana: MotionEvent {action = ACTION_OUTSIDE, actionButton = 0, id [0] = 0, x [0] = 0.0, y [0] = 0.0, toolType [0] = TOOL_TYPE_FINGER, buttonState = 0, metaState = 0, flags = 0x0, edgeFlags = 0x0, pointerCount = 1, historySize = 0, eventTime = 220247332, downTime = 220247332, deviceId = 4, source = 0x1002} –

3

He probado esto en API 21 y un nexo entre 5 y yo era capaz de iniciar sesión, de un servicio, cuando se disparó un evento táctil por el sistema. Sin embargo, los datos dentro del objeto MotionEvent, por ejemplo las coordenadas, devuelven 0.0 cuando está FUERA de lo que parece ser el paquete de mi aplicación.

Dos fuentes integration, permission

Soy curioso en cuanto a por qué el event.getX(), event.getY() y event.getPressure() 0.0 regresan cuando no esté en una actividad de la aplicación donde vive el servicio

Editar

Esta solución no impide que otros oyentes de recibir el evento táctil capured por el servicio debido a

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

Al devolver falsa, que permite a otros oyentes reciban el evento.

Edit2

Al parecer, el despachador de entrada en el sistema operativo va a establecer las coordenadas y la presión a 0 si la actividad actual y el oyente no comparten un UID, aquí es source

+0

¿lo ve? una forma de evitar esto? como cambiar el UID dinámicamente? – keinabel

+0

A menos que tenga su propio sistema operativo, no creo que sea posible. ¿Tal vez si el servicio está registrado como un servicio del sistema? Quiero decir que los valores están ahí, pero el sistema operativo eliminará los valores de interés y propagará el evento táctil a cualquier otro oyente. – Clocker

Cuestiones relacionadas