Create a Simple Pedometer and Step Counter in Android

Pedometer
In this example we will see how to create a simple pedometer application which will count the steps as we walk or run. Using the step values we may also calculate the approximate distance, pace and calories burned using certain formulas.
According to Wikipedia
A pedometer is a device, usually portable and electronic or electromechanical, that counts each step a person takes by detecting the motion of the person’s hands or hips.
Since most of our smartphones do not have an inbuilt pedometer sensor dedicated for step counting, we will use the Accelerometer sensor which is found in almost all devices to calculate the steps covered.
In this case the values received from Accelerometer sensor will be passed through a filter to get the approximate step detection.
Lets start with the coding part.
StepListener Interface
This interface will listen to alerts about steps being detected. Add the below code in a new class StepListener.java
1 2 3 4 5 6 7 8 9 10 |
// Will listen to step alerts public interface StepListener { public void step(long timeNs); } |
Sensor Filter
Now we will create a class with an algorithm to filter out values that has close approximation to steps. Create a new class SensorFilter.java and add the below code in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
public class SensorFilter { private SensorFilter() { } public static float sum(float[] array) { float retval = 0; for (int i = 0; i < array.length; i++) { retval += array[i]; } return retval; } public static float[] cross(float[] arrayA, float[] arrayB) { float[] retArray = new float[3]; retArray[0] = arrayA[1] * arrayB[2] - arrayA[2] * arrayB[1]; retArray[1] = arrayA[2] * arrayB[0] - arrayA[0] * arrayB[2]; retArray[2] = arrayA[0] * arrayB[1] - arrayA[1] * arrayB[0]; return retArray; } public static float norm(float[] array) { float retval = 0; for (int i = 0; i < array.length; i++) { retval += array[i] * array[i]; } return (float) Math.sqrt(retval); } public static float dot(float[] a, float[] b) { float retval = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; return retval; } public static float[] normalize(float[] a) { float[] retval = new float[a.length]; float norm = norm(a); for (int i = 0; i < a.length; i++) { retval[i] = a[i] / norm; } return retval; } } |
Step Detector
Now lets create a step detector class which will accept updates from accelerometer sensor and deploys the filter to detect if a step has been covered by the user. Create a class called StepDetector.java add the below code in it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 |
public class StepDetector { private static final int ACCEL_RING_SIZE = 50; private static final int VEL_RING_SIZE = 10; // change this threshold according to your sensitivity preferences private static final float STEP_THRESHOLD = 50f; private static final int STEP_DELAY_NS = 250000000; private int accelRingCounter = 0; private float[] accelRingX = new float[ACCEL_RING_SIZE]; private float[] accelRingY = new float[ACCEL_RING_SIZE]; private float[] accelRingZ = new float[ACCEL_RING_SIZE]; private int velRingCounter = 0; private float[] velRing = new float[VEL_RING_SIZE]; private long lastStepTimeNs = 0; private float oldVelocityEstimate = 0; private StepListener listener; public void registerListener(StepListener listener) { this.listener = listener; } public void updateAccel(long timeNs, float x, float y, float z) { float[] currentAccel = new float[3]; currentAccel[0] = x; currentAccel[1] = y; currentAccel[2] = z; // First step is to update our guess of where the global z vector is. accelRingCounter++; accelRingX[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[0]; accelRingY[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[1]; accelRingZ[accelRingCounter % ACCEL_RING_SIZE] = currentAccel[2]; float[] worldZ = new float[3]; worldZ[0] = SensorFilter.sum(accelRingX) / Math.min(accelRingCounter, ACCEL_RING_SIZE); worldZ[1] = SensorFilter.sum(accelRingY) / Math.min(accelRingCounter, ACCEL_RING_SIZE); worldZ[2] = SensorFilter.sum(accelRingZ) / Math.min(accelRingCounter, ACCEL_RING_SIZE); float normalization_factor = SensorFilter.norm(worldZ); worldZ[0] = worldZ[0] / normalization_factor; worldZ[1] = worldZ[1] / normalization_factor; worldZ[2] = worldZ[2] / normalization_factor; float currentZ = SensorFilter.dot(worldZ, currentAccel) - normalization_factor; velRingCounter++; velRing[velRingCounter % VEL_RING_SIZE] = currentZ; float velocityEstimate = SensorFilter.sum(velRing); if (velocityEstimate > STEP_THRESHOLD && oldVelocityEstimate <= STEP_THRESHOLD && (timeNs - lastStepTimeNs > STEP_DELAY_NS)) { listener.step(timeNs); lastStepTimeNs = timeNs; } oldVelocityEstimate = velocityEstimate; } } |
MainActivity
Now lets create our MainActivity.java from where we will start recording the readings and show the result to user.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
public class MainActivity extends AppCompatActivity implements SensorEventListener, StepListener { private TextView textView; private StepDetector simpleStepDetector; private SensorManager sensorManager; private Sensor accel; private static final String TEXT_NUM_STEPS = "Number of Steps: "; private int numSteps; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Get an instance of the SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); simpleStepDetector = new StepDetector(); simpleStepDetector.registerListener(this); TvSteps = (TextView) findViewById(R.id.tv_steps); BtnStart = (Button) findViewById(R.id.btn_start); BtnStop = (Button) findViewById(R.id.btn_stop); BtnStart.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { numSteps = 0; sensorManager.registerListener(MainActivity.this, accel, SensorManager.SENSOR_DELAY_FASTEST); } }); BtnStop.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { sensorManager.unregisterListener(MainActivity.this); } }); } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { simpleStepDetector.updateAccel( event.timestamp, event.values[0], event.values[1], event.values[2]); } } @Override public void step(long timeNs) { numSteps++; TvSteps.setText(TEXT_NUM_STEPS + numSteps); } } |
Layout XML
Now lets add our XML layout file which is used in the MainActivity.java. This layout contains a TextView which will show the steps and two buttons, “Start Pedometer” and “Stop Pedometer”. Name the file as activity_main.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:gravity="center" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:id="@+id/tv_steps" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" /> <Button android:id="@+id/btn_start" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Start Pedometer" /> <Button android:id="@+id/btn_stop" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="Stop Pedometer" /> </LinearLayout> |
Declare the MainActivity.java in Manifest file. Run the code and check the steps detection while walking. For maximum accuracy keep the device close to body. You may increase or decrease the sensitivity by changing the STEP_THRESHOLD in StepDetector class.
Hope you found this tutorial helpful. Please let me know your comments below.
Follow GadgetSaint on Facebook / Twitter for updates.
Wanna start your blog or site in 5 mins? Check out Official WordPress recommended web hosting Bluehost.
This code is not working. There is lack og textview.setText()
Should we declare permission in the Manifest file for run this app
No permissions required
Can you tell where do we need textview.settext?
I implemented it in my app and it works perfectly! Thanks so much!
You are welcome!
why i cant insert data in my sql lite ? my app crash
What error are you getting? Share your logcat
I don’t understand SensorFilter.java why are you used them?
As the name says, its used for filtering out unwanted values from accelerometer data
Is it possible to make public step listener data to string?
Yes. You make cast the value to String.
the app is not working … there is no error but the app is crashing .. what to do next ?????
Can you post the logcat?
now error is coming cannot resolve symbol tvsteps???
Tvsteps is the textview which you need to link with your layout xml using findviewbyid
when im declaring it with textview then it is coming tvsteps is not used
I think I need to see your code.
can’t the apps stored the walked data before on Firebase ?
I can’t get you. Do you mean you want to write step count data in Firebase? If that is the case you can do it. https://firebase.google.com/docs/database/android/read-and-write
Yes, write the step count data on Firebase. How I can do this ? I mean the step are saved in Firebase
Hi! Can i convert lister.step as model class ?
Hello just a question, thanks for the code i tried it but can you explain me a little how it’s works ?
Also this code is not very sensitive how can i increase sensibility ? Did I have to increase or decrease the treeshold ?
Decrease the threshold to increase the sensitivity.
I will try thank you, also this code works, can you explain me the principe? It’s a part of my thesis , i can quote you if you want 🙂 .
Hi, step(long timeNs) method not calling in MainActivivty. Any solution for this.
Yo man,
thanks 4 the example, it works!
STEP_THRESHOLD and STEP_DELAY_NS are not appropriate for step detect. Step increases when hang the phone up and down.
Great work. How do you calculate distance from these steps?
I implemented its working . Thank you so much.
Hello Sir, Thanks for posting this code.
but i’m having an error in my code in Tvstep statement (at the last of main activity)
plz help!
What error are you getting?
in error its saying Tvsteps can not be resolved.
plz can i get ur emailid? ill send u screenshots, then u can check in that.
there is no other error except this
You are getting this error because TvSteps is a TextView which need to be initialised in your onCreate using “findviewbyid”. You need to link your TvSteps TextView with the XML layout.
Do something like this in your activity onCreate:
TextView TvSteps = (TextView) findviewbyid(R.id.yourtextviewidinxml); // replace with your TextView id defined in layout XML
//please check the code
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
public class Two extends ActionBarActivity implements StepListener,SensorEventListener {
private TextView textView;
private StepDetector simpleStepDetector;
private SensorManager sensorManager;
private Sensor accel;
private static final String TEXT_NUM_STEPS = “Number of Steps: “;
private int numSteps;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main2);
// Get an instance of the SensorManager
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accel = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
simpleStepDetector = new StepDetector();
simpleStepDetector.registerListener(this);
//Tvsteps is initialised here
TextView TvSteps = (TextView) findViewById(R.id.tv_steps);
Button BtnStart = (Button) findViewById(R.id.btwo1);
Button BtnStop = (Button) findViewById(R.id.btwo2);
BtnStart.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
numSteps = 0;
sensorManager.registerListener(Two.this, accel, SensorManager.SENSOR_DELAY_FASTEST);
}
});
BtnStop.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
sensorManager.unregisterListener(Two.this);
}
});
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
simpleStepDetector.updateAccel(
event.timestamp, event.values[0], event.values[1], event.values[2]);
}
}
@Override
public void step(long timeNs) {
numSteps++;
//error in this Tvsteps
TvSteps.setText(TEXT_NUM_STEPS + numSteps);
}
}
//there r no errors in xml layput
//i have taken the same name in my xml layout, see:
Make your TextView TvSteps global variable, declare it outside onCreate
TextView TvSteps;
OnCreate{
TvSteps = (TextView) findViewById(R.id.tv_steps);
}
By this that error is removed in TvSteps … Thanks!
but a new problem has occured,
its saying:
Sytax error on token “OnCreate”, delete this token.
Share your entire code again
I think you copy pasted the code I send you……Keep your onCreate the way it is…..just make your TextView global…..the code I send is just an example for your understanding
WoW!! thankyou so muchh … no errors now finally 🙂
Bdw why was it showing error when i declared it inside OnCreate?
this is a right way, then wht was the need to declare it as global?? we didnt declare button as global but its still working.. then what was the problem?
When you declare inside onCreate it’s a local variable to onCreate and it’s scope is limited to onCreate. Declaring global you can access it from anywhere in the class. Here you are trying to access the local variable of onCreate outside….that’s why it’s showing error. By the way you need to work on your basics.
Sir,one more problem … there r no errors in the code now.
but the application is not working on d phone. i mean, its opening up, but the buttons r not working, no steps r being counted, though the code is complete n corrct
n yes sir, ill revise the basics, but right now plz help
Is it possible for the app to still count steps even when the phone is locked?
Hy Anu! Why did not you used Step_count_sensor and step_detect_sensor? What is the best practice using those sensors or using own logic?
Most of the Android devices doesn’t have an inbuilt Step Counter Sensor. In that case use my code. My code works on accelerometer.
Hey man,
I would love if you commented your code and possibly tossed it on github 🙂
Sure.
This is not working for me 🙁
Do you have any references from where you got the formulas in SensorFilter class? Would you give me some information please..
This code is very helpful for me.
sir in future , can i ask any question regarding to this code and about pedoMeter
In this code ,do you have any permission required in manifest
Well, what is the inside algorithm?
How do you figure out this from scratch?
Awesome! Would you mind putting the codes on github?
Definitely I will take out some time to put it on GitHub with a sample project as I am getting lot of queries about this article.
Do you have any references from where you got the formulas in SensorFilter class? Would you give me some information please
pedometer not working while walking….but working on shake up device. When i put my device in pocket by click start button then move steps..after steps,the number of steps remain same..not working
STEP_THRESHOLD and STEP_DELAY_NS are not appropriate for step detect. Step increases when hang the phone up and down.
Are there no import statement? I cannot get this to compile at all. The errors are mainly that the compiler cannot find things.
what is the algorithm here? only sensor filter?
Do you have any references from where you got the formulas in SensorFilter class? Would you give me some information please
this is formulas ERSP Energy-efficiet Real Time Smartphone Pedometer ?
I am unable to understand and compile with the above example. Someone help me out either in concepts of how to create or provide me the complete working code
I am unable to buid with the above example. Someone help me out either in concepts of how to create or provide me the complete working code
Thanks man!
I used your code. It counts the steps when motion is detected. But there are some problems in it. I have posted a question regarding it on StackOverflow at https://stackoverflow.com/questions/46823952/pedometer-step-counter-in-android.Can you please address these problems. Thank you
Can the app still running after exit the app ?
i have one problem like: Sensor and Listener is Null .
what is mean of this please help me
Hey can we make service for this . if yes how can please tell me
Thanks for sharing the algorithm.
How can I calculate the distance?
how to maximize the threashold sensitivity?
50f mean float so we have to make it for ex 500f to make it more sensitive?
Thanks brother this code is working properly little bit errors were occur but in others comments on this post there was a solution for these errors .
but i need one favor can you please describe ho this code is working i have a project code demo on 4th dec 2017.
I have noticed you don’t monetize your site, don’t waste your traffic, you can earn additional cash every month
because you’ve got hi quality content. If you want to know how to make extra bucks, search
for: Boorfe’s tips best adsense alternative
Hi, nice post.
How can I find if someone is climbing steps up or down?
Rishav and everyone who says that pedometer doesn’t work in pocket!
I had the same problem and first I thought that the algorythm was wrong.
I changed the threshold value but that didn’t help.
And finally I’ve got the solution (though I’m not saying for all devices).
The point is that Android turns on the save energy mode when you turn off the screen. System saves the resourses being in a sleeping mode and your app stops counting steps.
Read about the PowerManager WakeLock and the WAKE_LOCK permission, that’s what helped me (it keeps CPU in working state even if the screen is turned off). Just now I’ve tried to count steps with my device (screen off) in a back pocket and it works great even with a standart threshold = 50.
Thanks for sharing this algorythm, it’s great.
Woah this is cool! thanks alot could you complete this project ? with simple weekly graph?
I have noticed you don’t monetize your website, don’t waste your traffic, you can earn additional bucks every
month because you’ve got high quality content. If you want to know
how to make extra money, search for: Mertiso’s tips best adsense alternative
When i click the start and stop button nothing happens
I have checked your blog and i’ve found some duplicate content, that’s why you don’t rank
high in google’s search results, but there is a tool that can help you to create 100% unique content,
search for; Best article rewritwer Ercannou’s essential tools
I can show the steps count on next page(todays steps) the method is????
Hello and nice code.
In some phones (Samsung) a message is shown that the app is consuming a lot of battery…
May be necesary some parameter modification in STEP_DELAY_NS or SENSOR_DELAY_FASTEST or where?