it-swarm.com.de

Wie kann ein Dienst auf Berührungsgesten/-ereignisse hören?

Ich frage mich, wie Apps wie SwipePad und Wave Launcher Berührungsgesten/-ereignisse einfach über einen Dienst erkennen können. Diese Apps können Berührungsgesten erkennen, auch wenn sie sich nicht in ihrer eigenen Aktivität befinden. Ich habe überall im Internet nachgesehen und nicht gefunden, wie sie das schaffen können. 

Meine Hauptfrage ist, wie ein Dienst bei Berührungen/Ereignissen mithören kann, genauso wie eine normale Aktivität MotionEvents erhalten kann, auch wenn sie sich nicht in der ursprünglichen Aktivität oder im ursprünglichen Kontext befindet. Ich versuche im Wesentlichen, eine App zu erstellen, die eine bestimmte Berührungsgeste eines Benutzers unabhängig von der Aktivität, die sich oben befindet, neu arrangiert und etwas tut, wenn diese Geste wieder verwendet wird. Die Touch-Recongition ist ein Thread, der als Dienst im Hintergrund ausgeführt wird.

60
Brian

Ich hatte das gleiche Problem und habe es endlich herausgefunden! Danke an diesen Beitrag: Erstellen eines System-Overlay-Fensters (immer oben) . Sie müssen ein Alarmfenster anstelle eines Overlays verwenden (und dies bedeutet auch, dass Sie es in Andoid ICS verwenden können):

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

Dann hängen Sie einfach einen GestureListener auf folgende Weise an:

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!

18
pypmannetjies

Interessante Frage. Ich weiß nicht, wie sie das gemacht haben, und ich habe Google-Gruppenpostings gefunden, die mir sagen, dass es keinen globalen Touch-Listener gibt. Aber ich habe sowieso eine Idee ...

Ich habe diesen Beitrag gefunden, wo es jemandem gelingt, ein Popup-Fenster von einem Dienst anzuzeigen. Wenn ich dieses Popup transparent und im Vollbildmodus machen würde, bin ich mir sicher, dass ich die Berührungen erfassen könnte, da ich einen touch interceptor einstellen darf.

Edit: Bitte melden Sie die Ergebnisse, wenn Sie das versuchen, wäre es interessant zu wissen, ob dies funktioniert ...

5
Knickedi

Ich habe jede mögliche Lösung getestet, aber nichts hat funktioniert. Einige haben kein Touch-Ereignis ausgelöst.

Also habe ich etwas Reverse Engineering gemacht und jetzt eine Lösung veröffentlicht, die funktioniert 

  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);
3
Mr Coder

Ich habe dies auf API 21 und einem Nexus 5 getestet und konnte mich von einem Dienst aus anmelden, wenn ein Berührungsereignis vom System ausgelöst wurde. Die Daten im MotionEvent-Objekt, z. B. Koordinaten, geben jedoch 0,0 zurück, wenn AUSSERHALB des scheinbar Pakets meiner App ist.

Zwei Quellen Integration , Genehmigung

Ich bin neugierig, warum event.getX (), event.getY () und event.getPressure () 0,0 zurückgeben, wenn sie sich nicht in einer Aktivität der App befinden, in der der Dienst lebt.

Bearbeiten

Diese Lösung hindert andere Hörer nicht daran, das durch den Dienst erfasste Berührungsereignis wegen zu empfangen

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

Durch die Rückgabe von false können andere Hörer das Ereignis empfangen.

Edit2

Offensichtlich setzt der Eingabe-Dispatcher im Betriebssystem die Koordinaten und den Druck auf 0, wenn die aktuelle Aktivität und der Listener keine UID gemeinsam nutzen. Hier ist source

3
Clocker

Ich habe viele SO - Threads durchsucht, aber aus Sicherheitsgründen glaube ich nicht, dass dies für alle Pakete im System möglich ist. Es ist auf jeden Fall für Ihre eigene App.

Fenstermanager

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

Floating/Overlay-Layout

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

Layout

<?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"/>
0
John61590