How to Build a Step Counting Application in Android Studio? (original) (raw)

Last Updated : 23 Jul, 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.

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 `

<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

<stroke android:color="@color/colorPrimary" android:width="3dp"/>
<size android:width="120dp" android:height="120dp"/>

`

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.