Android - бездействие / активность независимо от топ приложения

1

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

Я пробовал несколько вещей:

  • Создайте сервис с окном и добавьте прослушиватель. Это съел событие касания и не прошло его.
  • Посмотрел на команду оболочки. getevent works (новая строка приходит каждый раз при получении касания), однако вам нужен root, и поэтому это не подходит для меня.
  • Посмотрел "время до блокировки", но ничего не придумал.

Также обратите внимание: это не касается безопасности, поскольку мне не нужна какая-либо идентифицирующая информация, такая как местоположение касания. Просто штамп типа (или живое событие).

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


@user2558882 имеет очень хорошее решение. На данный момент это лучший подход, с которым я столкнулся.

В то время как это здорово, все равно требуется, чтобы пользователь вручную включил наше приложение в элементы управления доступности. У нас есть клиенты с тысячами устройств, и у нас есть способ автоматически обновлять и изменять настройки. Мы стараемся, чтобы ручная настройка была минимальной, но некоторые вещи по-прежнему требуют ввода пользователя, например, включения режима Device Admin. Таким образом, это решение приемлемо, но я все еще открыт для того, чтобы не требовать ввода пользователем.


В результате я использовал идею @user2558882 для использования службы доступности. Хотя другие идеи приветствуются.

Теги:

2 ответа

2

Это просто идея и не может быть полностью переносимой.

Вот что может сделать AccessibilityService:

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

Вы узнаете о событии внутри onAccessibilityEvent(AccessibilityEvent):

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    // Some event

    timeSinceLastInteraction = System.currentTimeMillis();

}

Вы можете периодически регистрировать обновления:

Log.i("LOG_TIME_ELAPSED", "Last user interaction was " + 
             ((System.currentTimeMillis() - timeSinceLastInteraction) / 1000) + 
                      " seconds ago.");

Существует два способа настройки службы AccessibilityService:

  • В коде внутри onServiceConnected(). (API 4 и далее)

  • В xml, используя тэг meta-data в вашей службе. (API 14 и далее)

В вашем приложении, возможно, вы можете установить AccessibilityServiceInfo.eventTypes в:

accessibilitySeviceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;

Но TYPES_ALL_MASK будет включать в себя такие уведомления, как AccessibilityEvent.TYPE_ANNOUNCEMENT, AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED и т.д., которые, как я полагаю, вы не хотите перехватывать. Итак, вам нужно выбрать подмножество AccessibilityEvent.TYPE_X.

Еще одна вещь, о которой вы должны быть осторожны, - это тайм-аут уведомления:

Тайм-аут после последнего события данного типа перед AccessibilityService уведомляется.

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

Итак, будьте великодушны со значением тайм-аута.

Вы найдете эту страницу очень полезной, если вы решите пойти с опцией AccessibilityService: Разработка службы специальных возможностей.

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

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

Вы можете включить AccessibilityService во время развертывания и, возможно, ограничить доступ к меню настроек с помощью приложения, такого как AppLock.

Еще одна опция - проверять, включен ли ваш AccessibilityService время:

AccessibilityManager am = (AccessibilityManager)
                               getSystemService(ACCESSIBILITY_SERVICE);

List<AccessibilityServiceInfo> listOfServices = 
                             am.getEnabledAccessibilityServiceList(
                               AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

for (AccessibilityServiceInfo asi : listOfServices) {

    // Check if your AccessibilityService is running

}

Если функция AccessibilityService была отключена любознательным/пресловутым пользователем, вы можете заблокировать устройство, отображая полноэкранное представление с текстом: Device has been locked. Contact a Sales Rep to unlock this device.

  • 0
    Ух ты. Тонны информации, большое спасибо. Я посмотрю на это завтра и сообщу о моих результатах.
  • 1
    Я обновил свой вопрос. Ваше решение прекрасно работает, но для него нужен способ, который не требует ввода данных пользователем. Если нет такой вещи, я определенно буду использовать AccessibilityService .
Показать ещё 3 комментария
0

Я считаю, что вам нужно вернуть false, чтобы указать, что ваше прозрачное служебное окно не потребляет событие касания. Таким образом, цикл событий передаст его вниз по стеку в нижние окна.

https://developer.android.com/reference/android/view/View.OnTouchListener.html

Другая возможность - это добавить службу, которая слушает события движения/акселерометра.

https://developer.android.com/guide/topics/sensors/sensors_motion.html

Другая возможность - прослушать ACTION_USER_PRESENT

https://developer.android.com/reference/android/content/Intent.html#ACTION_USER_PRESENT

или ACTION_SCREEN_ON

https://developer.android.com/reference/android/content/Intent.html#ACTION_SCREEN_ON

  • 0
    Я знаю, что OnTouchListener не работает. Как только вы регистрируете слушателя, окно захватывает щелчок, и ему все равно, какое представление фактически потребляет его. Мне действительно нравится идея движения / акселерометра, однако она не будет работать для моего приложения. Я работаю над приложением киоска, где устройство может находиться в корпусе, не двигаясь.
  • 0
    Также обратите внимание, что если просто вернуть false сработало, это представляло бы угрозу безопасности. Вы получаете тип касания и местоположение в событии onTouch. И если бы вы могли поместить прозрачный вид поверх всего, вы могли бы точно сказать, где были касания (даже на клавиатуре).
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню