Home » Android » How do I determine when Google maps is Speaking in Android

How do I determine when Google maps is Speaking in Android

Posted by: admin June 15, 2020 Leave a comment

Questions:

I’m trying to modify my application to pause audio playback when Google maps is announcing a turn by turn direction.

I’ve added the following code (shown below) to my application. The audio focus listener is called when applications like Pandora Radio or Spotify request audio focus in order to play music but it’s not called when Google maps announces a turn by turn direction. Is there another intent I should be listening for in order to detect this behavior?

 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    audioManager.requestAudioFocus(new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
            .setAudioAttributes(
                    new AudioAttributes.Builder()
                            .setUsage(AudioAttributes.USAGE_MEDIA)
                            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                            .build()
            )
            .setAcceptsDelayedFocusGain(true)
            .setOnAudioFocusChangeListener(new AudioManager.OnAudioFocusChangeListener() {
                @Override
                public void onAudioFocusChange(int focusChange) {
                    // This is called by Pandora Radio and Spotify
                    Log.d("Focus change:", " Event is: " + focusChange);
                }
            }).build());
How to&Answers:

You will need AudioManager‘s AudioPlaybackCallback updates.

This only works on Android O and above.

To do this you have to access the audio manager –

 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);

And then add the listener like this –

Handler handler = new Handler();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    audioManager.registerAudioPlaybackCallback(new AudioManager.AudioPlaybackCallback() {
        @Override
        public void onPlaybackConfigChanged(List<AudioPlaybackConfiguration> configs) {
             super.onPlaybackConfigChanged(configs);
            // This will be called when navigation audio state on google maps changes
            Log.d("audio active", String.valueOf(audioManager.isMusicActive()));
        }
    }, handler);
}

The List<AudioPlaybackConfiguration> configs returned in the callback has a AudioAttribute object which contains a string describing the audio playing. For Google maps navigation the String constant value is USAGE_ASSISTANCE_NAVIGATION_GUIDANCE which you can compare to be sure that it is Google Maps announcing the navigation direction.

Programatically you can get it like this

// Loop through the configs to see the media's usage data
configs.get(0).getAudioAttributes().getUsage();

Answer:

@Override
    public void onAudioFocusChange(int focusChange) {
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                if (mPlayOnAudioFocus && !isPlaying()) {
                    play();
                } else if (isPlaying()) {
                    setVolume(MEDIA_VOLUME_DEFAULT);
                }
                mPlayOnAudioFocus = false;
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                setVolume(MEDIA_VOLUME_DUCK);
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                if (isPlaying()) {
                    mPlayOnAudioFocus = true;
                    pause();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS:
                mAudioManager.abandonAudioFocus(this);
                mPlayOnAudioFocus = false;
                stop();
                break;
        }
    }
}

The following code snippet contains an implementation of this interface for an app that plays audio. And it handles ducking for transient audio focus loss. It also handles audio focus change due to the user pausing playback, vs another app (like the Google Assistant) causing transient audio focus loss

does your app temporarily need audio focus (with the option to duck), since it needs to play an audio notification, or a turn by turn spoken direction, or it needs to record audio from the user for a short period of time? This is

AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK.

Ducking vs pausing on transient audio focus loss
You can choose to pause playback or temporarily reduce the volume of your audio playback in the OnAudioFocusChangeListener, depending on what UX your app needs to deliver. Android O supports auto ducking, where the system will reduce the volume of your app automatically without you having to write any extra code. In your OnAudioFocusChangeListener, just ignore the AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK event.

In Android N and earlier, you have to implement ducking yourself (as shown in the code snippet above).

for Detail visit :https://medium.com/androiddevelopers/audio-focus-3-cdc09da9c122

AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
added in API level 8
public static final int AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
Used to indicate a temporary request of audio focus, anticipated to last a short amount of time, and where it is acceptable for other audio applications to keep playing after having lowered their output level (also referred to as “ducking”). Examples of temporary changes are the playback of driving directions where playback of music in the background is acceptable.

Answer:

You should use “AudioManager.AUDIOFOCUS_GAIN_TRANSIENT”, according to the documentation:

AUDIOFOCUS_GAIN_TRANSIENT

Used to indicate a temporary gain or request of audio focus, anticipated to last a short amount of time. Examples of temporary changes are the playback of driving directions, or an event notification.