GOOGLE ADS

miércoles, 13 de abril de 2022

¿Existe una acción de difusión para los cambios de volumen?

Estoy programando un pequeño widget que debe actualizarse cada vez que el usuario cambia el volumen del timbre o la configuración de vibración.

La captura android.media.VIBRATE_SETTING_CHANGEDfunciona bien para la configuración de vibración, pero no he encontrado ninguna forma de recibir una notificación cuando cambia el volumen del timbre y, aunque podría intentar capturar cuando el usuario presiona las teclas físicas para subir/bajar el volumen, hay muchas otras opciones. para cambiar el volumen sin utilizar estas teclas.

¿Sabe si hay alguna acción de transmisión definida para esto o alguna forma de crear una o resolver el problema sin ella?


Solución del problema

Basado en el código de Nathan, adi y swooby, creé un ejemplo de trabajo completo con algunas mejoras menores.

Mirando a la AudioFragmentclase, podemos ver lo fácil que es escuchar los cambios de volumen con nuestra costumbre ContentObserver.

public class AudioFragment extends Fragment implements OnAudioVolumeChangedListener {
private AudioVolumeObserver mAudioVolumeObserver;
@Override
public void onResume() {
super.onResume();
// initialize audio observer
if (mAudioVolumeObserver == null) {
mAudioVolumeObserver = new AudioVolumeObserver(getActivity());
}
/*
* register audio observer to identify the volume changes
* of audio streams for music playback.
*
* It is also possible to listen for changes in other audio stream types:
* STREAM_RING: phone ring, STREAM_ALARM: alarms, STREAM_SYSTEM: system sounds, etc.
*/
mAudioVolumeObserver.register(AudioManager.STREAM_MUSIC, this);
}
@Override
public void onPause() {
super.onPause();
// release audio observer
if (mAudioVolumeObserver!= null) {
mAudioVolumeObserver.unregister();
}
}
@Override
public void onAudioVolumeChanged(int currentVolume, int maxVolume) {
Log.d("Audio", "Volume: " + currentVolume + "/" + maxVolume);
Log.d("Audio", "Volume: " + (int) ((float) currentVolume / maxVolume) * 100 + "%");
}
}

public class AudioVolumeContentObserver extends ContentObserver {
private final OnAudioVolumeChangedListener mListener;
private final AudioManager mAudioManager;
private final int mAudioStreamType;
private int mLastVolume;
public AudioVolumeContentObserver(
@NonNull Handler handler,
@NonNull AudioManager audioManager,
int audioStreamType,
@NonNull OnAudioVolumeChangedListener listener) {
super(handler);
mAudioManager = audioManager;
mAudioStreamType = audioStreamType;
mListener = listener;
mLastVolume = audioManager.getStreamVolume(mAudioStreamType);
}
/**
* Depending on the handler this method may be executed on the UI thread
*/
@Override
public void onChange(boolean selfChange, Uri uri) {
if (mAudioManager!= null && mListener!= null) {
int maxVolume = mAudioManager.getStreamMaxVolume(mAudioStreamType);
int currentVolume = mAudioManager.getStreamVolume(mAudioStreamType);
if (currentVolume!= mLastVolume) {
mLastVolume = currentVolume;
mListener.onAudioVolumeChanged(currentVolume, maxVolume);
}
}
}
@Override
public boolean deliverSelfNotifications() {
return super.deliverSelfNotifications();
}
}

public class AudioVolumeObserver {
private final Context mContext;
private final AudioManager mAudioManager;
private AudioVolumeContentObserver mAudioVolumeContentObserver;
public AudioVolumeObserver(@NonNull Context context) {
mContext = context;
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
}
public void register(int audioStreamType,
@NonNull OnAudioVolumeChangedListener listener) {
Handler handler = new Handler();
// with this handler AudioVolumeContentObserver#onChange()
// will be executed in the main thread
// To execute in another thread you can use a Looper
// +info: https://stackoverflow.com/a/35261443/904907
mAudioVolumeContentObserver = new AudioVolumeContentObserver(
handler,
mAudioManager,
audioStreamType,
listener);
mContext.getContentResolver().registerContentObserver(
android.provider.Settings.System.CONTENT_URI,
true,
mAudioVolumeContentObserver);
}
public void unregister() {
if (mAudioVolumeContentObserver!= null) {
mContext.getContentResolver().unregisterContentObserver(mAudioVolumeContentObserver);
mAudioVolumeContentObserver = null;
}
}
}

public interface OnAudioVolumeChangedListener {
void onAudioVolumeChanged(int currentVolume, int maxVolume);
}

¡Espero que todavía sea útil para alguien!:)

No hay comentarios:

Publicar un comentario

Regla de Firestore para acceder a la generación de subcolección Permisos faltantes o insuficientes

Tengo problemas con las reglas de Firestore para permitir el acceso a algunos recursos en una subcolección. Tengo algunos requests document...