public class

AudioFocusRequestCompat

extends java.lang.Object

 java.lang.Object

↳androidx.media.AudioFocusRequestCompat

Gradle dependencies

compile group: 'androidx.media', name: 'media', version: '1.7.0'

  • groupId: androidx.media
  • artifactId: media
  • version: 1.7.0

Artifact androidx.media:media:1.7.0 it located at Google repository (https://maven.google.com/)

Androidx artifact mapping:

androidx.media:media com.android.support:support-media-compat

Overview

Compatibility version of an .

Summary

Methods
public booleanequals(java.lang.Object o)

public AudioAttributesCompatgetAudioAttributesCompat()

Gets the AudioAttributesCompat set for this AudioFocusRequestCompat, or the default attributes if none were set.

public HandlergetFocusChangeHandler()

Gets the Handler to be used for the focus change listener.

public intgetFocusGain()

Gets the type of audio focus request configured for this AudioFocusRequestCompat.

public OnAudioFocusChangeListenergetOnAudioFocusChangeListener()

Gets the focus change listener set for this AudioFocusRequestCompat.

public inthashCode()

public booleanwillPauseWhenDucked()

Gets whether the application that would use this AudioFocusRequestCompat would pause when it is requested to duck.

from java.lang.Objectclone, finalize, getClass, notify, notifyAll, toString, wait, wait, wait

Methods

public int getFocusGain()

Gets the type of audio focus request configured for this AudioFocusRequestCompat.

Returns:

one of AudioManagerCompat.AUDIOFOCUS_GAIN, AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT, AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK, and AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE.

public AudioAttributesCompat getAudioAttributesCompat()

Gets the AudioAttributesCompat set for this AudioFocusRequestCompat, or the default attributes if none were set.

Returns:

non-null AudioAttributesCompat.

public boolean willPauseWhenDucked()

Gets whether the application that would use this AudioFocusRequestCompat would pause when it is requested to duck. This value is only applicable on and later.

Returns:

the duck/pause behavior.

public OnAudioFocusChangeListener getOnAudioFocusChangeListener()

Gets the focus change listener set for this AudioFocusRequestCompat.

Returns:

The that was set.

public Handler getFocusChangeHandler()

Gets the Handler to be used for the focus change listener.

Returns:

the same Handler set in. AudioFocusRequestCompat.Builder.setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler).

public boolean equals(java.lang.Object o)

public int hashCode()

Source

/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.media;

import static java.lang.annotation.RetentionPolicy.SOURCE;

import android.media.AudioAttributes;
import android.media.AudioFocusRequest;
import android.media.AudioManager;
import android.media.AudioManager.OnAudioFocusChangeListener;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.DoNotInline;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.util.ObjectsCompat;

import java.lang.annotation.Retention;

/** Compatibility version of an {@link AudioFocusRequest}. */
public class AudioFocusRequestCompat {

    // default attributes for the request when not specified
    /* package */ static final AudioAttributesCompat FOCUS_DEFAULT_ATTR =
            new AudioAttributesCompat.Builder().setUsage(AudioAttributesCompat.USAGE_MEDIA).build();

    @Retention(SOURCE)
    @IntDef({
        AudioManagerCompat.AUDIOFOCUS_GAIN,
        AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT,
        AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
        AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE
    })
    private @interface FocusGainType {}

    private final int mFocusGain;
    private final OnAudioFocusChangeListener mOnAudioFocusChangeListener;
    private final Handler mFocusChangeHandler;
    private final AudioAttributesCompat mAudioAttributesCompat;
    private final boolean mPauseOnDuck;

    private final Object mFrameworkAudioFocusRequest;

    /* package */ AudioFocusRequestCompat(
            int focusGain,
            OnAudioFocusChangeListener onAudioFocusChangeListener,
            Handler focusChangeHandler,
            AudioAttributesCompat audioFocusRequestCompat,
            boolean pauseOnDuck) {
        mFocusGain = focusGain;
        mFocusChangeHandler = focusChangeHandler;
        mAudioAttributesCompat = audioFocusRequestCompat;
        mPauseOnDuck = pauseOnDuck;

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O
                && mFocusChangeHandler.getLooper() != Looper.getMainLooper()) {
            mOnAudioFocusChangeListener =
                    new OnAudioFocusChangeListenerHandlerCompat(
                            onAudioFocusChangeListener, focusChangeHandler);
        } else {
            mOnAudioFocusChangeListener = onAudioFocusChangeListener;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            mFrameworkAudioFocusRequest = Api26Impl.createInstance(mFocusGain, getAudioAttributes(),
                    mPauseOnDuck, mOnAudioFocusChangeListener, mFocusChangeHandler);
        } else {
            mFrameworkAudioFocusRequest = null;
        }
    }

    /**
     * Gets the type of audio focus request configured for this {@code AudioFocusRequestCompat}.
     *
     * @return one of {@link AudioManagerCompat#AUDIOFOCUS_GAIN}, {@link
     *     AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT}, {@link
     *     AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and {@link
     *     AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
     */
    public @FocusGainType int getFocusGain() {
        return mFocusGain;
    }

    /**
     * Gets the {@link AudioAttributesCompat} set for this {@code AudioFocusRequestCompat}, or the
     * default attributes if none were set.
     *
     * @return non-null {@link AudioAttributesCompat}.
     */
    @NonNull
    public AudioAttributesCompat getAudioAttributesCompat() {
        return mAudioAttributesCompat;
    }

    /**
     * Gets whether the application that would use this {@code AudioFocusRequestCompat} would pause
     * when it is requested to duck. This value is only applicable on {@link
     * android.os.Build.VERSION_CODES#O} and later.
     *
     * @return the duck/pause behavior.
     */
    public boolean willPauseWhenDucked() {
        return mPauseOnDuck;
    }

    /**
     * Gets the focus change listener set for this {@code AudioFocusRequestCompat}.
     *
     * @return The {@link AudioManager.OnAudioFocusChangeListener} that was set.
     */
    @NonNull
    public OnAudioFocusChangeListener getOnAudioFocusChangeListener() {
        return mOnAudioFocusChangeListener;
    }

    /**
     * Gets the {@link Handler} to be used for the focus change listener.
     *
     * @return the same {@code Handler} set in. {@link
     *     Builder#setOnAudioFocusChangeListener(OnAudioFocusChangeListener, Handler)}.
     */
    @NonNull
    public Handler getFocusChangeHandler() {
        return mFocusChangeHandler;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof AudioFocusRequestCompat)) return false;
        AudioFocusRequestCompat that = (AudioFocusRequestCompat) o;
        return mFocusGain == that.mFocusGain
                && mPauseOnDuck == that.mPauseOnDuck
                && ObjectsCompat.equals(
                        mOnAudioFocusChangeListener, that.mOnAudioFocusChangeListener)
                && ObjectsCompat.equals(mFocusChangeHandler, that.mFocusChangeHandler)
                && ObjectsCompat.equals(mAudioAttributesCompat, that.mAudioAttributesCompat);
    }

    @Override
    public int hashCode() {
        return ObjectsCompat.hash(
                mFocusGain,
                mOnAudioFocusChangeListener,
                mFocusChangeHandler,
                mAudioAttributesCompat,
                mPauseOnDuck);
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    /* package */ AudioAttributes getAudioAttributes() {
        return (mAudioAttributesCompat != null)
                ? (AudioAttributes) mAudioAttributesCompat.unwrap()
                : null;
    }

    @RequiresApi(Build.VERSION_CODES.O)
    /* package */ AudioFocusRequest getAudioFocusRequest() {
        return (AudioFocusRequest) mFrameworkAudioFocusRequest;
    }

    /**
     * Builder class for {@link AudioFocusRequestCompat} objects.
     *
     * <p>See {@link AudioFocusRequestCompat} for an example of building an instance with this
     * builder. <br>
     * The default values for the instance to be built are:
     *
     * <table>
     * <tr><td>focus listener and handler</td><td>none</td></tr>
     * <tr><td>{@link AudioAttributesCompat}</td><td>attributes with usage set to
     * {@link AudioAttributesCompat#USAGE_MEDIA}</td></tr>
     * <tr><td>pauses on duck</td><td>false</td></tr>
     * <tr><td>supports delayed focus grant</td><td>false</td></tr>
     * </table>
     *
     * <p>In contrast to a {@link AudioFocusRequest}, attempting to {@link #build()} an {@link
     * AudioFocusRequestCompat} without an {@link AudioManager.OnAudioFocusChangeListener} will
     * throw an {@link IllegalArgumentException}, because the listener is required for all API
     * levels up to API 26.
     */
    public static final class Builder {
        private int mFocusGain;
        private OnAudioFocusChangeListener mOnAudioFocusChangeListener;
        private Handler mFocusChangeHandler;
        private AudioAttributesCompat mAudioAttributesCompat = FOCUS_DEFAULT_ATTR;

        // Flags
        private boolean mPauseOnDuck;

        /**
         * Constructs a new {@code Builder}, and specifies how audio focus will be requested. Valid
         * values for focus requests are {@link AudioManagerCompat#AUDIOFOCUS_GAIN},
         * {@link AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT}, and {@link
         * AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK}, and {@link
         * AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE}.
         * {@link AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE} is converted to
         * {@link AudioManagerCompat#AUDIOFOCUS_GAIN_TRANSIENT} on API levels previous to API 19.
         *
         * <p>By default there is no focus change listener, delayed focus is not supported, ducking
         * is suitable for the application, and the <code>AudioAttributesCompat</code> have a usage
         * of {@link AudioAttributes#USAGE_MEDIA}.
         *
         * @param focusGain the type of audio focus gain that will be requested
         * @throws IllegalArgumentException thrown when an invalid focus gain type is used
         */
        public Builder(@FocusGainType int focusGain) {
            setFocusGain(focusGain);
        }

        /**
         * Constructs a new {@code Builder} with all the properties of the {@code
         * AudioFocusRequestCompat} passed as parameter. Use this method when you want a new request
         * to differ only by some properties.
         *
         * @param requestToCopy the non-null {@code AudioFocusRequestCompat} to duplicate.
         * @throws IllegalArgumentException thrown when a null {@code AudioFocusRequestCompat} is
         *     used.
         */
        public Builder(@NonNull AudioFocusRequestCompat requestToCopy) {
            if (requestToCopy == null) {
                throw new IllegalArgumentException(
                        "AudioFocusRequestCompat to copy must not be null");
            }
            mFocusGain = requestToCopy.getFocusGain();
            mOnAudioFocusChangeListener = requestToCopy.getOnAudioFocusChangeListener();
            mFocusChangeHandler = requestToCopy.getFocusChangeHandler();
            mAudioAttributesCompat = requestToCopy.getAudioAttributesCompat();
            mPauseOnDuck = requestToCopy.willPauseWhenDucked();
        }

        /**
         * Sets the type of focus gain that will be requested. Use this method to replace the focus
         * gain when building a request by modifying an existing {@code AudioFocusRequestCompat}
         * instance.
         *
         * @param focusGain the type of audio focus gain that will be requested.
         * @return this {@code Builder} instance
         * @throws IllegalArgumentException thrown when an invalid focus gain type is used
         */
        @NonNull
        public Builder setFocusGain(@FocusGainType int focusGain) {
            if (!isValidFocusGain(focusGain)) {
                throw new IllegalArgumentException("Illegal audio focus gain type " + focusGain);
            }

            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT
                    && focusGain == AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE) {
                focusGain = AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT;
            }
            mFocusGain = focusGain;
            return this;
        }

        /**
         * Sets the listener called when audio focus changes after being requested with {@link
         * AudioManagerCompat#requestAudioFocus(AudioManager, AudioFocusRequestCompat)}, and until
         * being abandoned with {@link AudioManagerCompat#abandonAudioFocusRequest(AudioManager,
         * AudioFocusRequestCompat)}. Note that only focus changes (gains and losses) affecting the
         * focus owner are reported, not gains and losses of other focus requesters in the system.
         * <br>
         * Notifications are delivered on the main thread.
         *
         * @param listener the listener receiving the focus change notifications.
         * @return this {@code Builder} instance.
         * @throws NullPointerException thrown when a null focus listener is used.
         */
        @NonNull
        public Builder setOnAudioFocusChangeListener(@NonNull OnAudioFocusChangeListener listener) {
            return setOnAudioFocusChangeListener(listener, new Handler(Looper.getMainLooper()));
        }

        /**
         * Sets the listener called when audio focus changes after being requested with {@link
         * AudioManagerCompat#requestAudioFocus(AudioManager, AudioFocusRequestCompat)}, and until
         * being abandoned with {@link AudioManagerCompat#abandonAudioFocusRequest(AudioManager,
         * AudioFocusRequestCompat)}. Note that only focus changes (gains and losses) affecting the
         * focus owner are reported, not gains and losses of other focus requesters in the system.
         *
         * @param listener the listener receiving the focus change notifications.
         * @param handler the {@link Handler} for the thread on which to execute the notifications.
         * @return this {@code Builder} instance.
         * @throws NullPointerException thrown when a null focus listener or handler is used.
         */
        @NonNull
        public Builder setOnAudioFocusChangeListener(
                @NonNull OnAudioFocusChangeListener listener, @NonNull Handler handler) {
            if (listener == null) {
                throw new IllegalArgumentException("OnAudioFocusChangeListener must not be null");
            }
            if (handler == null) {
                throw new IllegalArgumentException("Handler must not be null");
            }

            mOnAudioFocusChangeListener = listener;
            mFocusChangeHandler = handler;
            return this;
        }

        /**
         * Sets the {@link AudioAttributesCompat} to be associated with the focus request, and which
         * describe the use case for which focus is requested. As the focus requests typically
         * precede audio playback, this information is used on certain platforms to declare the
         * subsequent playback use case. It is therefore good practice to use in this method the
         * same {@code AudioAttributesCompat} as used for playback, see for example {@link
         * MediaPlayer#setAudioAttributes(AudioAttributes)} in {@code MediaPlayer} or {@link
         * android.media.AudioTrack.Builder#setAudioAttributes(AudioAttributes)} in
         * {@code AudioTrack}.
         *
         * @param attributes the {@link AudioAttributesCompat} for the focus request.
         * @return this {@code Builder} instance.
         * @throws NullPointerException thrown when using null for the attributes.
         */
        @NonNull
        public Builder setAudioAttributes(@NonNull AudioAttributesCompat attributes) {
            if (attributes == null) {
                throw new NullPointerException("Illegal null AudioAttributes");
            }
            mAudioAttributesCompat = attributes;
            return this;
        }

        /**
         * Declare the intended behavior of the application with regards to audio ducking. See more
         * details in the {@link AudioFocusRequest} class documentation. Setting pauseOnDuck to true
         * will only have an effect on {@link android.os.Build.VERSION_CODES#O} and later.
         *
         * @param pauseOnDuck use {@code true} if the application intends to pause audio playback
         *     when losing focus with {@link AudioManager#AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK}.
         * @return this {@code Builder} instance.
         */
        @NonNull
        public Builder setWillPauseWhenDucked(boolean pauseOnDuck) {
            mPauseOnDuck = pauseOnDuck;
            return this;
        }

        /**
         * Builds a new {@code AudioFocusRequestCompat} instance combining all the information
         * gathered by this {@code Builder}'s configuration methods.
         *
         * @return the {@code AudioFocusRequestCompat} instance qualified by all the properties set
         *     on this {@code Builder}.
         * @throws IllegalStateException thrown when attempting to build a focus request without a
         *     focus change listener set.
         */
        public AudioFocusRequestCompat build() {
            if (mOnAudioFocusChangeListener == null) {
                throw new IllegalStateException(
                        "Can't build an AudioFocusRequestCompat instance without a listener");
            }

            return new AudioFocusRequestCompat(
                    mFocusGain,
                    mOnAudioFocusChangeListener,
                    mFocusChangeHandler,
                    mAudioAttributesCompat,
                    mPauseOnDuck);
        }

        /**
         * Checks whether a focus gain constant is a valid value for an audio focus request.
         *
         * @param focusGain value to check
         * @return true if focusGain is a valid value for an audio focus request.
         */
        private static boolean isValidFocusGain(@FocusGainType int focusGain) {
            switch (focusGain) {
                case AudioManagerCompat.AUDIOFOCUS_GAIN:
                case AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT:
                case AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK:
                case AudioManagerCompat.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE:
                    return true;
                default:
                    return false;
            }
        }
    }

    /**
     * Class to allow {@link OnAudioFocusChangeListener#onAudioFocusChange(int)} calls on a specific
     * thread prior to {@link Build.VERSION_CODES#O}.
     */
    private static class OnAudioFocusChangeListenerHandlerCompat
            implements Handler.Callback, OnAudioFocusChangeListener {

        private static final int FOCUS_CHANGE = 0x002a74b2;

        private final Handler mHandler;
        private final OnAudioFocusChangeListener mListener;

        /* package */ OnAudioFocusChangeListenerHandlerCompat(
                @NonNull OnAudioFocusChangeListener listener, @NonNull Handler handler) {

            mListener = listener;
            mHandler = new Handler(handler.getLooper(), this);
        }

        @Override
        public void onAudioFocusChange(final int focusChange) {
            mHandler.sendMessage(Message.obtain(mHandler, FOCUS_CHANGE, focusChange, 0));
        }

        @Override
        public boolean handleMessage(Message message) {
            if (message.what == FOCUS_CHANGE) {
                mListener.onAudioFocusChange(message.arg1);
                return true;
            }
            return false;
        }
    }

    @RequiresApi(26)
    private static class Api26Impl {
        private Api26Impl() {}

        @DoNotInline
        static AudioFocusRequest createInstance(
                int focusGain,
                AudioAttributes audioAttributes,
                boolean pauseOnDuck,
                OnAudioFocusChangeListener onAudioFocusChangeListener,
                Handler focusChangeHandler) {
            return new AudioFocusRequest.Builder(focusGain)
                    .setAudioAttributes(audioAttributes)
                    .setWillPauseWhenDucked(pauseOnDuck)
                    .setOnAudioFocusChangeListener(onAudioFocusChangeListener, focusChangeHandler)
                    .build();
        }
    }
}