Оверлей Android, чтобы захватить ВСЕ прикосновения и передать их дальше?

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

Получение представления, которое получает все сенсорные события

(Реализовано, результаты приведены ниже) Создание окна системного наложения (всегда сверху)

Что я могу сделать:

Я могу ЛИБО захватить ВСЕ события касания и воздействовать на них, перемещая свои спрайты и не позволяя ОС/домашнему экрану/браузеру видеть какие-либо из них, ИЛИ ИНАЧЕ я могу разрешить прохождение событий касания и получить только «TOUCH_OUTSIDE» для мое приложение для действий.

Моя недостигнутая цель:

Я НЕ МОГУ в жизни найти способ заставить ОБА работать с данными. Единственные методы, которые я могу придумать, которые я не могу реализовать, это: перехват данных в моем приложении и передача их в ОС/домашний экран/браузер для работы с Разрешение ОС/домашнему экрану/браузеру сначала получать данные, а затем получение обратного вызова с информацией каким-то образом. Разрешение ОС/домашнему экрану/браузеру получать данные, воздействовать на данные и опрашивать их на предмет того, каковы их значения прокрутки/местоположения, чтобы воздействовать на них в моем приложении.

Я боюсь, что это просто невозможно, кажется, я где-то читал в какой-то документации, которую сейчас не могу найти: «Все или ничего, либо ваше представление получает все события, либо ни одно из них»

(Чтобы избежать путаницы, я не имею в виду, что у меня есть два представления. Я имею в виду, что у меня есть одно представление, управляемое через действие/службу, перекрывающее ОС/домашний экран/браузер. Как оконное стекло, если хотите.)

Спасибо за любую полезную информацию, которую вы можете предложить, это очень ценится!

[ОБНОВЛЕНИЕ] Ниже опубликована моя собственная документация по этому вопросу, чтобы не вводить в заблуждение.


person While-E    schedule 31.01.2012    source источник
comment
есть вариант рутирования, и вы пытаетесь заставить его работать только на одном устройстве или на универсальном устройстве? У меня есть решение, которое включает в себя рутирование телефона и мониторинг /dev/input/eventX, где X — это поток событий, который предоставляет информацию о событии касания. Однако это работает только в том случае, если ваше устройство рутировано, и его необходимо настраивать для каждого устройства отдельно.   -  person Julia Schwarz    schedule 26.02.2014


Ответы (4)


Нашел эту документацию, в которой в значительной степени говорится, что невозможно сделать и то, и другое: Android: Multi коснитесь и TYPE_SYSTEM_OVERLAY

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

Чтобы создать оверлейное представление, при настройке LayoutParams вам нужно установить тип TYPE_SYSTEM_OVERLAY и использовать флаг FLAG_WATCH_OUTSIDE_TOUCH. Это представляет проблему, потому что, как говорится в документации Android: «вы не получите полный жест вниз / движение / вверх, а только местоположение первого нажатия как ACTION_OUTSIDE». Чтобы получить полный массив сенсорных событий, вам нужно использовать тип TYPE_SYSTEM_ALERT, но это приводит к тому, что оверлей захватывает экран и прекращает взаимодействие с другими элементами.

Кто-то хочет не согласиться, я хотел бы услышать хорошие новости :-D

person While-E    schedule 01.02.2012
comment
Пожалуйста, просмотрите линейку Pixel из игрового магазина, который получает только те события, которые ему нужны..play.google.com/store/apps/ - person Vishwaram Sankaran; 25.03.2016
comment
Но я действительно понятия не имею, как они это сделали - person Vishwaram Sankaran; 25.03.2016
comment
Я довольно долго работал над этой проблемой. Как уже говорилось, невозможно сделать и то, и другое (захватить все события касания и передать события касания нижнему слою) с помощью диспетчера окон. Однако я нашел решение, прослушивая getevents из logcat, создав процесс. Но для этого нужен суперпользователь. - person emir; 28.04.2018
comment
Pixel Ruler находится в лагере. Разрешить пропускать события, и я не думаю, что он захватывает сенсорные события через прозрачные части приложения; или, по крайней мере, я не вижу никаких функций, которые потребовали бы этих событий. - person JBSnorro; 27.03.2020

Вы можете использовать GestureOverlayView, если вы хотите скрыть линии, которые он рисует, вы можете установить цвет на Прозрачный #00000000, чтобы он не отображался, а затем вы можете фиксировать все прикосновения и жесты.

http://developer.android.com/resources/articles/gestures.html

person emalamisura    schedule 31.01.2012
comment
не решение. Если бы я создавал свой собственный лаунчер или домашнее приложение, то да. Это, однако, не дает мне больше видимости/перехвата событий касания. - person While-E; 01.02.2012
comment
Как вы понимаете? Вы можете наследовать от этого элемента управления и перехватывать события касания и обрабатывать их во всей активности, несмотря на ваш макет... - person emalamisura; 01.02.2012
comment
Я так понимаю, потому что пробовал. В моем вопросе я говорю, что я накладываю перед ОС/браузером/лаунчером... все. Это просто дает мне возможность быть ленивым и не кодировать свои собственные движения и жесты? Тем не менее, когда я прокручиваю свой домашний экран / браузер, срабатывает только одно касание (ВНЕШНЕЕ) ... Извините, если я запутал вас в вопросе. - person While-E; 01.02.2012
comment
Для пояснения я хочу получить события и прокрутить экран, вот где у меня проблема. Я могу сделать либо то, либо другое, но не то и другое, поскольку, когда вы объявляете оверлей non_focusable, поэтому поддержка получает события прокрутки, вы получаете только одно событие. Затем, если вы сделаете его фокусируемым, вы крадете все события и не можете передать их базовому браузеру/приложению. - person While-E; 01.02.2012
comment
ты все еще упускаешь мою мысль. У меня нет группы просмотра, у меня нет нескольких представлений. Прочитайте ссылку, которую я использовал ниже, чтобы полностью понять, о чем я говорю! Это system_overlay, который не может одновременно перехватывать и передавать значения.... - person While-E; 02.02.2012
comment
Да, я, очевидно, не совсем понял, как работает этот аспект Android, поэтому я задал вопрос? Разве сообщество не для этого, когда вы сами упираетесь в стену, спрашивая других об их опыте? Но спасибо за бессмысленный комментарий! Рад, что вы НАКОНЕЦ-ТО поняли, в чем был на самом деле вопрос... - person While-E; 04.02.2012

Я искал то же самое.

Этот флаг помогает мне FLAG_NOT_TOUCH_MODAL

Работает на Android 7 и 8, как показано ниже.

Единственное действие, которое я реализовал до сих пор, — это прикосновение, чтобы закрыть окно наложения.

Я также использовал код из здесь Пример кода системного наложения на Github, который был необходим для получить события.

Кстати, Google Maps отлично справляется с этим на Android 8. Вы можете перетаскивать их окно наложения, изменять его размер или закрывать. И все остальные приложения работают нормально, пока он работает.

    var type = 0

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
    {
        type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
    {
        type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
    }

    var flags = FLAG_NOT_TOUCH_MODAL

    mOverlayLayoutParams = WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, type, flags, PixelFormat.TRANSLUCENT)
person mswlogo    schedule 12.02.2018
comment
Не делает, как просил OP. В ссылке указано ... хотя другие приложения могут быть видны в фоновом режиме, с ними нельзя взаимодействовать. - person JBSnorro; 27.03.2020

Это не оптимальное решение, но оно работает. Перезапустите службу, установив флажок «Не трогать». поместите логическое значение в Intent, которое используется для startservice для определения значения переключения предыдущего состояния. Лучшей реализацией было бы активировать намерение при касании, когда окно прослушивает, и после фиксированного периода, когда оно не прослушивается.

public class bleh extends Service {
    public void onCteqwer(int i) {

        Context context; Class <bleh> context1 = bleh.class;

        WindowManager.LayoutParams params = null;
        WindowManager mang = (WindowManager) getSystemService(WINDOW_SERVICE);

        //check previous state of service
        if(i==0)
            params = new WindowManager.LayoutParams(arg0,arg1,arg2,arg3,arg4,arg5);

        if(i==1)
            params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,arg0,arg1,arg2,arg3,arg4);

        LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        View mViw = inflater.inflate(arg, null);

        mViw.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                return true;
            }
        });

        mang.addView(mViw, params);

        Intent z = new Intent(context, context1);

        if(i==0)
            z.putExtra("name", 1);
        if(i==1)
            z.putExtra("name", 0);

        stopSelf();
        startService(z);
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

    @Override
    public void onStart(Intent intent, int startId) {
        super.onStart(intent, startId);
        Bundle i=intent.getExtras();
        int userName = 0;

        if (i != null)
        {
            userName = i.getInt("name");
            onCteqwer(userName);
        }
    }
}
person Rico    schedule 11.07.2014