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!

有帮助吗?

解决方案

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.

其他提示

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

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.

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().

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

Is this only the problem with this specific game? Or is it with every game you play?

Beside the onPause() and onResume(), there is another cycle called onStop(). Maybe there are some fundamental things that are being done here. With the press of that "windows-open"-button, the game will probably not go into to onStop-state whereas pressing the "home"-button it will.

try this one:

public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);

    Log.d("Focus debug", "Focus changed !");

    if (!hasFocus) {
        Log.d("Focus debug", "Lost focus !");

    }
}

I wrote an app that unambiguously demonstrates the behavior of the recent-apps / recents key with respect to both Activities and Fragments.

(Any assertion that normal lifecycle events are not triggered by this key is patently false.)

In onCreate() the main Activity initializes an array for the logging of all known Activity lifecycle events and also fires the main Fragment alongside itself in a second FrameLayout.

In onAttach() the main Fragment initializes a separate array for the logging of all known Fragment lifecycle events.

For logging purposes, both Activity and Fragment treat onWindowFocusChanged() as just another lifecycle event.

Logged events are timestamped so a user 'pause' indication can be given when rendering (and rendering occurs inside onWindowFocusChanged() when hasFocus==true).

Here is what user sees when the test app is started:

enter image description here

After a few seconds user presses recent-apps, waits a few seconds, then presses it again to see the truth:

enter image description here

NB: If, instead of using the recent-apps button, the experiment is repeated by (a) pressing tablet off/on button (b) pressing Start 2nd Activity button(c) etc., identical results are yielded.

Answer to OP:
Apparently there is no code that can detect the actual pressing of the recent-apps key!

But it doesn't matter because the app needs to be correctly handling the associated lifecycle events anyway.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top