Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Escuchar los botones de volumen en el servicio de fondo?

Sé cómo escuchar los botones de volumen en una actividad. Pero, ¿puedo hacer eso en un servicio de fondo? Si es así, ¿cómo hacer eso?

  • Escuchar los botones de volumen en el servicio de fondo?
  • 7 Solutions collect form web for “Escuchar los botones de volumen en el servicio de fondo?”

    A juzgar por la pareja de otras preguntas sobre este tema, no.

    Otra pregunta 1 , Otra pregunta 2

    Los servicios simplemente no reciben devoluciones de llamada de KeyEvent.

    Siento mucho decirle, pero ES POSIBLE. Use el código a continuación (PARA LOS NUEVOS ANDROIDES, ESP. MARSHMALLOW, VER FONDO DE LA RESPUESTA):

    public class SettingsContentObserver extends ContentObserver { int previousVolume; Context context; public SettingsContentObserver(Context c, Handler handler) { super(handler); context=c; AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); previousVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC); } @Override public boolean deliverSelfNotifications() { return super.deliverSelfNotifications(); } @Override public void onChange(boolean selfChange) { super.onChange(selfChange); AudioManager audio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); int currentVolume = audio.getStreamVolume(AudioManager.STREAM_MUSIC); int delta=previousVolume-currentVolume; if(delta>0) { Logger.d("Ściszył!"); previousVolume=currentVolume; } else if(delta<0) { Logger.d("Zrobił głośniej!"); previousVolume=currentVolume; } } } 

    Luego en su servicio onCreate regístrelo con:

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

    A continuación, anule el registro en onDestroy:

     getApplicationContext().getContentResolver().unregisterContentObserver(mSettingsContentObserver); 

    Tenga en cuenta que este ejemplo juzga por el cambio de volumen de medios, si desea utilizar otro volumen, cambiarlo!

    ACTUALIZAR:

    Por encima del método supuestamente no funciona en Marshmallow, pero hay mucho mejor manera ahora desde MediaSession se introdujo! Así que primero tienes que migrar tu código a MediaController / MediaSession patrón y luego usar este código:

     private VolumeProviderCompat myVolumeProvider = null; myVolumeProvider = new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, maxVolume, currentVolume) { @Override public void onAdjustVolume(int direction) { // <0 volume down // >0 volume up } }; mSession.setPlaybackToRemote(myVolumeProvider); 

    De alguna manera las pulsaciones de botón de volumen se detectan incluso con la pantalla apagada (sólo asegúrese de registrar el receptor de intención de botones de medios adecuado, si es aplicable para su plataforma!)

    UPDATE 2 ya que GalDude pidió más información sobre cómo obtener medios MediaSession / MediaController. Lo siento, pero desde que dejé de usar Java será en Kotlin:

     lateinit var mediaSession: MediaSessionCompat // you have to initialize it in your onCreate method val kontroler: MediaControllerCompat get() = mediaSession.controller // in Java it's just getController() on mediaSession // in your onCreate/start method: mediaSession = MediaSessionCompat(this, "YourPlayerName", receiver, null) mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS or MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS) mediaSession.isActive = true if (ratingIsWorking) // note: rating crashes on some machines you have to check it! mediaSession.setRatingType(RatingCompat.RATING_5_STARS) mediaSession.setCallback(object : MediaSessionCompat.Callback() { ... // here you have to implement what happens with your player when play/pause/stop/ffw etc. is requested - see exaples elsewhere }) // onDestroy/exit method: mediaSession.isActive = false mediaSession.release() 

    La aplicación AOSP Music tiene un servicio ( MediaPlaybackService ) que responde a eventos de clave de volumen al registrar un BroadcastReceiver ( MediaButtonIntentReceiver ).

    Aquí está el fragmento de código donde registra el receptor:

      mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); ComponentName rec = new ComponentName(getPackageName(), MediaButtonIntentReceiver.class.getName()); mAudioManager.registerMediaButtonEventReceiver(rec); 

    Además, no se olvide de manifiesto:

      <receiver android:name="com.android.music.MediaButtonIntentReceiver"> <intent-filter> <action android:name="android.intent.action.MEDIA_BUTTON" /> <action android:name="android.media.AUDIO_BECOMING_NOISY" /> </intent-filter> </receiver> 

    Esto funciona incluso si la aplicación Música no está en primer plano. ¿No es eso lo que quieres?

    Android no documenta APIs al interactuar con los botones de volumen en ese caso. Así que supongo que la respuesta es no …

    Dependiendo del contexto en el que se requiera la devolución de llamada, podría estar disponible una solución alternativa.

    Para poder detectar el botón de volumen, una Actividad necesitará anular la función dispatchKeyEvent . Para que esto estuviera presente en múltiples actividades podría podría escribir una superclase que contiene la función anulada que se extiende por todas las actividades posteriores.

    Aquí está el código para detectar las pulsaciones de tecla de volumen hacia arriba / abajo:

      // Over-ride this function to define what should happen when keys are pressed (eg Home button, Back button, etc.) @Override public boolean dispatchKeyEvent(KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_DOWN) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: // Volume up key detected // Do something return true; case KeyEvent.KEYCODE_VOLUME_DOWN: // Volume down key detected // Do something return true; } } return super.dispatchKeyEvent(event); } 

    Yo era capaz de hacer que funcione en dispositivos Android MediaSession 5 MediaSession utilizando MediaSession . Sin embargo, ContentObserver sugerido por @ssuukk no funcionó para mí en los dispositivos 4.4 y 7.0 (al menos en ROMs que he estado probando). Aquí está un ejemplo completo que funciona en android 5+.

    Servicio:

     import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.support.v4.media.VolumeProviderCompat; import android.support.v4.media.session.MediaSessionCompat; import android.support.v4.media.session.PlaybackStateCompat; public class PlayerService extends Service { private MediaSessionCompat mediaSession; @Override public void onCreate() { super.onCreate(); mediaSession = new MediaSessionCompat(this, "PlayerService"); mediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS | MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS); mediaSession.setPlaybackState(new PlaybackStateCompat.Builder() .setState(PlaybackStateCompat.STATE_PLAYING, 0, 0) //you simulate a player which plays something. .build()); //this will only work on Lollipop and up, see https://code.google.com/p/android/issues/detail?id=224134 VolumeProviderCompat myVolumeProvider = new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, /*max volume*/100, /*initial volume level*/50) { @Override public void onAdjustVolume(int direction) { /* -1 -- volume down 1 -- volume up 0 -- volume button released */ } }; mediaSession.setPlaybackToRemote(myVolumeProvider); mediaSession.setActive(true); } @Override public IBinder onBind(Intent intent) { return null; } @Override public void onDestroy() { super.onDestroy(); mediaSession.release(); } } 

    En AndroidManifest.xml :

     <application ...> ... <service android:name=".PlayerService"/> </application> 

    En su actividad:

     @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ... startService(new Intent(this, PlayerService.class)); } 

    Hay varias cosas a tener en cuenta:

    • Intercepta completamente los botones de volumen mientras este código está en ejecución, no podrá ajustar el volumen del timbre con los botones de volumen. Esto podría ser posible para arreglarlo, simplemente no lo intenté.
    • Si ejecuta el ejemplo tal cual, los botones de volumen permanecerán controlados por la aplicación incluso cuando la pantalla esté desactivada y la aplicación haya sido eliminada de la lista de "Aplicaciones recientes". Tendrás que ir a Settings->Applications , encontrar la aplicación y obligarla a detenerla para recuperar los botones de volumen.

    Checkout Controlando el volumen y la reproducción de su aplicación … Esto ayudará a resolver su problema … varias aplicaciones podrían querer escuchar las pulsaciones de botones desde el fondo, esto puede ser la razón por la cual KeyEvents sólo puede ser manejado por Actividades como son la interfaz Al usuario presionando las teclas.

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.