30

我想知道这个按钮调用什么方法。

在此处输入图像描述

我的游戏总是正确暂停/恢复,除了当我使用这个按钮时,这个按钮似乎没有调用ActivityonPause()的andonResume()方法。如果我退出游戏,转到另一个窗口(如图片上的那个)然后使用此按钮继续,它会起作用。但是如果我只是按下这个按钮,当我进入游戏时,游戏会暂停,但线程不会像每隔一次那样恢复,游戏只是在屏幕上静止并闪烁了一下。

很难解释,但我希望我有点清楚,如果没有,请问!

4

8 回答 8

26

按下“最近的应用程序”按钮时,不会调用任何标准的活动生命周期方法。在最近的应用程序弹出列表之后,活动将保持活动状态。通过此列表的半透明左侧部分,您甚至可以观察到应用程序动画仍在运行,如果您运行的游戏带有一些没有正确处理这种情况的动画。实际上,Google Play 中的许多游戏都没有妥善处理这种情况,即使是好的游戏,比如愤怒的小鸟。

当用户打开“最近的应用程序”列表(或从它返回)时,唯一被调用的 Activity 方法是带有布尔参数的onWindowFocusChangedhasFocus。当用户打开使用equalsonWindowFocusChanged()调用的最近 App 方法列表时,当用户在此列表中按 Back 时,使用equals调用相同的方法。hasFocusfalsehasFocustrue

于 2012-09-20T09:48:09.270 回答
9

我有同样的问题,我解决了这个问题如下。

为 Home 和 RecentApp 注册按钮单击广播

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

现在广播接收器代码

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
                    }
                }
            }
        }
    }
}

但不要忘记unregisterReceiver广播接收器

于 2018-02-24T18:55:57.967 回答
6

要检测何时按下“最近的应用程序”按钮,您可以使用辅助功能服务。您需要运行自己的辅助功能服务并接收类型为“TYPE_WINDOW_STATE_CHANGED”的事件并检查事件的类名。

  1. 阅读android developer 中的无障碍服务。设置您自己的无障碍服务,请求用户许可。
  2. 在您的无障碍服务覆盖方法中onAccessibilityEvent()
  3. 在此方法中,您将收到AccessibilityEvent event对象,该对象包含有关您设备上刚刚发生的事件的所有必要信息。
  4. 我们对 ClassName 感兴趣。ClassName 有时可以为 null,所以不要忘记 != null 检查。最近应用程序窗口的包名称将根据 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”字母)

不知道旧设备的类名,但我认为 2017 年没有人维护它们;)

所以你会有这样的东西:

@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.
    }
}

我已经在以下真实设备上对其进行了测试:LG、Nexus、索尼和虚拟设备:摩托罗拉、三星。

如果有人知道这些类名的例外情况,请联系我。

于 2017-03-13T21:13:10.410 回答
4

我遇到了类似的问题,所以,我需要知道用户何时按下最近的应用程序按钮(旧版本的 android 中的菜单键按钮)。经过几个小时的研究,当按下主页按钮或菜单按钮时,我没有发现要捕获的事件。我发现onStop()当用户按下主页按钮时调用需要更长的时间,所以我想出了一个技巧来区分这些与响应时间相关的两个按钮并覆盖两种方法:

@覆盖

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

@覆盖

public void onStop() {
    super.onStop();
    if (isNotPower) {
        defStop = System.currentTimeMillis() - userLeaveTime;
        if (defStop > 200 ) {
            //home button
        }
        if (defStop < 200) {
            //recent apps button
        }
    }
    isNotPower = false;
}
  • isNotPower用于检查未按下电源按钮的参数 - 当按下电源按钮时调用该方法onStop(),但不调用onUserLeaveHint().
于 2015-10-06T06:37:21.037 回答
3

我发现最好的方法是收听名为“ACTION_CLOSE_SYSTEM_DIALOGS”的广播动作。来自谷歌文档:

广播操作:当用户操作应请求关闭临时系统对话框时广播。临时系统对话框的一些示例是通知窗口阴影和最近的任务对话框

工作代码:

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);
于 2017-03-30T10:53:51.967 回答
0

试试这个:

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

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

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

    }
}
于 2014-01-28T11:13:40.603 回答
0

这只是这个特定游戏的问题吗?还是你玩的每一场比赛都这样?

除了onPause()and之外onResume(),还有另一个循环叫做onStop()。也许这里正在做一些基本的事情。按下“windows-open”按钮后,游戏可能不会进入 toonStop状态,而按下“home”按钮则会。

于 2012-09-18T14:44:45.080 回答
0

我写了一个应用程序,它明确地展示了最近应用程序/最近在活动和片段方面的行为。

(任何关于正常生命周期事件不是由该键触发的断言显然是错误的。)

onCreate()Activity中初始化一个数组以记录所有已知的Activity生命周期事件,并在第二个 FrameLayout 中触发主 Fragment。

onAttach()Fragment中初始化一个单独的数组,用于记录所有已知的Fragment生命周期事件。

出于日志记录的目的,ActivityFragment都被视为onWindowFocusChanged()另一个生命周期事件。

记录的事件带有时间戳,因此可以在渲染时给出用户“暂停”指示(并且渲染发生在onWindowFocusChanged()when内hasFocus==true)。

以下是用户在启动测试应用程序时看到的内容:

在此处输入图像描述

几秒钟后,用户按下recent-apps,等待几秒钟,然后再次按下以查看真相:

在此处输入图像描述

注意:如果不使用最近的应用程序按钮,而是通过 (a) 按下平板电脑关闭/打开按钮 (b) 按下 Start 2nd Activity 按钮 (c) 等来重复实验,则会产生相同的结果。

对 OP 的回答:
显然没有代码可以检测到最近应用程序键的实际按下!

但这并不重要,因为无论如何应用程序都需要正确处理相关的生命周期事件。

于 2018-10-26T10:32:15.457 回答