当用户移动时运行服务以收集传感器数据。

8

我想在用户移动/手机非静止时跟踪传感器数据(加速度计,陀螺仪)。

我能做的事情:

  1. 使用Sensor Listener监听传感器数据
        sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
        
        val accelerometerSensor = 
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
    
        sensorManager.registerListener(
                accSensor,
                accelerometerSensor,
                SensorManager.SENSOR_DELAY_NORMAL
            )
  1. 运行一个前台服务,即使应用程序从最近使用的应用程序中滑出,也始终在后台运行以跟踪传感器。
serviceIntent = Intent(context, SensorService::class.java)
context.startForegroundService(serviceIntent)
  1. 使用广播监听器,监听启动完成事件,以便在应用程序重新启动时立即启动服务。

但我无法:

  1. 停止传感器服务,在设备停止移动时收集传感器数据。
  2. 当用户设备开始移动并收集传感器数据时,启动未运行的传感器。

如何从系统接收“运动开始”和“运动结束”通知/回调,以便我们可以决定启动/结束前台服务。


你的问题可以重新表述为“当手机移动时是否有任何系统通知触发?”或者你的问题更像是“当手机移动时会有一个系统通知触发,但我尝试监听它的所有尝试都失败了”。 - x00
1
但是主要问题是“为什么?” 你为什么需要这个?如果例如 - 为了节省电池电量...那么你可能走错了方向。 - x00
@x00 我希望相信第一种情况,但如果我没有正确执行,也有可能是第二种情况。 - erluxman
你认为在节省电池寿命且不总是显示通知的情况下(这会让用户感到烦恼),有什么建议?但两种情况都有几乎相同的解决方案。现在我很好奇,您认为记录传感器(加速度计和磁力计)仅在用户移动时的方式更好。 - erluxman
2个回答

3

这段内容有点长,太长了无法在评论区内进行回答。它的某种程度上也是一个答案,但没有证据,只是我的经验。

我并不是 Android 方面的专家,但对传感器有一些了解。最重要的是他们始终处于活跃状态(除非完全关闭),而且总会存在一些噪音

  1. 不能百分之百确定是否有运动。相反,您需要收集所有事件,选择阈值并自行决定。(可能需要聚合来自多个传感器的测量数据才能做出决策,甚至考虑测量历史记录-例如,如果用户在颠簸的道路上驾驶汽车,噪声会在较长时间内更高)。
  2. 如果相应的代码由操作系统执行或由您的服务执行,几乎没有能耗差异。但使用您的代码可以进行更多的定制,包括阈值、聚合和其他逻辑。这就是为什么我认为操作系统将API最小化,并且不存在移动开始/移动停止等事件。
  3. 唯一消耗超过最低限度的是您的代码。除了您的代码以外,没有人会决定是否使用常量流通知来打扰用户。

因此,请考虑聚合策略和阈值,在未达到阈值时不显示通知,并使代码快速(以便其不会使用太多能源)。这样就可以了,或多或少……因为这些决定并不容易。许多大公司的应用程序都无法在所有情况下正确执行它们。只需安装几个计步器应用程序,您就会发现它们将显示不同的步数。


你有没有任何想法如何一直保持监听传感器,以决定是否显示通知?因为据我所知,要一直监听传感器,除了显示连续的通知外别无他法。 - erluxman
就像我说的:“我绝对不是Android方面的专家。但是……”但是你所说的话非常奇怪。传感器和通知不能是同一个API。绝不可能!因此,我查看了@user3252344提供的链接,并进行了一些谷歌搜索(例如在这里https://developer.android.com/guide/topics/sensors/sensors_overview和这里https://code.tutsplus.com/tutorials/android-barometer-logger-acquiring-sensor-data--mobile-10558),**我没有看到**关于强制性通知的任何内容。也许你正在使用其他API——这个API对于你的任务是错误的。 - x00
Android在需要资源时会杀死后台服务,为了避免这种情况,我们需要运行前台服务并显示通知。否则,当我们从最近的应用程序中滑动关闭应用时,服务也将被终止,我们将无法接收传感器更新。 - erluxman
这就是我在第一条评论中所说的:你正在问错问题。再提一个关于你问题根源的问题:“如何保持服务运行?” - x00

2
"什么是'运动'的阈值取决于您的应用程序,因此没有很多现成的选项(例如,您是否关心用户是否摇晃手机,还是只关心他们在汽车中移动了几条街道?)。
有一些传感器类型可以检测运动的开始/停止。请参见此处。它们是否适合您的应用程序取决于您的应用程序。
1. 停止传感器: TYPE_STATIONARY_DETECT会在用户静止5秒钟后触发事件。监听它,并使用它来停止服务。如果您需要更快的速度,您将不得不自己实现。
2. 启动传感器: TYPE_MOVEMENT_DETECT与静止检测相反,当用户移动5秒钟后触发。如果5秒的延迟不是致命缺陷,您可以监听这个事件以重新启动服务。
如果您希望您的移动唤醒应用程序从睡眠中恢复,则可以使用SIGNIFICANT_MOTION类型,但我从未找到过对该传感器类型的“重要”定义。
如果您的运动不是这两种情况之一 - 持续5秒的运动或触发“重要”标志的任何东西 - 那么您将需要自己实现开始和停止,因为如果传感器没有启动并检测到运动,则无法检测要启动的运动。例如,我曾使用过类似于这样的伪代码:"
class MotionSensorMediator:
    
    enum state=[waiting, active]

    def ctor():
        state = waiting

    def onSensorEvent(SensorEvent event):
        switch state:
             case waiting:
                  checkMovementThreshold(event)
                  break
             case active:
                  checkMovementThreshold(event)
                  sendToListener(event)
                  break

    def checkMovementThreshold(SensorEvent event):
        results = //some distance calculations
        if result > threshold && state == waiting:
             state = active
        else if result < threshold && state == active:
             state = waiting

我似乎无法记录在onSensorChanged触发的TYPE_MOTION_DETECT或TYPE_STATIONARY_DETECT事件。我是否漏掉了什么东西..没有任何提示,所以我可能错过了某些内容.. - erluxman
有没有处理这些传感器的示例应用程序/演示? - erluxman
我个人没有使用过这两个,因为它们不适合我的应用程序,所以很抱歉我不知道! - user3252344

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接