Open In App

How to Build a Step Counting Application in Android Studio?

Improve
Improve
Like Article
Like
Save
Share
Report

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 the 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. Note that select Kotlin as the programming language.

Step 2: Working with AndroidManifest.xml for taking permission from the user

Navigate to the app/manifests/AndroidManifest.xml and write 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: Adding a drawable resource file 

Navigate to app/res/drawable and right-click on the drawable folder and go to New/Drawable Resource File

Name the file as the circle and with the default settings, click on the ok button.

Step 4: Working with drawable resource file

In this step, we will add the code to the resource file. We are making a circular stroke to use it, in the ImageView in the main XML file of the app. Below is the code for the circle.xml resource file that we made It in the previous step.

XML




<?xml version="1.0" encoding="utf-8"?>
    <item>
          <!-- creates an oval shape -->
        <shape android:shape="oval">
            
              <!-- giving the color and width to the stroke -->
            <stroke android:color="#0F9D58" android:width="3dp"/>
           
              <!-- giving the width and the height to the shape -->
            <size android:width="120dp" android:height="120dp"/>
        </shape>
    </item>
 
</selector>


Step 5: Working with the activity_main.xml file

Navigate to the app/res/layout/activity_main.xml and add the below code to that file. Below is the code for the activity_main.xml file. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    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:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="290dp"
        android:text="Steps"
        android:textSize="45sp"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
    <!--Text View for the step count-->
    <TextView
        android:id="@+id/tv_stepsTaken"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="30dp"
        android:text="0"
        android:textSize="37sp"
        android:textColor="@color/black"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/steps" />
 
    <!--Image View for the circle-->
    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_marginTop="264dp"
        android:background="@drawable/circle"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
     
</androidx.constraintlayout.widget.ConstraintLayout>


Step 6: Working with the MainActivity.kt file

Go to the MainActivity.kt file and refer to the following code. Below is the code for the MainActivity.kt file. Comments are added inside the code to understand the code in more detail.

Kotlin




import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.widget.TextView
import android.widget.Toast
 
class MainActivity : AppCompatActivity(), SensorEventListener {
      // Added SensorEventListener the MainActivity class
    // Implement all the members in the class MainActivity
    // after adding SensorEventListener
 
      // we have assigned sensorManger to nullable
    private var sensorManager: SensorManager? = null
 
      // Creating a variable which will give the running status
    // and initially given the boolean value as false
    private var running = false
   
      // Creating a variable which will counts total steps
    // and it has been given the value of 0 float
    private var totalSteps = 0f
   
      // Creating a variable  which counts previous total
    // steps and it has also been given the value of 0 float
    private var previousTotalSteps = 0f
 
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        loadData()
        resetSteps()
         
        // Adding a context of SENSOR_SERVICE as Sensor Manager
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
    }
 
    override fun onResume() {
        super.onResume()
        running = true
       
          // Returns the number of steps taken by the user since the last reboot while activated
        // This sensor requires permission android.permission.ACTIVITY_RECOGNITION.
          // So don't forget to add the following permission in AndroidManifest.xml present in manifest folder of the app.
        val stepSensor = sensorManager?.getDefaultSensor(Sensor.TYPE_STEP_COUNTER)
       
 
        if (stepSensor == null) {        
              // This will give a toast message to the user if there is no sensor in the device
            Toast.makeText(this, "No sensor detected on this device", Toast.LENGTH_SHORT).show()
        } else {         
              // Rate suitable for the user interface
            sensorManager?.registerListener(this, stepSensor, SensorManager.SENSOR_DELAY_UI)
        }
    }
 
    override fun onSensorChanged(event: SensorEvent?) {
       
          // Calling the TextView that we made in activity_main.xml
        // by the id given to that TextView
        var tv_stepsTaken = findViewById<TextView>(R.id.tv_stepsTaken)
         
        if (running) {
            totalSteps = event!!.values[0]
               
              // Current steps are calculated by taking the difference of total steps
            // and previous steps
            val currentSteps = totalSteps.toInt() - previousTotalSteps.toInt()
             
            // It will show the current steps to the user
            tv_stepsTaken.text = ("$currentSteps")
        }
    }
 
    fun resetSteps() {
        var tv_stepsTaken = findViewById<TextView>(R.id.tv_stepsTaken)
        tv_stepsTaken.setOnClickListener {         
              // This will give a toast message if the user want to reset the steps
            Toast.makeText(this, "Long tap to reset steps", Toast.LENGTH_SHORT).show()
        }
 
        tv_stepsTaken.setOnLongClickListener {
           
            previousTotalSteps = totalSteps
           
              // When the user will click long tap on the screen,
            // the steps will be reset to 0
            tv_stepsTaken.text = 0.toString()
             
            // This will save the data
            saveData()
 
            true
        }
    }
 
    private fun saveData() {
       
        // Shared Preferences will allow us to save
          // and retrieve data in the form of key,value pair.
        // In this function we will save data
        val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
         
        val editor = sharedPreferences.edit()
        editor.putFloat("key1", previousTotalSteps)
        editor.apply()
    }
 
    private fun loadData() {
       
        // In this function we will retrieve data
        val sharedPreferences = getSharedPreferences("myPrefs", Context.MODE_PRIVATE)
        val savedNumber = sharedPreferences.getFloat("key1", 0f)
         
        // Log.d is used for debugging purposes
        Log.d("MainActivity", "$savedNumber")
         
        previousTotalSteps = savedNumber
    }
 
    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
          // We do not have to write anything in this function for this app
    }
}


Now run the app and see the output of the code below: 

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.


Last Updated : 29 Nov, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads