Android - VolumeProviderCompat and setCurrentVolume

    Android support library developers used a wrapper and delegate pattern to support MediaSession and VolumeProvider for pre-lollipop versions. A volume provider is a callback registered on an active media session to be notified of volume events. VolumeProviderCompat like any other compat APIs is supposed to enable support in older platform versions. Its API set includes all VolumeProvider's APIs and ideally should facilitate quick development. However, few APIs like setCurrentVolume and getCurrentVolume (when used in Lollipop) doesn't seem to work at all.

    Turns out that mCurrentVolume in VolumeProviderCompat isn't even updated. So getCurrentVolume() is never going to return the expected values.

    public final void setCurrentVolume(int currentVolume) {
        if (mCallback != null) {
            mCallback.onVolumeChanged(this);
        }
    }

    Besides, the actual request to update the volume is never relayed to the underlying implementation, VolumeProvider by the wrapper, VolumeProviderCompatApi21.

class VolumeProviderCompatApi21 {
    public static Object createVolumeProvider(int volumeControl, int maxVolume, int currentVolume,
            final Delegate delegate) {
        return new VolumeProvider(volumeControl, maxVolume, currentVolume) {
            @Override
            public void onSetVolumeTo(int volume) {
                delegate.onSetVolumeTo(volume);
            }

            @Override
            public void onAdjustVolume(int direction) {
                delegate.onAdjustVolume(direction);
            }
        };
    }

    public static void setCurrentVolume(Object volumeProviderObj, int currentVolume) {
        ((VolumeProvider) volumeProviderObj).setCurrentVolume(currentVolume);
    }

    public interface Delegate {
        void onSetVolumeTo(int volume);
        void onAdjustVolume(int delta);
    }
}

  Fortunately, this is confirmed by support library developers (link) and a fix should hopefully be out soon. Meanwhile, the recommendation (when using support library 22.2.1) is just to get the underlying volume provider and use its APIs. Unfortunately, this needs a if/else based on the SDK_VERSION as VolumeProvider is available only in 21+ and kind of defeats the point of using a compact API. Ugly but necessary.

          VolumeProviderCompat compatProvider;
          ((VolumeProvider) compatProvider.getVolumeProvider()).getCurrentVolume()


No comments: