Audio Focus nelle App Android

Di - 12 September 2013 - in
Android Audio Focus

Sui nostri device abbiamo diverse applicazioni che possono riprodurre audio. Molti di noi hanno installato Google PlayMusic, qualche player per musica offline, magari TED per ascoltarci dei grandissimi talk durante il nostro viaggio casa-ufficio; e, potenzialmente, potrebbero eseguire audio tutte contemporaneamente… non capiremmo niente. Per evitare questo problema, le applicazioni possono richiedere ad Android di ottenere l’accesso esclusivo all’audio del device. Tengo a precisare che le applicazioni possono e dovrebbero richiedere l’audio focus, ma ad esempio l’applicazione di TED non lo richiede, quindi se sto ascoltando una canzone e faccio partire un talk di TED… disastro.

Livelli di Focus Audio

Richiedere l’audio focus non necessariamente ferma la riproduzione audio di un’altra applicazione, in base al tipo di audio che vogliamo riprodurre (Stream Type) e per quanto tempo vogliamo mantenere il focus con la nostra app (Gain Type).

Tipi di Gain/Loss e loro utilizzo

Durante la richiesta di audio focus, abbiamo la possibilità di richiedere l’audio focus per un determinato lasso di tempo/utilizzo e inviare alle applicazioni che hanno precedentemente il focus (nell’esempio precedente Google Play Music) l’informazione che hanno perso il focus e quale tipo di focus è stato richiesto da un’altra applicazione.

AUDIOFOCUS_GAIN richiede il focus a tempo indeterminato, ad esempio quando eseguiamo un MP3 dovremo richiedere questo tipo di focus per poter riprodurre audio richiedendo alle altre applicazioni di interrompere la loro riproduzione.

AUDIOFOCUS_GAIN_TRANSIENT è consigliato per riproduzioni audio fino a 45 secondi (Es. leggiamo un SMS), le altre applicazioni con audio focus sapranno che non é strettamente necessario che fermino la riproduzione, potrebbero semplicemente ridurre il loro volume di riproduzione al 20% e attendere che la nostra applicazione rilasci il focus prima di riportare il volume al 100% ( o mettere in pausa e far ripartire la riproduzione).

AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK si richiede che non sia utilizzato per piú di 15 secondi, ad esempio se un’applicazione di tracciamento GPS della corsa deve comunicarci quanti chilometri abbiamo percorso, in questo caso l’applicazione che riproduce musica in background potrebbe ignorare la nostra richiesta di focus audio o ridurre al 90% il volume di riproduzione.

Considerando i comportamenti che dovrebbero rispettare le altre applicazioni quando la nostra richiede l’audio focus, é bene non essere scellerati e richiedere il focus audio all’apertura dell’applicazione; immaginate di star sentendo della musica e decidere di controllare se ci sono dei video interessanti di YouTube. La musica deve continuare fino a che non decidiamo di far partire un filmato, non durante la consultazione del nostro stream delle sottoscrizioni.

Tipi di Stream Audio

Specificando quale tipo di audio vogliamo riprodurre, il sistema operativo si occuperà di scegliere attraverso quale canale audio effettuare la riproduzione del nostro stream.

Ad esempio se abbiamo le cuffie collegate ma richiediamo STREAM_ALARM l’audio verrà riprodotto dallo speaker del telefono; allo stesso modo, se dobbiamo riprodurre delle notifiche e il telefono è in vibrazione, queste non verranno riprodotte né dallo speaker, né in cuffia.

Chiediamo il Focus

Vediamo un’esempio

AudioManager am = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);

int result = am.requestAudioFocus(mOnAudioFocusChangeListener,
    // Hint: the music stream.
    AudioManager.STREAM_MUSIC,
    // Request permanent focus.
    AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
    mState.audioFocusGranted = true;
} else if (result == AudioManager.AUDIOFOCUS_REQUEST_FAILED) {
    mState.audioFocusGranted = false;
}

Nella prima riga otteniamo l’oggetto AudioManager di sistema che useremo subito per richiedere il focus completo e riprodurre “musica”, specificando anche una funzione di per gestire i successivi cambiamenti di focus che potrebbero essere generati da altre applicazioni; il costrutto if serve per mantenere l’informazione se l’applicazione ha ottenuto il focus audio o meno.

É importante definire un listener per l’evento di AudioFocusChange in modo che la nostra applicazione risponda in maniera corretta alle richieste di focus che possono avvenire da parte di altre applicazioni; di seguito un’esempio:

mOnAudioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
    @Override
    public void onAudioFocusChange(int focusChange) {
        switch (focusChange) {
        case AudioManager.AUDIOFOCUS_GAIN:
            mState.audioFocusGranted = true;
            if(mState.released) {
                initializeMediaPlayer();
            }
            switch(mState.lastKnownAudioFocusState) {
            case UNKNOWN:
                if(mState.state == PlayState.PLAY && !mPlayer.isPlaying()) {
                    mPlayer.start();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
                if(mState.wasPlayingWhenTransientLoss) {
                    mPlayer.start();
                }
                break;
            case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
                restoreVolume();
                break;
            }
            break;
        case AudioManager.AUDIOFOCUS_LOSS:
            mState.userInitiatedState = false;
            mState.audioFocusGranted = false;
            teardown();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
            mState.userInitiatedState = false;
            mState.audioFocusGranted = false;
            mState.wasPlayingWhenTransientLoss = mPlayer.isPlaying();
            mPlayer.pause();
            break;
        case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
            mState.userInitiatedState = false;
            mState.audioFocusGranted = false;
            lowerVolume();
            break;
        }
    mState.lastKnownAudioFocusState = focusChange;
    }
};

Molto brevemente, il codice riportato qui sopra si occupa, decide come comportarsi con l’audio che stiamo riproducendo quando altre applicazioni richiedono il focus audio.

Per chi reputasse poco importante gestire correttamente il comportamento in caso di perdita del focus audio, ricordo che anche le notifiche e l’applicazione di telefonia di Android sono applicazioni come le altre e comunicano la richiesta di focus utilizzando l’audio manager.

Via | Android Developer Blog

Leave a Reply

Articolo scritto da

Techy, sviluppatore .Net per professione, sviluppatore Android per passione. All Around Android Lover e Google Enthusiast

Contatta l'autore

Previous post:

Next post: