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 version="1.0" encoding="utf-8"?>
<resources>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="colorPrimary">#0f9d58</color>
<color name="colorPrimaryDark">#006d2d</color>
<color name="colorAccent">#55cf86</color>
</resources>
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.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="@android:color/white"/>
</shape>
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 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"
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.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:fromXScale="1.75"
android:toXScale="1"
android:fromYScale="1.75"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:fromXScale="1"
android:toXScale="1.75"
android:fromYScale="1"
android:toYScale="1.75"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:fromXScale="2"
android:toXScale="1"
android:fromYScale="2"
android:toYScale="1"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<scale
android:fromXScale="1"
android:toXScale="2"
android:fromYScale="1"
android:toYScale="2"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
Step 6: Working with MainActivity file
Navigate to app > java > {package-name} > MainActivity.kt/MainActivity.java and add the following code.
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) {}
};
}
@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