Una buena experiencia de usuario es imprescindible.
Las aplicaciones multimedia tienen que ofrecer a los usuarios poder controlar el volumen de su aplicación utilizando el hardware o el software de control del volumen del dispositivo, auriculares bluetooth, o los auriculares.
De la misma manera, tiene que ser posible parar, pausar, saltar... Los medios que se están reproduciendo.
Android mantiene un flujo (mediaplayer) de audio para cada medio, notificación, llamada... que hay en el dispositivo. Se puede controlar el volumen de cada uno por separado.
La mayoría de estos flujos responden a STREAM_MUSIC, otros corresponderían como flujos del sistema, como la alarma.
Por defecto, poner las teclas del dispositivo cambia el volumen del flujo activo. Si el dispositivo no esta reproduciendo nada cambia el volumen de la llamada.
Mediante setVolumeControlStream() se puede cambiar el volumen del audio que se esta reproduciendo.
setVolumeControlStream(AudioManager.STREAM_MUSIC);
Hace que al pulsar las teclas de volumen funcionen como se espere.
Para esto, necesitaremos los permisos:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Disponemos de la posibilidad de que responda a las teclas de pausa, reproducción... para que sea nuestra app la que lo controle, necesitará el broadcast, dentro del manifest, sería el broadcast que escuchamos. Normalmente lo lanza el sistema, nosotros normalmente usamos RemoteControlReceiver.
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
<receiver android:name=".RemoteControlReceiver">
<intent-filter>
<action android:name="android.intent.action.MEDIA_BUTTON" />
</intent-filter>
</receiver>
tendremos la clase broadcastReceiver que es y le hacemos hacer la acción.
y el receptor extrae la tecla que se tiene que pulsar de la siguiente manera:
y el receptor extrae la tecla que se tiene que pulsar de la siguiente manera:
public class Receptor extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if (
Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())){
@Override
public void onReceive(Context context, Intent intent) {
if (
Intent.ACTION_MEDIA_BUTTON.equals(intent.getAction())){
KeyEvent event =(KeyEvent)intent.getParcelableExtra(Intent.EXTRA_KEY_EVENT);
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()){
// tecla pulsada
}
}
}
}
if (KeyEvent.KEYCODE_MEDIA_PLAY == event.getKeyCode()){
// tecla pulsada
}
}
}
}
Android utiliza el foco de audio para moderar cuando diversas apps están reproduciendo medios. Antes que una app inicie la reproducción tiene que pedir y recibir el foco. Con requestAudioFocus() podremos pedir el foco y devolverá AUDIOFOCUS_REQUEST_GRANTED si lo ha conseguido.
Hace falta especificar que flujo se esta utilizando y si será puntual o permanente la petición, por ejemplo un aviso o reproducción de música.
AudioManager am = mContext.getSystemService(Context.AUDIO_SERVICE);
...
// petición del foco para reproducir música
int result = am.requestAudioFocus(afChangeListener,
// utiliza un flujo de música
AudioManager.STREAM_MUSIC,
// petición permanente
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
// comienza la reproducción.
}
...
// petición del foco para reproducir música
int result = am.requestAudioFocus(afChangeListener,
// utiliza un flujo de música
AudioManager.STREAM_MUSIC,
// petición permanente
AudioManager.AUDIOFOCUS_GAIN);
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
// comienza la reproducción.
}
Cada vez que cambia el foco, cambia el changelistener y le podemos decir lo que tiene que hacer.
Cada vez que la aplicación que roba el foco se dispara:
AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK
este va a buscar si hay alguna cosa programada.
Una vez finaliza la reproducción hace falta liberar el foco de audio con abandonAudioFocus().am.abandonAudioFocus(afChangeListener);
Esta la posibilidad de que el volumen quede bajo hasta que se vuelva a poner el foco en la app inicial, por ejemplo un navegador de rutas para un vehículo, esto se hace con:
int result = am.requestAudioFocus(afChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK);
También podemos gestionar cuando un foco cambia de app:
// gestión cuando se pierde el foco, el cual depende de la manera como se pierde.
OnAudioFocusChangeListener afChangeListener = new OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT
// Pausa
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Sigue reproduciendo.
} else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) {
am.unregisterMediaButtonEventReceiver(RemoteControlReceiver);
am.abandonAudioFocus(afChangeListener);
// Para.
}
}
};
Reducir el volumen (ducking) nos permite puntualmente reducir el volumen cuando una app tiene el foco de audio sin parar la reproducción.
OnAudioFocusChangeListener afChangeListener = new
OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
if (focusChange == AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) {
// Baja el volumen
} else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) {
// Sube el volumen
}
}
};
Los usuarios pueden disponer de altavoces, auriculares, etc, y hace falta saber como conectar y gestionar cada uno de estos dispositivos.
Para saber que dispositivos se están utilizando, utilizaremos la clase AudioManager.
if (isBluetoothA2dpOn()) {//ajustamos para Bluetooth.
} else if (isSpeakerphoneOn()) {
// ajustamos para altavoz
} else if (isWiredHeadsetOn()) {
// ajustamos para auriculares
} else {
// no hay ninguna salida para escuchar el audio.
}
En el caso de cambiar alguno de estos dispositivos podemos tener problemas con el volumen. Dispondremos de una señal que se envía a las aplicaciones ACTION_AUDIO_BECOMING_NOISY para controlar estos casos.
private class Receptor extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(AudioManager.ACTION_AUDIO_BECOMING_NOISY.equals(intent.getAction())){
// Hacemos una pausa
}
}
}
private IntentFilter intentFilter = new
IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY);
private void startPlayback() {
registerReceiver(myNoisyAudioStreamReceiver(), intentFilter);
}
private void stopPlayback() {
unregisterReceiver(myNoisyAudioStreamReceiver);
}
1. Desarrolla una aplicación para Android que reproduzca una pista de música almacenada en los recursos del dispositivo. La aplicación debe disponer de botones para parar, pausar e iniciar la pista de música. Debe mostrar el tiempo de reproducción.
Solución.Proyecto en Android Studio.
2. A partir del ejercicio anterior, crea un servicio en primer plano que realice la reproducción de música mostrando con una notificación de información al usuario en la barra de estado.
Solución.
3. Crea una aplicación móvil para Android que permita acceder a los contenidos de música de tu dispositivo, los muestre en una lista, y en seleccionar una pista la reproduzca. Crea una animación de un botón que al pulsarlo desaparezca.
Solución.
Apuntes.
Cap comentari :
Publica un comentari a l'entrada