1

I am quite a beginner in programing, and this is in fact my first project in android. I'm developing a pedometer application. For this purpose, I need to collect data at a frequency rate of exactly 50 Hz. None of the available options allows me to get satisfactory results:

SensorManager.SENSOR_DELAY_FASTES

SensorManager.SENSOR_DELAY_GAME

SensorManager.SENSOR_DELAY_NORMAL

SensorManager.SENSOR_DELAY_UI

So i tried like this:

sm.registerListener(this, accelerometer, 20000);

And here arises the problem. Despite a given frequency, the system does not return the samples on every 20ms interwal. I made some messurments to show you what i mean:

  1. ms x y z

  2. 71048 -0.0059945136 7.981956E-4 -0.17364979

  3. 71068 -0.024843872 0.0054850876 -0.22273922

  4. 71086 0.016724974 0.0061867684 -0.12516594

  5. 71106 0.008605644 0.0050877184 -0.15809155

  6. 71127 -0.016088352 0.0035609156 -0.19820023

  7. 71150 7.1662664E-4 0.010106161 -0.14373398

  8. 71167 0.007880032 0.0055761486 -0.15989017

  9. 71187 0.016164377 7.1927905E-4 -0.1634798

  10. 71209 -0.0028537065 -0.0033412725 -0.17127609

  11. 71227 0.0044119656 -0.0018739849 -0.16169643

As you can see at provided data, the interval between samples is not always 20ms.

Here I found the idea of how to deal with it:

Impossibility to change the rate of the accelerometer

" Unfortunately as suggested by other answers, the delay (or sampling rate) that you set is only a suggestion (for the system) of the minimum your application requires however, this can change drastically depending on other applications running or your device entering on power saving modes (turning off cpu etc). One way I was able to get a somewhat good sampling rate was by recording my data from a service, making the service a foreground service and having a power lock with the flag PARTIAL_WAKE_LOCK."

However, I am not able to implement this method. It gives me an error:

Caused by: java.lang.NullPointerException: class name is null

Which leads to the line:

startForeground(notificationId, notification);

Here is my code (i know it's a bit messy, sorry for that):

    Notification notification = null; 

    Intent viewIntent = new Intent(this, SensorService.class); 
    PendingIntent viewPendingIntent =
            PendingIntent.getActivity(contex, 0, viewIntent, 0);

    NotificationCompat.Builder notificationBuilder =
            new NotificationCompat.Builder(contex)
                    .setContentTitle("test")
                    .setContentText("testt")
                    .setContentIntent(viewPendingIntent);

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(contex);

    notification = notificationBuilder.build();
    int notificationId = 1;
    notificationManager.notify(notificationId, notification);
    startForeground(notificationId, notification);
}

And method onStartCommand:

public int onStartCommand(Intent intent, int flags, int startId) {
    //Power management
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE); //Uzyskujemy dostęp do PowerManager'a.
    PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "My Tag");  //PARTIAL_WAKE_LOCK zapewnia że CPU pracuje.
    wl.acquire();
    Log.d(TAG,"onStartCommand");
    return START_STICKY;
}

The above code is in a class SensorService:

public class SensorService extends Service implements SensorEventListener{
....
}

And SensorService class is called like this:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pedometer_test);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    xText = (TextView)findViewById(R.id.xText);
    yText = (TextView)findViewById(R.id.yText);
    zText = (TextView)findViewById(R.id.zText);
    textViewSteps = (TextView)findViewById(R.id.textViewSteps);

    this.stepCounter = new StepCounter(textViewSteps);  

    this.filterValues = new FilterValues(stepCounter, filteredFileWriter);  
    this.sensorService = new SensorService(xText, yText, zText, textViewSteps, stepCounter, filterValues, getApplicationContext());

}

Do you guys have any ideas on how to fix this error? Maybe there is another easier way to set this even sampling rate? Or maybe I am trying to implement a method that will not work at all? I would appreciate any sort of help.

PS: This is my first post on StacOverFlow, so I apologize in advance for incorrect formating and my poor english. I have not been writing anything in this language for a while.

EDIT: Whole idea of pedometer algorithm is based on:

http://www.analog.com/media/en/technical-documentation/analog-dialogue/pedometer.pdf

Community
  • 1
  • 1
rooyo
  • 11
  • 1
  • Android sensor sample frequency is all over the place. I have seen Android devices that can't sample the acceleration sensor at 50Hz... Some can do over 300Hz. If you need exactly 50Hz, the only idea that occurs to me is to set the acceleration from the Sensor Manager using SensorManager.SENSOR_DELAY_FASTEST and then sampling that value from a thread or handler at exactly 50Hz using Thread.Sleep() or PostDelay(). However, I suspect you can work around the 50Hz issue by looking at the algorithm, but that is different question. – Kaleb Dec 09 '15 at 19:55

0 Answers0