¿Es posible pausar cualquier aplicación de video (reproductor multimedia) en Android cuando se despliega el panel de notificaciones?

11

Supongamos que tengo el código fuente de AOSP. ¿Cómo puedo pausar la aplicación en primer plano al desplegar el panel de notificaciones? Busqué en Google y encontré que una APLICACIÓN puede escuchar el evento onWindowFocusChangey tomar medidas de manera proactiva, pero ¿cómo puedo pausar CUALQUIER APLICACIÓN al desplegar el panel de notificaciones, sin modificar cada APLICACIÓN respectivamente (lo cual no es práctico)?

¿Hay alguna manera de llamar a la onPausefunción de cualquier aplicación en primer plano desde el proceso SystemUI?

zhangxaochen
fuente
respuesta agregada a todas sus preguntas, vea esto - stackoverflow.com/a/59589825/9640177
mayank1513
La clave está iniciando una actividad transparente cuando se retira la notificación. Esto llamará al método onPause de la actividad actual. mientras que la solicitud de enfoque causará una pausa en la reproducción de medios
mayank1513

Respuestas:

10

Puede usar el siguiente método para detectar la extracción del panel de notificaciones,

En su archivo de manifiesto

 <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />

En su actividad, anule onWindowFocusChanged()y escriba el siguiente código.

Esto usa el permiso

@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    try
    {
        if(!hasFocus)
        {
            Object service  = getSystemService("statusbar");
            Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
            Method collapse = statusbarManager.getMethod("collapse");
            collapse .setAccessible(true);
            collapse .invoke(service);
        }
    }
    catch(Exception ex)
    {
        if(!hasFocus)
        {
            try {
                Object service  = getSystemService("statusbar");
                Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
                Method collapse = statusbarManager.getMethod("collapse");
                collapse .setAccessible(true);
                collapse .invoke(service);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();                
            }
            ex.printStackTrace();
        }
    }
}

Luego, en su solicitud de aplicación para el enfoque de audio, consulte el siguiente enlace

https://developer.android.com/guide/topics/media-apps/audio-focus#java

Esto pausará el acceso de audio para todas las demás aplicaciones.

Akash Dubey
fuente
1
¡La recompensa @zhangxaochen expira en 5 horas, ya la perdiste y, si se vence, se desperdicia!
Akash Dubey
3

La solución tiene dos partes.

  1. detección de extracción del panel de notificaciones
  2. pausar cualquier aplicación de reproducción de medios

Para detectar la extracción del panel de notificaciones, puede emplear el método sugerido por Akash o el mismo código aquí por Lalith.

En su archivo de manifiesto

<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />

En su actividad, anule onWindowFocusChanged () y escriba el siguiente código.

@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    try
    {
        if(!hasFocus)
        {
            Object service  = getSystemService("statusbar");
            Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
            Method collapse = statusbarManager.getMethod("collapse");
            collapse .setAccessible(true);
            collapse .invoke(service);
        }
    }
    catch(Exception ex)
    {
        if(!hasFocus)
        {
            try {
                Object service  = getSystemService("statusbar");
                Class<?> statusbarManager = Class.forName("android.app.StatusBarManager");
                Method collapse = statusbarManager.getMethod("collapse");
                collapse .setAccessible(true);
                collapse .invoke(service);

            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();                
            }
            ex.printStackTrace();
        }
    }
}

Para la segunda parte, todos los reproductores multimedia bien diseñados implementan oyentes de cambio de enfoque de audio. Por lo tanto, para pausar todas las aplicaciones del reproductor de medios, puede solicitar un enfoque de audio temporal o completo dependiendo de si desea permitir que las aplicaciones se reproduzcan nuevamente tan pronto como el panel de notificaciones esté colapsado.

Usar siguiente

AudioManager audioManager = (AudioManager) Context.getSystemService(Context.AUDIO_SERVICE);
playbackAttributes = new AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_GAME)
    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
    .build();
focusRequest = new AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN)
    // replace AUDIOFOCUS_GAIN with AUDIOFOCUS_GAIN_TRANSIENT if you want to pause and again resume when notification panel collapsed
    .setAudioAttributes(playbackAttributes)
    .setAcceptsDelayedFocusGain(true)
    .setOnAudioFocusChangeListener(afChangeListener, handler)
    .build();
// to requestAudioFocus and pause other media apps
audioManager.requestAudioFocus(focusRequest);

// to resume again in case you requested AUDIOFOCUS_GAIN_TRANSIENT
audioManager.abandonAudioFocus(afChangeListener);

No olvides implementar AudioFocusChangeListener

AudioManager.OnAudioFocusChangeListener afChangeListener = new AudioManager.OnAudioFocusChangeListener() {
    @Override
    public void onAudioFocusChange(int focusChange) {
        // leave this empty if you don't need to handle audio focus for your app
    }
};

¿Hay alguna manera de llamar a la función onPause de cualquier aplicación en primer plano desde el proceso SystemUI?

Por lo que he investigado, el proceso ui del sistema no es accesible. Sin embargo, puede iniciar una actividad con un tema transparente .

En tu manifiesto

<activity android:name=".your.activity" android:theme="@android:style/Theme.Translucent.NoTitleBar" />

veo esto y también he probado personalmente la creación de actividad transparente.

Esto significa que la actividad en la parte superior ahora es su actividad transparente y, naturalmente, se llamará al método onPause de la otra actividad. Una vez que el panel de notificaciones está colapsado, puede destruir esta actividad. Y para estar seguro, también puede configurar onTouch listener creando una vista vacía que sienta la pantalla que debería destruir la actividad en Touch.

mayank1513
fuente
3

Suponiendo que el dispositivo Android usa el MediaPlayer predeterminado , de acuerdo con este diagrama de estado , puede usar el estado nativo pausey el stopestado.

Si solo desea detener el sonido, ¿es probable que cambie el volumen del sonido con una Automatización de volumen ?

Un stefani
fuente