Search code examples
androidandroid-10.0

Android 10 - how to DISABLE VIBRATION for "Ring Volume without activating "do not disturb"


On Android 10 I am trying to disable the vibration for "Ring Volume".
So I am trying to reach the state on the image, which I can reach via the UI - programmatically.

  • Disabled vibration of Ring Volume
  • Do not Disturb mode off

enter image description here

Problem:

I tried using the AudioManager.setRingerMode() Its spec says:

    /**
     * Sets the ringer mode.
     * <p>
     * Silent mode will mute the volume and will not vibrate. Vibrate mode will
     * mute the volume and vibrate. Normal mode will be audible and may vibrate
     * according to user settings.
     * <p>This method has no effect if the device implements a fixed volume policy
     * as indicated by {@link #isVolumeFixed()}.
     * * <p>From N onward, ringer mode adjustments that would toggle Do Not Disturb are not allowed
     * unless the app has been granted Do Not Disturb Access.
     * See {@link NotificationManager#isNotificationPolicyAccessGranted()}.
     * @param ringerMode The ringer mode, one of {@link #RINGER_MODE_NORMAL},
     *            {@link #RINGER_MODE_SILENT}, or {@link #RINGER_MODE_VIBRATE}.
     * @see #getRingerMode()
     * @see #isVolumeFixed()
     */
    public void setRingerMode(int ringerMode) {

Sound like it would be the way to reach the state on the image.

But the code below activates the "Do not Disturb" mode. Which despite of disabling the Vibration also has a lot of other effects: suppress the notifications etc. which I do not want to activate.

See image below

final AudioManager audio = (AudioManager) mContext.getSystemService(mContext.AUDIO_SERVICE);
audio.setRingerMode(AudioManager.RINGER_MODE_SILENT);

Is the state on the picture above - unreachable programmatically?
According to this thread - Enable Silent Mode in android without triggering Do Not Disturb it is unreachable?

Do not DIsturb activates on RINGER_MODE_SILENT

enter image description here


Solution

  • I have found more about behavior described. DND mode activates - when

    1. there was a command to go into the vibrate mode audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
    2. When the phone (or the emulator in my case) does not have support for Vibration.

    To support vibrate, silent, normal modes, and the ability to adjust the volume without going to DND mode enter image description here enter image description here enter image description here I do the following:

    private void adjustVolume(double ringAndNotificationsVolumeInPercent, int ringMode) {
    
        // ringer mode applies to notification
        final AudioManager audioManager = (AudioManager) context.getSystemService(context.AUDIO_SERVICE);
    
         // ALWAYS set the ringer mode, cause changing the volume might implicitly change the mode
        switch (ringMode) {
            case AudioManager.RINGER_MODE_SILENT:
                /**
                 * This is a tricky one:
                 *
                 * The goal is - to just disable Vibration and set volume to 0.
                 *
                 * using
                 * audioManager.setRingerMode(AudioManager.RINGER_MODE_SILENT);
                 * sets the phone to to "DontDisturb" mode,
                 * having a lot of side effects: like supressing notifications etc.
                 *
                 * Instead - setting the phone to "RINGER_MODE_NORMAL",
                 * then adjusting the volume - has the correct effect.
                 */
                audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
                audioManager.adjustStreamVolume(AudioManager.STREAM_NOTIFICATION, AudioManager.ADJUST_MUTE, AudioManager.FLAG_VIBRATE);
                break;
    
            case AudioManager.RINGER_MODE_VIBRATE:
                Log.d(TAG, "vibrate mode");
                if (utilsVolume.isDontDisturbOff()) {
    
                    // if there is no vibrate mode - the OS may set the phone to DontDisturb
                    audioManager.setRingerMode(AudioManager.RINGER_MODE_VIBRATE);
                } else {
                    Log.d(TAG, "Cant enable vibration mode, cause the Dont DIsturb Mode is on. It would cause ");
                }
                break;
    
            case AudioManager.RINGER_MODE_NORMAL:
                audioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
    
                // adjust volume
                setSoundRelativeToMax(ringAndNotificationsVolumeInPercent, AudioManager.STREAM_NOTIFICATION);
                setSoundRelativeToMax(ringAndNotificationsVolumeInPercent, AudioManager.STREAM_RING);
                break;
    
            default:
                Log.d("TAG", "Ignore unknown RINGER_MODE " + ringMode);
                break;
        }
    }
    
    private void setSoundRelativeToMax(double percent, int streamType) {
        // requested rights in MainActivity
        final AudioManager audio = (AudioManager) context.getSystemService(context.AUDIO_SERVICE);
    
        int maxVolume = audio.getStreamMaxVolume(streamType);
        int seventyVolume = (int) (maxVolume * percent);
        audio.setStreamVolume(streamType, seventyVolume, 0);
    }