Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using TYPE_STEP_COUNTER in a background service?

I'm looking at implementing the step sensor API introduced in Android 4.4 (http://youtu.be/yv9jskPvLUc). However, I am unable to find a clear explanation on what the recommended way to monitor this in the background is? It seems like most examples only show how to do this with an activity while the app is running. I don't particularly need a high frequency of updates - I basically want to log the amount of steps the user has walked every hour to a backend service. Should I just spin up a background service that calls registerListener on SensorManager, or is there a more elegant way?

like image 750
Mattias Petter Johansson Avatar asked Dec 26 '15 15:12

Mattias Petter Johansson


3 Answers

As far as I know, there is no way around the SensorManager, but if you need the data very infrequently, you could trigger the sensor manually and get its values with a TriggerEventListener, which is a little cleaner than a SensorEventListener.

AlarmManager is typically the best option for starting an hourly timer, and it works even if your app isn't running. AlarmManager sends an Intent to a class that extends BroadcastReceiver, and that class will start your Service. The AlarmManager can be set anywhere in your app depending on your implementation.

StepCountService

SensorManager sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
Sensor stepCounter = mSensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
sensorManager.requestTriggerSensor(listener, stepCounter);

private TriggerEventListener listener = new TriggerEventListener(){
    @Override
    public void onTrigger(TriggerEvent event) {
        //handle step count here 
    }
}

MainActivity

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, AlarmReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
    PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME,AlarmManager.INTERVAL_HOUR, 
    AlarmManager.INTERVAL_HOUR, alarmIntent);

AlarmReceiver

public class AlarmReceiver extends BroadcastReceiver {

  @Override
  public void onReceive(Context context, Intent intent) {
    Intent service = new Intent(context, StepCountService.class);
    context.startService(service);
  }
} 
like image 142
TheoKanning Avatar answered Nov 12 '22 07:11

TheoKanning


This is not a complete solution, but the most energy-efficient way could be to wake up your device every hour or so, start a service which quickly reads the data, then goes back to sleep.

Depending on which device level you target, using a WakefulBroadcastReceiver, as described in this answer, seems the way to go.

You need to

  1. create the code by modifying the templates at WakefulBroadcastReceiver
  2. add the Service and the BroadCastReceiver into the manifest.
  3. schedule a repeating alarm somewhere in your app

If any of the points a less than clear, say so. See http://code.tutsplus.com/tutorials/android-barometer-logger-acquiring-sensor-data--mobile-10558

like image 24
serv-inc Avatar answered Nov 12 '22 07:11

serv-inc


@TheoKanning's answer is the correct way to do this manually. Alternatively, Google Fit continuously logs this data and has an API you can use to pull it into your app.

  • https://developers.google.com/fit/android/get-started
  • https://developers.google.com/fit/android/history
like image 44
var47 Avatar answered Nov 12 '22 07:11

var47