我需要找出最后一次用户交互的时间,无论哪个应用程序位于顶部。我不关心事件发生在哪里或什么,我只是需要知道它是什么时候。或者,碰巧,我收到一个事件。
我尝试了很多东西:
getevent
有效(每次收到触摸都会出现新行)但是你需要root,所以对我来说这不是一个合适的解决方案。另请注意:由于我不需要任何识别信息(如触摸位置),因此不存在安全问题。只是一种印章(或现场活动)。
我愿意使用反射来解决这个问题。
@ user2558882有一个非常好的解决方案。截至目前,这是我遇到的最佳方法。
虽然这很好,但仍然需要用户在辅助功能控件中手动启用我们的应用程序。我们拥有数千台设备的客户,我们有办法自动更新和更改设置。我们尝试将手动配置保持在最低限度,但有些事情仍需要用户输入,例如启用设备管理模式。所以这个解决方案是可以接受的,但我仍然对一种不需要任何用户输入来启用的方式开放。
我最终实现了@ user2558882的使用无障碍服务的想法。虽然欢迎其他想法。
答案 0 :(得分:3)
这只是一个想法,可能无法完全转移。
以下是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选项,您会发现此页面非常有用:Developing an Accessibility Service。
从您的评论到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
。
答案 1 :(得分:1)
我相信你必须返回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