studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android events service touch gesture

para - manual de programacion android pdf



¿Cómo puede un servicio escuchar gestos/eventos táctiles? (5)

Me pregunto cómo aplicaciones como SwipePad y Wave Launcher son capaces de detectar gestos / eventos táctiles 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.

Mi pregunta principal es cómo un servicio puede escuchar eventos / invitaciones táctiles de la misma forma que una actividad normal puede recibir eventos de movimiento aunque no estén en la actividad o el contexto original. Básicamente, estoy intentando crear una aplicación que reconfigure un gesto táctil particular de un usuario independientemente de 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.


He buscado a través de muchos hilos SO, pero por razones de seguridad, no creo que esto sea posible para todos los paquetes en el sistema. Ciertamente es para tu propia aplicación.

WindowManager

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

Diseño flotante / superpuesto

floatyView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate (R.layout.floating_view, null); floatyView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.d(TAG, "event.x " + event.getX()); Log.d(TAG, "event.y " + event.getY()); if (event.getAction() == MotionEvent.ACTION_UP) { v.performClick(); } return false; } });

Diseño

<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:background="@android:color/transparent" android:layout_width="wrap_content" android:layout_height="wrap_content"/>


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é esta publicación 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 un interceptor táctil .

Editar : informa los resultados cuando lo intentes, sería interesante saber si esto funciona ...


Probé esto en API 21 y en un nexo 5 y pude iniciar sesión, desde un servicio, cuando el sistema activó un evento táctil. 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.

integration dos fuentes, permission

Tengo curiosidad por saber por qué event.getX (), event.getY () y event.getPressure () devuelven 0.0 cuando no está en una actividad de la aplicación donde vive el servicio.

Editar

Esta solución no evita que otros oyentes reciban el evento táctil captado por el servicio debido a

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

Al devolver falso, permite que otros oyentes reciban el evento.

Edit2

Aparentemente, el despachador de entrada en el SO configurará las coordenadas y la presión en 0 si la actividad actual y el oyente no comparten un UID, aquí está la source


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

Así que hice ingeniería inversa y ahora publico una solución que funciona

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


Tuve el mismo problema y finalmente lo descubrí. Gracias a esta publicación: Creación de una ventana de superposición del sistema (siempre en la parte superior) . Necesita usar una ventana de alerta en lugar de una superposición (y esto también significa que puede usarla 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);

Luego solo adjunte 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);

¡Hurra!