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