Android - 不活动/活动,无论***应用程序
Posted
技术标签:
【中文标题】Android - 不活动/活动,无论***应用程序【英文标题】:Android - Inactivity/Activity regardless of top app 【发布时间】:2013-09-18 21:04:58 【问题描述】:我需要找出最后一次用户交互是什么时候,无论哪个应用程序在最前面。我不在乎事件发生在哪里或发生了什么,我只需要知道它是什么时候发生的。或者,当它发生时,我收到一个事件。
我尝试了多种方法:
-
使用窗口创建服务并添加触摸侦听器。这吃掉了触摸事件并没有传递下去
寻找一个shell命令。
getevent
有效(每次收到触摸时都会输入新行)但是您需要 root,所以这对我来说不是一个合适的解决方案。
寻找“距离锁定的时间”,但一无所获。
另请注意:这没有安全问题,因为我不需要任何识别信息,例如触摸位置。只是一个类型印章(或现场活动)。
我也愿意使用反射来解决这个问题。
@user2558882 有一个很好的解决方案。到目前为止,这是我遇到的最好的方法。
虽然这很好,但它仍然需要用户在辅助功能控件中手动启用我们的应用程序。我们的客户拥有数千台设备,我们有办法自动更新和更改设置。我们尝试将手动配置保持在最低限度,但有些事情仍然需要用户输入,例如启用设备管理模式。所以这个解决方案是可以接受的,但是我仍然愿意接受一种不需要任何用户输入来启用的方式。
我最终实现了@user2558882 使用无障碍服务的想法。虽然欢迎其他想法。
【问题讨论】:
【参考方案1】:这只是一个想法,可能无法完全转移。
以下是 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。
事件通知超时对于避免传播事件很有用 过于频繁地向客户发送,因为这是通过 an 完成的 昂贵的进程间调用。可以将超时视为 确定事件生成何时稳定的标准。
所以,请尽量设置超时值。
如果您决定使用 AccessibilityService 选项,您会发现此页面非常有用:Developing an Accessibility Service。
从您的 cmets 到 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
。
【讨论】:
哇。大量信息,非常感谢。我明天某个时候会调查一下,然后告诉你我的结果。 我更新了我的问题。您的解决方案效果很好,但想要一种无需用户输入即可启用的方式。如果没有这样的事情,我肯定会使用AccessibilityService
。
@Randy 很高兴知道。在每台设备上启用服务听起来确实是个问题。您可以做的最好的事情是:在第一次运行时将用户带到“辅助功能设置”页面。更多信息在这里:Link。希望有人能提出更好的解决方案。
@Randy Hey Randy,只是想知道这个解决方案是否确实可行 &|可实施。
这是我们最终实施的解决方案,但它并不完美。如果用户使用 Chrome 并滚动网页,则它不会注册为可访问性事件,因此我们不会将其视为用户交互。【参考方案2】:
我相信你必须返回 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
【讨论】:
我知道的 OnTouchListener 不起作用。一旦你注册了一个监听器,窗口就会捕获点击,它并不关心哪个视图实际使用它。我真的很喜欢运动/加速度计的想法,但是,它不适用于我的应用程序。我正在开发一个信息亭应用程序,其中设备可能位于一个外壳中,从不移动。 另外请注意,如果简单地返回 false 工作,它会带来安全问题。您在 onTouch 事件中收到触摸类型和位置。而且,如果您可以在所有内容之上放置一个透明视图,您将能够准确判断触摸的位置(甚至在键盘上)。 @Randy Ok 添加了更多想法。 遗憾的是,这两种解决方案都不行。以上是关于Android - 不活动/活动,无论***应用程序的主要内容,如果未能解决你的问题,请参考以下文章
如何在 PhoneGap 应用启动时启动 Android 活动?
设备重新启动后,地理围栏是不是在 android 中保持活动状态
创建新活动错误:RED SQUIGGLYS EVERYWHERE