É possível pausar qualquer aplicativo de vídeo (mediaplayer) no Android ao abrir o painel de notificações?

11

Suponha que eu tenha o código-fonte AOSP. Como posso pausar o aplicativo em primeiro plano ao puxar o painel de notificação? Pesquisei no Google e encontrei um aplicativo que pode ouvir o evento onWindowFocusChangee executar alguma ação de forma proativa, mas como posso pausar qualquer aplicativo ao abrir o painel de notificações, sem modificar todos os aplicativos respectivamente (o que é impraticável)?

Existe uma maneira de chamar a onPausefunção de qualquer aplicativo em primeiro plano a partir do processo SystemUI?

zhangxaochen
fonte
resposta adicionada a todas as suas perguntas, consulte isso - stackoverflow.com/a/59589825/9640177
mayank1513
A chave está iniciando uma atividade transparente quando a notificação é baixada. Isso chamará o método onPause da atividade atual. Considerando que solicitar o foco fará com que a reprodução da mídia seja pausada
mayank1513

Respostas:

10

Você pode usar o método abaixo para detectar a solicitação do painel de notificação,

No seu arquivo de manifesto

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

Em sua atividade, substitua onWindowFocusChanged()e escreva o código abaixo.

Isso usa a permissão

@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();
        }
    }
}

Em seguida, em sua solicitação de aplicativo para foco em áudio, consulte o link abaixo

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

Isso interromperá o acesso ao áudio para todos os outros aplicativos.

Akash Dubey
fonte
11
A recompensa @zhangxaochen expira em 5 horas, você já a perdeu e, se expirar, será desperdiçada !!
Akash Dubey
3

Existem duas partes na solução

  1. detecção de puxar painel de notificação
  2. pausando qualquer aplicativo de reprodução de mídia

Para detectar o recebimento do painel de notificação, você pode empregar o método sugerido por Akash ou o mesmo código aqui por Lalith.

No seu arquivo de manifesto

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

Em sua atividade, substitua onWindowFocusChanged () e escreva o código abaixo.

@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();
        }
    }
}

Na segunda parte, todos os reprodutores de mídia bem projetados implementam ouvintes de mudança de foco de áudio. Portanto, para pausar todos os aplicativos do media player, você pode solicitar um foco de áudio temporário ou total, dependendo se deseja permitir que os aplicativos sejam reproduzidos novamente assim que o painel de notificações for fechado.

Use as seguintes

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);

Não se esqueça de implementar o 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
    }
};

Existe uma maneira de chamar a função onPause de qualquer aplicativo em primeiro plano a partir do processo SystemUI?

Tanto quanto eu pesquisei sistema ui processo não está acessível. No entanto, você pode iniciar uma atividade com tema transparente .

No seu manifesto

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

veja isso e eu também testei pessoalmente criando atividades transparentes.

Isso significa que a atividade no topo agora é sua atividade transparente e o método onPause da outra atividade será chamado naturalmente. Depois que o painel de notificação estiver fechado, você poderá destruir esta atividade. E para garantir a segurança, você também pode definir o ouvinte do onTouch, criando uma exibição vazia que parece a tela que deve destruir a atividade do onTouch.

mayank1513
fonte
3

Supondo que o dispositivo Android use o MediaPlayer padrão , de acordo com este diagrama de estado , você pode usar o nativo pausee o stopestado.

Se você não quiser parar o som, provavelmente poderá alterar o volume do som usando uma VolumeAutomation ?

A STEFANI
fonte