How to Build a Simple Android App for Breathing Exercise? (original) (raw)

Last Updated : 23 Jul, 2025

Android mobiles are very handy, and they provide the information instantaneously. Just assume that you are continuously flying or attending patients or participating in meetings etc., very often. During those times, there are possibilities of getting stressed and hence meditation is very much essential in this fast running lives. Here providing the source code for the breathing exercise app and surely that will be helpful to get more energetic and enthusiastic.

Steps to Implement Breathing Exercise in Android

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: Add colors

Go to the **app > res > values > colors.xml file and set the colors for your app.

**colors.xml:

XML `

#FF000000 #FFFFFFFF #0f9d58 #006d2d #55cf86

`

Step 3: Create 2 drawables

Create a drawable for setting the background of the screen and a drawable for the background and circle shape of the breathing view.

background.xml `

<solid android:color="@android:color/white"/>

bg\_circle.xml

`

Step 4: Working with activity_main.xml

Go to the **activity_main.xml file and refer to the following code. Below is the code for the **activity_main.xml file.

**activity_main.xml:

XML `

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/background">

<View
    android:id="@+id/circle"
    android:layout_width="150dp"
    android:layout_height="150dp"
    android:background="@drawable/bg_circle"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"/>

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="INHALE"
    android:textSize="18sp"
    android:textStyle="bold"
    android:textColor="#4dd1b2"
    app:layout_constraintBottom_toBottomOf="@id/circle"
    app:layout_constraintTop_toTopOf="@id/circle"
    app:layout_constraintLeft_toLeftOf="@id/circle"
    app:layout_constraintRight_toRightOf="@id/circle"/>

</androidx.constraintlayout.widget.ConstraintLayout>

`

Step 5: Create 4 animations

Navigate to **app > res and right of the res folder and select **New > Android Resource Directory and set the name and type as **anim. Now in that folder create 4 animation files for circle and text inhale and exhale animations respectively.

anim_inner_circle_exhale.xml `

<scale
    android:fromXScale="1.75"
    android:toXScale="1"
    android:fromYScale="1.75"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"/>

anim\_inner\_circle\_inhale.xml

<scale
    android:fromXScale="1"
    android:toXScale="1.75"
    android:fromYScale="1"
    android:toYScale="1.75"
    android:pivotX="50%"
    android:pivotY="50%"/>

anim\_text\_exhale.xml

<scale
    android:fromXScale="2"
    android:toXScale="1"
    android:fromYScale="2"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"/>

anim\_text\_inhale.xml

<scale
    android:fromXScale="1"
    android:toXScale="2"
    android:fromYScale="1"
    android:toYScale="2"
    android:pivotX="50%"
    android:pivotY="50%"/>

`

Step 6: Working with MainActivity file

Navigate to **app > java > {package-name} > MainActivity.kt/MainActivity.java and add the following code.

MainActivity.java `

package org.geeksforgeeks.demo;

import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity { // Text indicating INHALE, HOLD, EXHALE private TextView statusText; // Circle that expands/contracts with breathing private View innerCircleView;

// Animation variables
private Animation animationInhaleText;
private Animation animationExhaleText;
private Animation animationInhaleInnerCircle;
private Animation animationExhaleInnerCircle;

// Handler for timing the hold phase
private final Handler handler = new Handler();

// Durations for inhale, exhale, and hold phases (in milliseconds)
private final int inhaleDuration = 6000;
private final int exhaleDuration = 6000;
private final int holdDuration = 6000;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    statusText = findViewById(R.id.textView);
    innerCircleView = findViewById(R.id.circle);

    // Load animations for breathing phases
    prepareAnimations();

    // Start the breathing cycle with inhale
    startInhale();
}

// Loads and sets up animations for inhale and exhale
private void prepareAnimations() {
    // Inhale animation: Text grows and stays large
    animationInhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_inhale);
    animationInhaleText.setDuration(inhaleDuration);
    animationInhaleText.setFillAfter(true);
    animationInhaleText.setAnimationListener(inhaleAnimationListener);

    animationInhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_inhale);
    animationInhaleInnerCircle.setDuration(inhaleDuration);
    animationInhaleInnerCircle.setFillAfter(true);

    // Exhale animation: Text shrinks and returns to normal
    animationExhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_exhale);
    animationExhaleText.setDuration(exhaleDuration);
    animationExhaleText.setAnimationListener(exhaleAnimationListener);

    animationExhaleInnerCircle = AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_exhale);
    animationExhaleInnerCircle.setDuration(exhaleDuration);
    animationExhaleInnerCircle.setFillAfter(true);
}

// Starts the inhale phase
private void startInhale() {
    statusText.setText("INHALE");
    statusText.startAnimation(animationInhaleText);
    innerCircleView.startAnimation(animationInhaleInnerCircle);
}

// Listener for inhale animation
private final Animation.AnimationListener inhaleAnimationListener = new Animation.AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        statusText.setText("HOLD");
        // Wait for the hold duration, then start the exhale phase
        handler.postDelayed(MainActivity.this::startExhale, holdDuration);
    }

    @Override
    public void onAnimationStart(Animation animation) {}

    @Override
    public void onAnimationRepeat(Animation animation) {}
};

// Starts the exhale phase
private void startExhale() {
    statusText.setText("EXHALE");
    statusText.startAnimation(animationExhaleText);
    innerCircleView.startAnimation(animationExhaleInnerCircle);
}

// Listener for exhale animation
private final Animation.AnimationListener exhaleAnimationListener = new Animation.AnimationListener() {
    @Override
    public void onAnimationEnd(Animation animation) {
        statusText.setText("HOLD");
        // Wait for the hold duration, then start inhale again
        handler.postDelayed(MainActivity.this::startInhale, holdDuration);
    }

    @Override
    public void onAnimationStart(Animation animation) {}

    @Override
    public void onAnimationRepeat(Animation animation) {}
};

}

MainActivity.kt

@file:Suppress("DEPRECATION") package org.geeksforgeeks.demo

import android.os.Bundle import android.os.Handler import android.view.View import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.TextView import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() { // Text indicating INHALE, HOLD, EXHALE private lateinit var statusText: TextView // Circle that expands/contracts with breathing private lateinit var innerCircleView: View

// Animation variables
private lateinit var animationInhaleText: Animation
private lateinit var animationExhaleText: Animation
private lateinit var animationInhaleInnerCircle: Animation
private lateinit var animationExhaleInnerCircle: Animation

// Handler for timing the hold phase
private val handler = Handler()

// Durations for inhale, exhale, and hold phases (in milliseconds)
private val inhaleDuration = 6000
private val exhaleDuration = 6000
private val holdDuration = 6000

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    statusText = findViewById(R.id.textView)
    innerCircleView = findViewById(R.id.circle)

    // Load animations for breathing phases
    prepareAnimations()

    // Start the breathing cycle with inhale
    startInhale()
}

// Loads and sets up animations for inhale and exhale
private fun prepareAnimations() {
    // Inhale animation: Text grows and stays large
    animationInhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_inhale).apply {
        duration = inhaleDuration.toLong()
        // Keeps text in final state after animation
        fillAfter = true
        // Calls listener when animation ends
        setAnimationListener(inhaleAnimationListener)
    }
    animationInhaleInnerCircle =
        AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_inhale).apply {
            duration = inhaleDuration.toLong()
            // Keeps circle expanded
            fillAfter = true
        }

    // Exhale animation: Text shrinks and returns to normal
    animationExhaleText = AnimationUtils.loadAnimation(this, R.anim.anim_text_exhale).apply {
        duration = exhaleDuration.toLong()
        setAnimationListener(exhaleAnimationListener)
    }
    animationExhaleInnerCircle =
        AnimationUtils.loadAnimation(this, R.anim.anim_inner_circle_exhale).apply {
            duration = exhaleDuration.toLong()
            // Keeps circle contracted
            fillAfter = true
        }
}

// Starts the inhale phase
private fun startInhale() {
    statusText.text = "INHALE"
    statusText.startAnimation(animationInhaleText)
    innerCircleView.startAnimation(animationInhaleInnerCircle)
}

// Listener for inhale animation
private val inhaleAnimationListener = object : Animation.AnimationListener {
    override fun onAnimationEnd(animation: Animation) {
        statusText.text = "HOLD"
        // Wait for the hold duration, then start the exhale phase
        handler.postDelayed({ startExhale() }, holdDuration.toLong())
    }

    override fun onAnimationStart(animation: Animation) {}
    override fun onAnimationRepeat(animation: Animation) {}
}

// Starts the exhale phase
private fun startExhale() {
    statusText.text = "EXHALE"
    statusText.startAnimation(animationExhaleText)
    innerCircleView.startAnimation(animationExhaleInnerCircle)
}

// Listener for exhale animation
private val exhaleAnimationListener = object : Animation.AnimationListener {
    override fun onAnimationEnd(animation: Animation) {
        statusText.text = "HOLD"
        // Wait for the hold duration, then start inhale again
        handler.postDelayed({ startInhale() }, holdDuration.toLong())
    }

    override fun onAnimationStart(animation: Animation) {}
    override fun onAnimationRepeat(animation: Animation) {}
}

}

`

**Refer to the following repo to get the entire code: Breathing_Exercise_in_Android

Output: