Reputation: 19385
Things I was able to do :
sensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
val accelerometerSensor =
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
accSensor,
accelerometerSensor,
SensorManager.SENSOR_DELAY_NORMAL
)
serviceIntent = Intent(context, SensorService::class.java)
context.startForegroundService(serviceIntent)
But I was not able to:
What might be the way to receive the Motion start and Motion end notifications/callback from the system so that we can decide to start/end foreground services.
Upvotes: 8
Views: 969
Reputation: 758
The thresholds for what is 'movement' depends on your application so there's not a lot of ready-made options (e.g. do you care if the user shakes their phone, or just if they move somewhere in a car for a few streets?).
There are sensor types which detect movement start/stop. See here. Whether or not they're good for your app depends on your app.
TYPE_STATIONARY_DETECT
fires an event when the user has not moved for 5 seconds. Listen for it, and use it to stop your service. If you want faster than that, you'll have to do it yourself.
TYPE_MOVEMENT_DETECT
is the opposite of stationary-detect, and fires when the user has been moving for 5 seconds. You could listen for this to start the service back up if the 5 second latency isn't a deal-breaker.
Type SIGNIFICANT_MOTION
is also useable if you want your movement to wake the app from sleep, but I've never had much luck finding what counts as 'significant' for that sensor type.
If your movement isn't one of those two things - a 5-second sustained movement or whatever sets off the 'significant' flag - then you will need to implement the start and the stop yourself, because a sensor can't detect what movement to start on if it's not already started & detecting movement. For example I've used something like this pseudocode
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
Upvotes: 2
Reputation: 13833
Too big for a comment, so I'll post it as an answer. And it is in some way an answer, but without proofs, just my experience.
I'm in no way an expert in the Android. But I know a thing or two about sensors in general. And the main thing is that they are always active (if not turned off entirely), and that there is always some noise. So
moving starts
/moving stops
.So, think of aggregation strategy and thresholds, don't show notifications if thresholds are not passed, and make your code fast (so that it won't use too much energy). And your are done... more or less... because these decisions are not easy to make. A lot of apps from big companies fail to make them right in all the cases. Just install a couple of pedometer-apps and you'll see that they all will show different counts of steps.
Upvotes: 3