Android - 不活动/活动,无论顶级应用程序

时间:2013-09-18 21:04:59

标签: android

我需要找出最后一次用户交互的时间,无论哪个应用程序位于顶部。我不关心事件发生在哪里或什么,我只是需要知道它是什么时候。或者,碰巧,我收到一个事件。

我尝试了很多东西:

  1. 使用窗口创建服务并添加触摸侦听器。这吃了触摸事件而没有把它传下来
  2. 寻找一个shell命令。 getevent有效(每次收到触摸都会出现新行)但是你需要root,所以对我来说这不是一个合适的解决方案。
  3. 寻找“直到锁定的时间”但却没有任何结果。
  4. 另请注意:由于我不需要任何识别信息(如触摸位置),因此不存在安全问题。只是一种印章(或现场活动)。

    我愿意使用反射来解决这个问题。


    @ user2558882有一个非常好的解决方案。截至目前,这是我遇到的最佳方法。

    虽然这很好,但仍然需要用户在辅助功能控件中手动启用我们的应用程序。我们拥有数千台设备的客户,我们有办法自动更新和更改设置。我们尝试将手动配置保持在最低限度,但有些事情仍需要用户输入,例如启用设备管理模式。所以这个解决方案是可以接受的,但我仍然对一种不需要任何用户输入来启用的方式开放。


    我最终实现了@ user2558882的使用无障碍服务的想法。虽然欢迎其他想法。

2 个答案:

答案 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:

  1. 在代码中,在onServiceConnected()中。 (API 4起)

  2. 在xml中,使用服务中的meta-data标记。 (API 14起)

  3. 在您的应用程序中,您可以将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