Как сервис может прослушивать сенсорные жесты / события? - PullRequest
60 голосов
/ 16 июля 2011

Мне интересно, как такие приложения, как SwipePad и Wave Launcher, могут обнаруживать жесты / события касания просто через сервис.Эти приложения могут обнаруживать жесты касания, даже если они не принадлежат им.Я просмотрел весь Интернет и не нашел, как они могут это сделать.

Мой главный вопрос заключается в том, как служба может прослушивать гостевые события / события, как обычное мероприятие, которое может получать MotionEvents, даже если оно не находится в исходном действии или контексте.По сути, я пытаюсь создать приложение, которое будет распознавать конкретный сенсорный жест от пользователя независимо от того, какое действие находится сверху, и что-то делать, когда этот жест повторяется.Прикосновение касания будет потоком, работающим в фоновом режиме как услуга.

Ответы [ 5 ]

18 голосов
/ 30 августа 2012

У меня была такая же проблема, и я наконец понял это! Благодаря этому сообщению: Создание системного оверлея (всегда сверху) . Вам нужно использовать окно предупреждения вместо наложения (и это также означает, что вы можете использовать его в 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);

Ура!

5 голосов
/ 22 сентября 2011

Интересный вопрос.Я не знаю, как они это сделали, и я нашел сообщения в группах Google, которые говорят мне, что нет глобального слушателя касания.Но в любом случае у меня есть идея ...

Я нашел этот пост , где кому-то удается отобразить всплывающее окно из службы.Если бы я сделал это всплывающее окно прозрачным и полноэкранным, я уверен, что смогу захватывать касания, поскольку мне разрешено устанавливать сенсорный перехватчик .

Редактировать :Пожалуйста, сообщите результаты, когда вы попробуете это, было бы интересно узнать, работает ли это ...

3 голосов
/ 27 января 2016

Я проверил это на API 21 и Nexus 5, и мне удалось войти в систему из службы, когда сенсорное событие было запущено системой. Однако данные в объекте MotionEvent, например, координаты, возвращают 0.0, когда ВНЕ того, что кажется пакетом моего приложения.

Два источника интеграция , разрешение

Мне любопытно, почему event.getX (), event.getY () и event.getPressure () возвращают 0.0, когда не находятся в активности приложения, в котором находится сервис.

Редактировать

Это решение не запрещает другим слушателям получать событие касания, захваченное службой из-за

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

Возвращая false, он позволяет другим слушателям получать событие.

Edit2

По-видимому, диспетчер ввода в ОС установит координаты и давление на 0, если текущая активность и слушатель не разделяют UID, здесь source

3 голосов
/ 28 августа 2015

Я протестировал каждое возможное решение, но ничего не помогло, некоторые не сработали, сенсорное событие вызвало заморозку экрана.

Итак, я провел реверс-инжиниринг и сейчас публикую решение, которое работает

  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 голосов
/ 12 апреля 2018

Я искал во многих SO-потоках, но по соображениям безопасности не думаю, что это возможно для всех пакетов в системе. Это, конечно, для вашего собственного приложения.

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

Плавающая / Наложение макета

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

Компоновка

<?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"/>
...