Cambio de volumen Listener: ¿Es preferible registerMediaButtonEventReceiver a onKeyDown?

En busca de un "más completo y compatible (es decir, todas las versiones de Android …)" manera de escuchar los cambios de volumen, he encontrado dos diferentes enfoques para manejar esto:

  1. RegisterMediaButtonEventReceiver
  2. OnKeyDown + SettingsContentObserver

¿Qué método es preferible?

¿Y por qué?

UPDATE 1: Gracias al comentario de abajo, descubrí que onKeyDown () realmente se hace cargo de la clave de volumen, que puede no ser una solución completa, ya que uno de los puestos mencionados que el volumen podría cambiarse a través de interfaces distintas de los botones de hardware Mencionar que Google parece estar quitando gradualmente esas capacidades de "toma de posesión").

OTOH, android.media.VOLUME_CHANGED_ACTION es un hack y ni siquiera está documentado . Lo que probablemente significa que dejará de funcionar en Android 5 o menos …

UPDATE 2: registerMediaButtonEventReceiver no funciona en absoluto! (Para los botones de hardware de volumen que es, lo intenté).

¿Ideas adicionales?

Sería genial tener en futuras APIs BroadcastReceiver para flujos de volumen, pero hoy quizás la mejor solución es registrar un ContentObserver para la configuración (que incluye VOLUME_NOTIFICATION):

 mSettingsContentObserver = new SettingsContentObserver( new Handler() ); this.getApplicationContext().getContentResolver().registerContentObserver( android.provider.Settings.System.CONTENT_URI, true, mSettingsContentObserver ); 

Vea esta respuesta para más información: https://stackoverflow.com/a/7017516/117382

Edit: Corregido con código de trabajo. Tal vez esta solución sea mejor: https://stackoverflow.com/a/17398781/117382

Para poder escuchar todos los flujos de volumen la mejor manera para mí es usar ContentObserver. Aquí está mi código:

 public class AudioVolumeObserver { public interface OnAudioStreamVolumeChangedListener { void onAudioStreamVolumeChanged(ArrayList<Integer> audioStreamType); } public interface OnAudioModeVolumeChangedListener { void onAudioModeVolumeChanged(int volumeMode); } private static class AudioVolumeContentObserver extends ContentObserver { private final AudioManager mAudioManager; private final OnAudioStreamVolumeChangedListener mVolumeStreamListener; private final OnAudioModeVolumeChangedListener mVolumeModeListener; private int[] currentVolumeStreams = new int[6]; private int[] lastVolumeStreams = new int[6]; private int currentVolumeMode; private int lastVolumeMode; ArrayList<Integer> changedVolumeStreams = new ArrayList<>(); public AudioVolumeContentObserver( @NonNull Handler handler, @NonNull AudioManager audioManager, @NonNull OnAudioModeVolumeChangedListener volumeModeListener, @NonNull OnAudioStreamVolumeChangedListener volumeStreamListener) { super(handler); mAudioManager = audioManager; mVolumeModeListener = volumeModeListener; mVolumeStreamListener = volumeStreamListener; lastVolumeMode = mAudioManager.getRingerMode(); lastVolumeStreams[0] = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); lastVolumeStreams[1] = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM); lastVolumeStreams[2] = mAudioManager.getStreamVolume(AudioManager.STREAM_RING); lastVolumeStreams[3] = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); lastVolumeStreams[4] = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM); lastVolumeStreams[5] = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION); } @Override public void onChange(boolean selfChange) { currentVolumeMode = mAudioManager.getRingerMode(); currentVolumeStreams[0] = mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL); currentVolumeStreams[1] = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM); currentVolumeStreams[2] = mAudioManager.getStreamVolume(AudioManager.STREAM_RING); currentVolumeStreams[3] = mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC); currentVolumeStreams[4] = mAudioManager.getStreamVolume(AudioManager.STREAM_ALARM); currentVolumeStreams[5] = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION); if (currentVolumeMode != lastVolumeMode){ lastVolumeMode = currentVolumeMode; mVolumeModeListener.onAudioModeVolumeChanged(currentVolumeMode); } changedVolumeStreams.clear(); for (int i=0; i<6; i++) if (currentVolumeStreams[i] != lastVolumeStreams[i]) { lastVolumeStreams[i] = currentVolumeStreams[i]; changedVolumeStreams.add(i); } if (!changedVolumeStreams.isEmpty()){ mVolumeStreamListener.onAudioStreamVolumeChanged(changedVolumeStreams); } } } private final Context mContext; private AudioVolumeContentObserver mAudioVolumeContentObserver; public AudioVolumeObserver( @NonNull Context context) { mContext = context; } public void start(@NonNull OnAudioModeVolumeChangedListener volumeModeListener, @NonNull OnAudioStreamVolumeChangedListener volumeStreamListener) { stop(); Handler handler = new Handler(); AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE); mAudioVolumeContentObserver = new AudioVolumeContentObserver(handler, audioManager, volumeModeListener, volumeStreamListener); mContext.getContentResolver() .registerContentObserver(android.provider.Settings.System.CONTENT_URI, true, mAudioVolumeContentObserver); } public void stop() { if (mAudioVolumeContentObserver == null) { return; } mContext.getContentResolver() .unregisterContentObserver(mAudioVolumeContentObserver); mAudioVolumeContentObserver = null; } } 
  • ¿Cómo detener / cancelar el administrador de alarmas en otra actividad?
  • BroadcastReceiver no funciona cuando la aplicación no se está ejecutando
  • ¿Debo usar android: process = ": remote" en mi receptor?
  • Cómo obtener el nombre del contacto al recibir SMS
  • Detectar el final de una llamada entrante atendida por el usuario en android? (No rechazado)
  • Programáticamente eliminar SMS no funciona
  • Ventana emergente sobre la pantalla de llamada entrante nativa de Android, como la aplicación de llamador verdadero para Android
  • Detectar qué tarjeta SIM ha recibido el mensaje
  • ¿Los BroadcastReceivers de Android comenzaron en un nuevo hilo?
  • BroadcastReceiver SMS_Received no funciona en nuevos dispositivos
  • Preferencias compartidas dentro de broadcastreceiver
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.