How to Build a Step Counting Application in Android Studio?
Last Updated :
03 Apr, 2025
Many of us have used the step counter on our phones while we go for walk or run. It counts the total steps that the user has walked and displays it on the screen. The other name for the step counter is a pedometer. But have you ever thought about how can an app count our steps? What is the coding behind the working of this app? Let's find the answer to these questions by making one.
What are we going to build in this article?
We will be building an application that displays the steps that the user has walked. We will use TextView in our XML file which will show the step count and a heading on the screen, and one ImageView for displaying the circle around the text. When the user will tap for a long time on the screen it will get reset to 0. A sample GIF is given below to get an idea about what we are going to do in this article.
Note that we are going to implement the application using Java/Kotlin language.
Step by Step Implementation
Step 1: Create a New Project
To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio.
Step 2: Adding permissions
Navigate to the app > manifests > AndroidManifest.xml and add the code given below in the manifest for taking the user permission for Activity Recognition.
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
Step 3: Working with the activity_main.xml file
Navigate to the app > res > layout > activity_main.xml and add the below code. Also create a drawable in app > res > drawable folder and name it as circle.xml. The code for both the files are given below.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<!--Text View for the "Steps" displayed-->
<TextView
android:id="@+id/steps"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Steps"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@+id/tv_stepsTaken"
app:layout_constraintEnd_toEndOf="@+id/tv_stepsTaken"
app:layout_constraintStart_toStartOf="@+id/tv_stepsTaken" />
<!--Text View for the step count-->
<TextView
android:id="@+id/tv_stepsTaken"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0"
android:textColor="@color/black"
android:textSize="100sp"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@+id/imageView"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toTopOf="@+id/imageView" />
<!--Image View for the circle-->
<ImageView
android:id="@+id/imageView"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/circle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<stroke android:color="@color/colorPrimary" android:width="3dp"/>
<size android:width="120dp" android:height="120dp"/>
</shape>
Step 4: Working with the MainActivity file
Go to the MainActivity file and refer to the following code. Below is the code for the MainActivity file. Comments are added inside the code to understand the code in more detail.
MainActivity.java
package org.geeksforgeeks.demo;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity implements SensorEventListener {
// Declare sensor and sensor manager
private SensorManager sensorManager;
private Sensor stepSensor;
// Step counting variables
private boolean running = false;
private float totalSteps = 0f;
private float previousTotalSteps = 0f;
// UI Component
private TextView stepsTakenTextView;
private static final int PERMISSION_REQUEST_ACTIVITY_RECOGNITION = 100;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Check and request permission for Activity Recognition (Android 10+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (checkSelfPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{android.Manifest.permission.ACTIVITY_RECOGNITION}, PERMISSION_REQUEST_ACTIVITY_RECOGNITION);
}
}
// Define text view for step count
stepsTakenTextView = findViewById(R.id.tv_stepsTaken);
// Define sensor and sensor manager
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager != null) {
stepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER);
}
// Check if sensor is available
if (stepSensor == null) {
Toast.makeText(this, "No Step Counter Sensor found!", Toast.LENGTH_LONG).show();
}
loadData();
resetSteps();
}
// Register sensor when activity starts
@Override
protected void onStart() {
super.onStart();
registerSensor();
}
// Unregister sensor when activity stops
@Override
protected void onStop() {
super.onStop();
sensorManager.unregisterListener(this);
}
// Register step counter sensor
private void registerSensor() {
if (stepSensor != null) {
sensorManager.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_UI);
Log.d("Step Counter", "Step Sensor Registered");
}
}
// Handle step counter changes
@Override
public void onSensorChanged(SensorEvent event) {
if (event == null) return;
Log.d("Step Counter", "Sensor event received: " + event.values[0]);
// Update step count
if (running) {
totalSteps = event.values[0];
int currentSteps = (int) (totalSteps - previousTotalSteps);
stepsTakenTextView.setText(String.valueOf(currentSteps));
}
}
// Handle resume event
@Override
protected void onResume() {
super.onResume();
running = true;
registerSensor();
}
// Handle pause event
@Override
protected void onPause() {
super.onPause();
running = false;
}
// Handle long press to reset steps
private void resetSteps() {
stepsTakenTextView.setOnClickListener(v ->
Toast.makeText(MainActivity.this, "Long press to reset steps", Toast.LENGTH_SHORT).show()
);
stepsTakenTextView.setOnLongClickListener(v -> {
previousTotalSteps = totalSteps;
stepsTakenTextView.setText("0");
saveData();
return true;
});
}
// Save step count
private void saveData() {
SharedPreferences sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putFloat("key1", previousTotalSteps);
editor.apply();
Log.d("Step Counter", "Steps saved: " + previousTotalSteps);
}
// Load step count
private void loadData() {
SharedPreferences sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE);
previousTotalSteps = sharedPreferences.getFloat("key1", 0f);
Log.d("Step Counter", "Loaded steps: " + previousTotalSteps);
}
// Handle permission request results
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_ACTIVITY_RECOGNITION) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Toast.makeText(this, "Permission Granted", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Permission Denied", Toast.LENGTH_SHORT).show();
}
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
MainActivity.kt
package org.geeksforgeeks.demo
import android.content.Context
import android.content.pm.PackageManager
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity(), SensorEventListener {
// initialize sensor and sensor manager
private lateinit var sensorManager: SensorManager
private var stepSensor: Sensor? = null
// initialize variable for step count and to give the running status
private var running = false
private var totalSteps = 0f
private var previousTotalSteps = 0f
// initialize text view for step count
private lateinit var stepsTakenTextView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Check and request permission for Activity Recognition (Android 10+)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (checkSelfPermission(android.Manifest.permission.ACTIVITY_RECOGNITION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(arrayOf(android.Manifest.permission.ACTIVITY_RECOGNITION), 100)
}
}
// define text view for step count
stepsTakenTextView = findViewById(R.id.tv_stepsTaken)
// define sensor and sensor manager
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
stepSensor = sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
// check if sensor is available
if (stepSensor == null) {
Toast.makeText(this, "No Step Counter Sensor found!", Toast.LENGTH_LONG).show()
}
loadData()
resetSteps()
}
// register sensor to listen for changes
override fun onStart() {
super.onStart()
registerSensor()
}
// unregister sensor to stop listening for changes
override fun onStop() {
super.onStop()
sensorManager.unregisterListener(this)
}
// register sensor to listen for changes
private fun registerSensor() {
if (stepSensor != null) {
sensorManager.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_UI)
Log.d("Step Counter", "Step Sensor Registered")
}
}
// handle sensor event
override fun onSensorChanged(event: SensorEvent?) {
if (event == null) return
Log.d("Step Counter", "Sensor event received: ${event.values[0]}")
// update step count
if (running) {
totalSteps = event.values[0]
val currentSteps = (totalSteps - previousTotalSteps).toInt()
stepsTakenTextView.text = "$currentSteps"
}
}
// handle resume event
override fun onResume() {
super.onResume()
running = true
registerSensor()
}
// handle pause event
override fun onPause() {
super.onPause()
running = false
}
// handle long press to reset steps
private fun resetSteps() {
stepsTakenTextView.setOnClickListener {
Toast.makeText(this, "Long press to reset steps", Toast.LENGTH_SHORT).show()
}
stepsTakenTextView.setOnLongClickListener {
previousTotalSteps = totalSteps
stepsTakenTextView.text = "0"
saveData()
true
}
}
// save step count
private fun saveData() {
val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
val editor = sharedPreferences.edit()
editor.putFloat("key1", previousTotalSteps)
editor.apply()
Log.d("Step Counter", "Steps saved: $previousTotalSteps")
}
// load step count
private fun loadData() {
val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
previousTotalSteps = sharedPreferences.getFloat("key1", 0f)
Log.d("Step Counter", "Loaded steps: $previousTotalSteps")
}
// handle accuracy change
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {}
}
Output:
Note: We have to allow the permission required for the app by going to app settings and then enabling it.
It will not count the steps in the emulator, you have to use a real android device to test it.
Similar Reads
Non-linear Components In electrical circuits, Non-linear Components are electronic devices that need an external power source to operate actively. Non-Linear Components are those that are changed with respect to the voltage and current. Elements that do not follow ohm's law are called Non-linear Components. Non-linear Co
11 min read
Spring Boot Tutorial Spring Boot is a Java framework that makes it easier to create and run Java applications. It simplifies the configuration and setup process, allowing developers to focus more on writing code for their applications. This Spring Boot Tutorial is a comprehensive guide that covers both basic and advance
10 min read
Class Diagram | Unified Modeling Language (UML) A UML class diagram is a visual tool that represents the structure of a system by showing its classes, attributes, methods, and the relationships between them. It helps everyone involved in a projectâlike developers and designersâunderstand how the system is organized and how its components interact
12 min read
Backpropagation in Neural Network Back Propagation is also known as "Backward Propagation of Errors" is a method used to train neural network . Its goal is to reduce the difference between the modelâs predicted output and the actual output by adjusting the weights and biases in the network.It works iteratively to adjust weights and
9 min read
3-Phase Inverter An inverter is a fundamental electrical device designed primarily for the conversion of direct current into alternating current . This versatile device , also known as a variable frequency drive , plays a vital role in a wide range of applications , including variable frequency drives and high power
13 min read
Polymorphism in Java Polymorphism in Java is one of the core concepts in object-oriented programming (OOP) that allows objects to behave differently based on their specific class type. The word polymorphism means having many forms, and it comes from the Greek words poly (many) and morph (forms), this means one entity ca
7 min read
CTE in SQL In SQL, a Common Table Expression (CTE) is an essential tool for simplifying complex queries and making them more readable. By defining temporary result sets that can be referenced multiple times, a CTE in SQL allows developers to break down complicated logic into manageable parts. CTEs help with hi
6 min read
What is Vacuum Circuit Breaker? A vacuum circuit breaker is a type of breaker that utilizes a vacuum as the medium to extinguish electrical arcs. Within this circuit breaker, there is a vacuum interrupter that houses the stationary and mobile contacts in a permanently sealed enclosure. When the contacts are separated in a high vac
13 min read
Python Variables In Python, variables are used to store data that can be referenced and manipulated during program execution. A variable is essentially a name that is assigned to a value. Unlike many other programming languages, Python variables do not require explicit declaration of type. The type of the variable i
6 min read
Spring Boot Interview Questions and Answers Spring Boot is a Java-based framework used to develop stand-alone, production-ready applications with minimal configuration. Introduced by Pivotal in 2014, it simplifies the development of Spring applications by offering embedded servers, auto-configuration, and fast startup. Many top companies, inc
15+ min read