28

在作为 facebook messenger 应用程序的一部分的 facebook 聊天头中,我注意到以下行为:据我所知,聊天头本身和打开的聊天屏幕都是服务的一部分。不涉及任何活动。

我怎么能确定?在打开的聊天屏幕上按主页后,它会最小化回聊天头,我可以立即重新打开聊天屏幕。如果聊天屏幕是一个活动,然后startActivity(intent)在按下主页按钮后重新打开活动,将延迟活动的启动,如下所示: 在按下 HOME 按钮后从服务启动活动,没有 5 秒延迟

在这里:5 秒延迟显示按下主页按钮的活动的原因?

在我的服务 onCreate 方法中,我使用以下代码显示来自服务的 UI:

public class ServiceTest extends Service {
...
    @Override 
    public void onCreate() {
        super.onCreate();

        windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);

        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.WRAP_CONTENT,
            WindowManager.LayoutParams.TYPE_PHONE,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT);

        windowManager.addView(someView, params);
    }
....
}

有谁知道如何直接从显示 UI 的服务接收“按下主页按钮”事件?当用户按下主页按钮时,我想最小化我的视图(类似于 facebook 聊天头)。

4

8 回答 8

12

在对这个问题进行了自己的研究之后,我得出了以下结论:

TYPE_SYSTEM_OVERLAYFacebook 通过提供 flag属性“拦截”导航按钮。查看@jawsware 提供的 这个帖子答案

做他建议不要做的事——会导致控制导航按钮的“影响”

使用此标志可将焦点集中在您的叠加层上,并从后面的活动中获取焦点。

使用onFocusChangedListener视图回调或OnKey 侦听器,它们会通过关闭覆盖的全屏模式来对其做出反应。

这也解释了他们如何通过 3 个导航按钮对它做出反应 - 主页/返回/最近的任务

于 2013-08-17T12:35:48.547 回答
5

您可以通过重写 View.onCloseSystemDialogs() 来实现它。您可能需要检查 View.java,因为此方法在 API 文档中不可见。

显然,我们通常无法检测到“按下主页按钮”。在大多数情况下,窗口是由 startActivity() 创建的。由“按下主页按钮”引起的 CloseSystemDialogs 例程由 android 框架的内部类 PhoneWindow.DecorView 作为 ViewRootImpl 的视图祖先处理。但是当我们直接将视图添加到窗口管理器时,ViewRootImpl 的视图祖先是我们的自定义视图,但 PhoneWindow.DecorView。查看 ViewRootImpl.java 的源代码可能更容易理解。

KeyEvent.KEYCODE_APP_SWITCH 也会导致 closeSystemDialogs 例程。这解释了 facebook 聊天头是如何工作的。

于 2013-09-16T14:41:45.560 回答
2

好的完整编辑我的答案,

在您的活动中覆盖以下方法。

 @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        this.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD);           
    }

覆盖上述方法后,现在您可以使用 onKeyDown() 方法轻松地在您的活动中收听 HOME 按键。

  @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {     

        if(keyCode == KeyEvent.KEYCODE_HOME)
        {
           //The Code Want to Perform. 
        }
    });

试试这个希望它有帮助

于 2013-08-07T12:26:04.610 回答
2

您可以监控(例如每 200 毫秒检查一次)最高运行活动,查看它是您的活动还是其他活动,并知道它何时发生变化。这也可以让您处理来电等情况。

ActivityManager am = (ActivityManager) context.getSystemService(Activity.ACTIVITY_SERVICE);
am.getRunningTasks(1).get(0).topActivity...
于 2013-08-17T05:08:55.383 回答
2

这是工作示例代码。

mLinear =  new LinearLayout(getApplicationContext()) {

          //home or recent button
          public void onCloseSystemDialogs(String reason) {
              //The Code Want to Perform. 
          }

          @Override
          public boolean dispatchKeyEvent(KeyEvent event) {
              if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
                || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_UP
                || event.getKeyCode() == KeyEvent.KEYCODE_VOLUME_DOWN
                || event.getKeyCode() == KeyEvent.KEYCODE_CAMERA ) {

              //The Code Want to Perform.
              }
          return super.dispatchKeyEvent(event);
          }
};

mLinear.setFocusable(true);

View mView = inflate.inflate(R.layout.floating_panel_layout, mLinear);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);

//params
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
             width,
             height,
             WindowManager.LayoutParams.TYPE_SYSTEM_ALERT,
             WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                    | WindowManager.LayoutParams.FLAG_FULLSCREEN
                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
              PixelFormat.TRANSLUCENT);
params.gravity = Gravity.LEFT | Gravity.CENTER_VERTICAL;
wm.addView(mView, params);
于 2016-02-09T15:09:05.870 回答
2

这是我的方式。它工作正常。把它放在 onReceive() 函数中。

if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
    {
        String reason = intent.getStringExtra(SYSTEM_REASON);

        //Toast.makeText(context,"ACTION_CLOSE_SYSTEM_DIALOGS : Reason : " + reason ,Toast.LENGTH_LONG).show();

        // Detect home screen key press or "recent app" key pressed when screen is in unlocked state
        if (reason != null)
        {
            if (reason.equals(SYSTEM_HOME_KEY))
            {
            // For Home press
            }
            else if (reason.equals(SYSTEM_RECENT_APPS))
            {
            // For long press
            }
        }
    }
于 2016-02-18T15:26:27.937 回答
1

我相当肯定 facebook 不会监听主页按钮的按下,因为它们的逻辑要求聊天头出现,无论什么应用程序可见,只要它不是 facebook。

一种简单粗暴的方法是visible在您的应用程序单例中维护一个静态标志,并从您拥有的每个活动中修改它。在 onPause() 中,将其设置为 false,并在 onResume() 和 onCreate() 中将其设置为true

然后简单地检查这个标志的状态,并采取相应的行动。如果它是真的,这意味着你的应用程序是可见的。

您可能希望在执行操作之前添加一个小暂停,以防止每次更改 Activity 时注入的 View 闪烁。

于 2013-08-07T15:03:25.993 回答
0

您可以将类别 HOME 添加到清单文件中。

于 2013-08-17T22:14:36.837 回答