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:
- RegisterMediaButtonEventReceiver
- OnKeyDown + SettingsContentObserver
¿Qué método es preferible?
- Anular la pantalla de llamada saliente predeterminada
- No se puede instanciar el receptor en BroadcastReceiver SMS
- AlarmManager dentro de BroadcastReceiver cuando BOOT_COMPLETED
- Cómo interceptar la intención de ACTION_MEDIA_MOUNTED en Android?
- GCM push notificaciones en android 3.1: deshabilitar receptor de difusión
¿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?
- ¿Cómo iniciar la actividad de intentservice?
- Restricción de Android Broadcast Receiver de una aplicación específica
- Android BroadcastReceiver android.intent.action.BATTERY_CHANGED
- Android captura nueva llamada saliente
- actualizar mi aplicación
- Android OrderedBroadcast No funciona en la versión de lanzamiento
- Android External App Install (en la tarjeta SD), vuelva a cargar las alarmas del alarmmanager al re-montar a través del receptor
- Difusión en contacto agregar / cambiar?
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; } }
- Crear, almacenar e inflar diseño personalizado en tiempo de ejecución
- Instalar crashlytics sin tela?