2

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

Skip
  • 6,240
  • 11
  • 67
  • 117
  • have you found any answer? I am trying something similar and in emulator, I can see it works when you click the bell icon above volume slider which invokes a silent mode rather than DND. – Gautam Apr 12 '20 at 13:25
  • Hi, I havent found any answer unfortunately :( – Skip Apr 15 '20 at 13:08
  • I have been trying to solve this for months now ... IMHO it is very vendor specific. It might work just with setting `RINGER_MODE_SILENT` or it will force the `DnD` every time. You can try fiddling with the interruption filters, but again it depends on the vendor. It is just ridiculous. – CAPS LOCK May 28 '20 at 19:07
  • I have tried that on a Google Phone (Pixel3) and found no solution. Assuming, that Google implements its own spec correctly - I assme, that right now there is no solution. – Skip Jun 03 '20 at 07:21
  • Even if Google implements changes, other vendors might not include it. Besides, older devices will never get updated and that makes the problem for apps that rely on this API even worse. It looks like there is nothing we can do about it ... – CAPS LOCK Jul 14 '20 at 08:24
  • I am trying on a Pixel device. Its Google hardware... – Skip Jul 16 '20 at 19:40
  • Sure. In the previous comment I was referring to all impacted devices. – CAPS LOCK Jul 21 '20 at 12:50

1 Answers1

1

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);
}
Skip
  • 6,240
  • 11
  • 67
  • 117