Question

private static int changedFocus;
private static boolean focusGranted;
private static AudioManager audioManager;

public static int getChangedFocus() {
    return changedFocus;
}

public static boolean isFocusGranted() {
    return focusGranted;
}

public static void requestFocus(final Context context) {
    if (audioManager == null) {
        audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
    }
    switch (audioManager.requestAudioFocus(OnFocusChangeListener.getInstance(),
            AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN)) {
        case AudioManager.AUDIOFOCUS_REQUEST_GRANTED:
            focusGranted = true;
            break;

        case AudioManager.AUDIOFOCUS_REQUEST_FAILED:
            focusGranted = false;
            break;
    }
}

private static final class OnFocusChangeListener implements AudioManager.OnAudioFocusChangeListener {

    private static OnFocusChangeListener instance;

    protected static OnFocusChangeListener getInstance() {
        if (instance == null) {
            instance = new OnFocusChangeListener();
        }
        return instance;
    }

    @Override
    public void onAudioFocusChange(final int focusChange) {
        changedFocus = focusChange;
        System.out.println("on focus change: " + focusChange);
        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                GlobalMusicPlayer.onFocusGained();
                break;

            case AudioManager.AUDIOFOCUS_LOSS:
                GlobalMusicPlayer.onFocusLoss();
                break;

            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                GlobalMusicPlayer.onFocusLossTransient();
                break;

            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                GlobalMusicPlayer.onFocusLossTransientCanDuck();
                break;
        }
    }
}

I call requestFocus(context) and get AudioManager.AUDIOFOCUS_REQUEST_GRANTED as a return value.

After that, onAudioFocusChange never called and thus changedFocus is always 0.

isFocusGranted() // true
getChangedFocus() // 0

Devices: Nexus 10, Motorola Xoom.

Was it helpful?

Solution

case AudioManager.AUDIOFOCUS_GAIN in onAudioFocusChange() is more of an AudioFocus re-gain. It only gets triggered after the lost event.

case AudioManager.AUDIOFOCUS_REQUEST_GRANTED is where you should add another GlobalMusicPlayer.onFocusGained().

OTHER TIPS

Actually I can't see what can be wrong with your code so I have created small test activity.

To test audio focus listener you have to start this activity, minimize it using "Home" button and then start some music player (tested with stock one on emulator) – you should be able to see 'Focus LOST' toast as soon as music starts playing. When you stop the music – you should see 'Focus GAINED' message.

Also, here is a good article about handling audio focus (just leaving it here for future reference)

import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.widget.Toast;

public class MainActivity extends Activity {

private static final String TAG = MainActivity.class.getSimpleName();

private AudioManager mAudioManager;
private AudioFocusChangeListenerImpl mAudioFocusChangeListener;
private boolean mFocusGranted, mFocusChanged;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

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

    mAudioFocusChangeListener = new AudioFocusChangeListenerImpl();
    int result = mAudioManager.requestAudioFocus(mAudioFocusChangeListener,
            AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);

    switch (result) {
        case AudioManager.AUDIOFOCUS_REQUEST_GRANTED:
            mFocusGranted = true;
            break;
        case AudioManager.AUDIOFOCUS_REQUEST_FAILED:
            mFocusGranted = false;
            break;
    }

    String message = "Focus request " + (mFocusGranted ? "granted" : "failed");
    Toast.makeText(this, message, Toast.LENGTH_LONG).show();
    Log.i(TAG, message);
}

@Override
protected void onDestroy() {
    super.onDestroy();

    mAudioManager.abandonAudioFocus(mAudioFocusChangeListener);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

private class AudioFocusChangeListenerImpl implements AudioManager.OnAudioFocusChangeListener {

    @Override
    public void onAudioFocusChange(int focusChange) {
         mFocusChanged = true;
        Log.i(TAG, "Focus changed");

        switch (focusChange) {
            case AudioManager.AUDIOFOCUS_GAIN:
                Log.i(TAG, "AUDIOFOCUS_GAIN");
                Toast.makeText(MainActivity.this, "Focus GAINED", Toast.LENGTH_LONG).show();
                break;
            case AudioManager.AUDIOFOCUS_LOSS:
                Log.i(TAG, "AUDIOFOCUS_LOSS");
                Toast.makeText(MainActivity.this, "Focus LOST", Toast.LENGTH_LONG).show();
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                Log.i(TAG, "AUDIOFOCUS_LOSS_TRANSIENT");
                Toast.makeText(MainActivity.this, "Focus LOST TRANSIENT", Toast.LENGTH_LONG).show();
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                Log.i(TAG, "AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
                Toast.makeText(MainActivity.this, "Focus LOST TRANSIENT CAN DUCK", Toast.LENGTH_LONG).show();
                break;
        }
    }
}
}

I found that this behavior is not implemented on some devices. My first HTC phone respect the listener API, but my Asus one doesn't. I don't know why Google let this kind of fragmentation exist.

You can see on someone complained on https://groups.google.com/forum/#!topic/android-developers/qWFHOOkgWT8

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top