How to Control Volume using Android SeekBar in Java

Nitish Kumar Singh

Nov 16, 2023

Hello Developers! In this blog post, we will learn how to change volume using SeekBar in Android using Java. Basically we increase or decrease system volume of phone when progress of SeekBar chnages and show a TextView for volume level.

Photo by Adrien on Unsplash

To change the volume of phone, we add SeekBar.OnSeekChangeListener on SeekBar to get progress and use AudioManager  and it's methods to change phone volume in following steps:

Setup SeekBar

Add following xml in your activity layout file and you can design it as your requirements.

.....
  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:orientation="horizontal">
      <TextView
         android:id="@+id/volumeLevel"
         android:layout_width="60dp"
         android:layout_height="match_parent"
         android:gravity="center"
         android:textSize="15sp"/>
      <SeekBar
         android:id="@+id/volumeSlider"
         android:layout_width="0dp"
         android:layout_weight="1"
         android:layout_height="30dp"
         android:layout_marginStart="10dp"
         android:layout_marginEnd="10dp"
         android:layout_gravity="center"/>
  </LinearLayout>
.....

Initialize TextView and SeekBar, add SeekBar.OnSeekChangeListener on SeekBar and setMax value on SeekBar as you want in onCreate of activity java file.

    TextView volumeLevel = findViewById(R.id.volumeLevel);
    SeekBar volumeSlider = findViewById(R.id.volumeSlider);
    volumeSlider.setMax(maxProgress); // it will come from maxProgress variable
    
    // There are more code available
    
    volumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
              
            
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });

Change Volume Using AudioManager

We use getStreamMaxVolumegetStreamMinVolumegetStreamVolume and setStreamVolume methods of AudioManager to change volume of MUSIC_STREAM, but you can change any stream volume with the same way.

Declare three variables above onCreate as below:

    private final int maxProgress = 25; // you can set it as you want
    private int minVolumeIndex,maxVolumeIndex;

The above variables maxProgress use for setting max value on seekbar (here i use 25), minVolumeIndex and maxVolumeIndex use to store min and max volume index. So we calculate volume index based on progress of seekbar.

Add follwing code in onCreate above setOnSeekBarChangeListener:

    // initialize min and max volumeIndex
    AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
    maxVolumeIndex = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
    minVolumeIndex = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ?
            audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC) : 0;
    // sync progress of seekbar and textview with current volume
    int currentVolume  = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
    int progress = getSeekBarProgressFromVolume(currentVolume);
    volumeSlider.setProgress(progress);
    volumeLevel.setText(String.valueOf(progress));

Add following code in onProgressChanged method of  SeekBar.OnSeekBarChangeListener:

    if (fromUser){
        int volumeIndex = getRightVolume(progress);
        audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,volumeIndex,0);
        volumeLevel.setText(String.valueOf(progress));
    }

If you want to change volume of different stream then use that stream constant at all places where used AudioManager.STREAM_MUSIC.

Create two method in activity java file as below code:

    private int getRightVolume(int input) {
        // Ensure that the input is within the valid range (0 to a maxValue)
        input = Math.max(0, Math.min(input, maxProgress));

        // Calculate the right volume index from minVolumeIndex(x) to maxVolumeIndex(y)
        double ratio = (double) input / (maxProgress + 1);
        return (int) Math.round(minVolumeIndex + (maxVolumeIndex - minVolumeIndex) * ratio);
    }
    private int getSeekBarProgressFromVolume(int value) {
        // Calculate the reverse interpolated input based on the value
        double ratio = (double) (value - minVolumeIndex) / (maxVolumeIndex - minVolumeIndex);
        int result = (int) Math.round(ratio * maxProgress);

        // Ensure that the result is within the valid range (0 to maxValue)
        return Math.max(0, Math.min(result, maxProgress));
    }

getRightVolume method use to get right volume index based on progress and max of seekbar, and getSeekBarProgressFromVolume use to get progress of seekbar based on current volume index (level) of phone so we set progress of seekbar and text on textview on first time when activity created.

So below is final code of activity java file:

    private final int maxProgress = 25; // you can set it as you want
    private int minVolumeIndex,maxVolumeIndex;

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

        TextView volumeLevel = findViewById(R.id.volumeLevel);
        SeekBar volumeSlider = findViewById(R.id.volumeSlider);
        volumeSlider.setMax(maxProgress); // it will come from maxProgress variable

        // initialize min and max volumeIndex
        AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
        maxVolumeIndex = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        minVolumeIndex = Build.VERSION.SDK_INT >= Build.VERSION_CODES.P ?
                audioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC) : 0;
        // sync progress of seekbar and textview with current volume
        int currentVolume  = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        int progress = getSeekBarProgressFromVolume(currentVolume);
        volumeSlider.setProgress(progress);
        volumeLevel.setText(String.valueOf(progress));

        volumeSlider.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser){
                    int volumeIndex = getRightVolume(progress);
                    audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,volumeIndex,0);
                    volumeLevel.setText(String.valueOf(progress));
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });
    }
    private int getRightVolume(int input) {
        // Ensure that the input is within the valid range (0 to a maxValue)
        input = Math.max(0, Math.min(input, maxProgress));

        // Calculate the right volume index from minVolumeIndex(x) to maxVolumeIndex(y)
        double ratio = (double) input / (maxProgress + 1);
        return (int) Math.round(minVolumeIndex + (maxVolumeIndex - minVolumeIndex) * ratio);
    }
    private int getSeekBarProgressFromVolume(int value) {
        // Calculate the reverse interpolated input based on the value
        double ratio = (double) (value - minVolumeIndex) / (maxVolumeIndex - minVolumeIndex);
        int result = (int) Math.round(ratio * maxProgress);

        // Ensure that the result is within the valid range (0 to maxValue)
        return Math.max(0, Math.min(result, maxProgress));
    }

I hope you learned how to change volume of any stream using seekbar and enjoyed this blog post.

Published on Nov 15, 2023
Comments (undefined)

Read More