Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to pause any video (mediaplayer) APP in Android when pull down the notification panel?

Assume I have the AOSP source code, How can I pause the APP in the foreground when pulling down the notification panel? I've googled and find an APP can listen the event onWindowFocusChange and take some action proactively, but how can I pause ANY APP when pulling down the notification panel, without modify every APP respectively (which is impractical)?

Is there a way that I can call the onPause function of any foreground App from the SystemUI process?

like image 218
zhangxaochen Avatar asked Dec 30 '19 01:12

zhangxaochen


People also ask

What is on pause in Android?

App pause is a feature in Android Q which allows us as users to pause a specific application for that day. Once an application is in pause state, you will not receive notifications from the app for the rest of the day.

What is MediaPlayer release?

android.media.MediaPlayer. MediaPlayer class can be used to control playback of audio/video files and streams.

Which class provides methods to play and control the video player?

MediaController class provides the playback controls of video player such as play, pause, backward, forward, etc. to control the video player. Using VideoView and MediaController class we can create a video player.


3 Answers

You can use below method for detecting the notification panel pull,

In your manifest file

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

In your activity override the onWindowFocusChanged() and write the below code.

This uses the permission

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

Then in your app request for audio focus, refer below link

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

This will pause audio access for all other apps.

like image 185
Akash Dubey Avatar answered Oct 07 '22 02:10

Akash Dubey


There are two parts to the solution

  1. detecting notification panel pull
  2. pausing any media playing app

For detecting notification panel pull you may employ the method suggested by Akash or same code here by Lalith.

In your manifest file

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

In your activity override the onWindowFocusChanged() and write the below code.

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

For the second part all well designed media players implement Audio Focus Change Listeners. Thus to pause all media player apps you can request temporary or full audio focus depending on whether you want to let the apps play again as soon as notification panel is collapsed.

Use following

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

Don't forget to implement 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
    }
};

Is there a way that I can call the onPause function of any foreground App from the SystemUI process?

As far as I have researched system ui process is not accessible. However, you can launch an activity with transparent theme.

In your manifest

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

see this and I have also personally tested creating transparent activity.

This means that the activity on top now is your transparent activity and the onPause method of the other activity will naturally be called. Once the notification panel is collapsed you can destroy this activity. And to be on safe side you can also set onTouch listener by creating an empty view that feels the screen which should destroy the activity onTouch.

like image 29
mayank1513 Avatar answered Oct 07 '22 02:10

mayank1513


Assuming that the Android device use the default MediaPlayer, according to this state diagram, you may use the native pause and stop state.

If you only wan't to stop sound, you may probably change the sound volume using a VolumeAutomation ?

like image 3
A STEFANI Avatar answered Oct 07 '22 00:10

A STEFANI