How to detect "Recent Apps" system button clicks (Honeycomb+)

21,389

Solution 1

None of standard Activity Lifecycle methods is called when "Recent Apps" button pressed. Activity will stay active after list of recent apps popups. Through semi-transparent left part of this list you can even observe application animation is still running, if you running a game with some animation that didn't handle this situation properly. Actually many of games in Google Play didn't handle this situation properly, even good ones, like Angry Birds.

The only Activity method are getting called when user opens "Recent Apps" list (or returns from it) is onWindowFocusChanged with boolean parameter hasFocus. When user open list of Recent App method onWindowFocusChanged() called with hasFocus equals false, and same method called with hasFocus equals true when user pressing Back in this list.

Solution 2

I have same problem, i resolved this problem as below.er

Register button click broadcast for Home and RecentApp

InnerReceiver mReceiver = new InnerReceiver();
IntentFilter mFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
registerReceiver(mReceiver, mFilter);

Now BroadcastReceiver code

class InnerReceiver extends BroadcastReceiver {
    final String SYSTEM_DIALOG_REASON_KEY = "reason";
    final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
    final String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";

    @Override
    public void onReceive(Context context, Intent intent) {

        if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
            if (reason != null) {
                if (mListener != null) {
                    if (reason.equals(SYSTEM_DIALOG_REASON_HOME_KEY)) {
                        // Home Button click
                    } else if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
                        // RecentApp or Overview Button click
                    }
                }
            }
        }
    }
}

But Dont forgot to unregisterReceiver BroadcastReceiver

Solution 3

To detect when 'Recent apps' button was pressed you can use Accessibility Service. You'll need to run your own Accessibility Service and receive events with type "TYPE_WINDOW_STATE_CHANGED" and check event's class name.

  1. Read about Accessibility Service in android developer. Set up your own Accessibility Service, ask for permission from user.
  2. In your Accessibility Service override method onAccessibilityEvent()
  3. In this method you will receive AccessibilityEvent event object, this object contains all necessary information about an event that have just happened on your device.
  4. We are interested in the ClassName. ClassName sometimes can be null so don't forget about != null check. Package names of Recent apps window will vary depending on the version of Android:

    • Android 4.1: "com.android.internal.policy.impl.RecentApplicationsDialog"
    • Android 4.2 - 4.4: "com.android.systemui.recent.RecentsActivity"
    • Android 5.0 - 7.1: "com.android.systemui.recents.RecentsActivity" ("s" letter was added)

Don't know the class name for older devices but I don't think someone maintains them in 2017 ;)

So you will have something like this:

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    if (event.getEventType() != AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED || event.getClassName() == null) 
        return;

    String className = String.valueOf(event.getClassName());

    if (className.equals("com.android.internal.policy.impl.RecentApplicationsDialog")
            || className.equals("com.android.systemui.recent.RecentsActivity")
            || className.equals("com.android.systemui.recents.RecentsActivity")){
        //Recent button was pressed. Do something.
    }
}

I've tested it on the following real devices: LG, Nexus, Sony and virtual devices: Motorola, Samsung.

If someone knows exception for these class names please ping me.

Solution 4

I faced similar problem, so, I needed to know when the user press the recent apps button (menu key button in old versions of android). After a several hours of research I didn't found an event to catch when the home button or the menu button is pressed. I found that it's take a longer time to call onStop() when the user press the home button, so I figured out a trick to distinguish between these tow buttons relating on time of response and overriding two methods:

@Override

public void onUserLeaveHint() {
    // do stuff
    super.onUserLeaveHint();
    userLeaveTime = System.currentTimeMillis() ;
    isNotPower = true;
}

@Override

public void onStop() {
    super.onStop();
    if (isNotPower) {
        defStop = System.currentTimeMillis() - userLeaveTime;
        if (defStop > 200 ) {
            //home button
        }
        if (defStop < 200) {
            //recent apps button
        }
    }
    isNotPower = false;
}
  • The isNotPower parameter that's to check that not the power button is pressed- when the power button pressed the onStop() method is called but not the onUserLeaveHint().

Solution 5

The best way I have found is listent to Broadcast Action called "ACTION_CLOSE_SYSTEM_DIALOGS".From the Google docs:

Broadcast Action: This is broadcast when a user action should request a temporary system dialog to dismiss. Some examples of temporary system dialogs are the notification window-shade and the recent tasks dialog.

Working code:

IntentFilter intentFilterACSD = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);

    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
                    //do what you want here
            }
        }
    };
    this.registerReceiver(broadcastReceiver, intentFilterACSD);
Share:
21,389
Green_qaue
Author by

Green_qaue

Updated on June 19, 2021

Comments

  • Green_qaue
    Green_qaue almost 3 years

    I'm wondering what method this button calls.

    enter image description here

    My game always pauses/resumes correctly except for when I use this button, its seems like this button doesn't call the onPause() and onResume() methods of an Activity. It works if I exit the game, go to another window(like the one on the picture) and then use this button to resume. But If I just press this button, when ingame, the game pauses but the thread dosnt resume like it does every other time, the game kind of just stands still on screen and flickers a bit.

    Hard to explain but I hope I'm being sort of clear, if not, ask!

  • Green_qaue
    Green_qaue over 11 years
    good point, will try tagging some methods and see what happens.
  • Green_qaue
    Green_qaue over 11 years
    thank you, cleared it up a bit :) always good to know the machine your working with.
  • amram99
    amram99 over 9 years
    It seems that on Android 4.4.4, onPause/onStop are called when the recent apps button is pressed.
  • Bourne
    Bourne over 6 years
    But onWindowFocusChanged will also be false if you open another activity within the app, so it doesn't necessarily help knowing that "Recent Apps" button was hit (also called the Overview button now).
  • evanjmg
    evanjmg about 6 years
    I've done the full implementation here in android for react native github.com/evanjmg/react-native-home-pressed/blob/master/…
  • Manuel Ramírez
    Manuel Ramírez about 6 years
    This does work for detecting the recents app, but it doesn't trigger again to detect which app was brought to the foreground from that screen. Any insights?
  • Rahul Sharma
    Rahul Sharma over 5 years
    @Lokesh why onRecentAppClick is called twice in some devices like it is working fine with OnePlus 6 running on Android 9.0 but with Redmi 4 running on Android 7.1 it is called twice.
  • Lokesh
    Lokesh over 5 years
    @RahulSharma thanks for update, i will check and update answer soon