如何从诸如信使聊天头服务之类的服务中检测后退按钮/主页按下? [英] How to detect backbutton/home press from a service like messenger chat head service?

查看:70
本文介绍了如何从诸如信使聊天头服务之类的服务中检测后退按钮/主页按下?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在查看几个 stackoverflow 问题,以了解如何使用 Windows 管理器收听服务上的 backpress 按钮.大多数答案都表明这是不可能的,但是我可以看到该信使处理得很好.

I have been looking through several stackoverflow question to find out how can I listen to backpress button on a service using windows manager. Most of the answers proposes that it's not possible, however I can see that messenger handle it very well.

messenger 如何处理其头部聊天服务上的 backpress 按钮?(或者我完全错了,它们不是使用 Windows 管理器的服务?)

How does messenger handle the backpress button on it's head chat service? (Or I am completely wrong and they are not a service using windows manager?)

推荐答案

为了实现您的需求,您需要扩展一些您将用作视图根容器的 ViewGroup.让我们从这个开始:

To achieve what you need, you need to extend some ViewGroup that you are going to use as a root container for your views. Let's start with this:

public class BackButtonAwareLinearLayout extends LinearLayout {

    public interface BackButtonListener {
        void onBackButtonPressed();
    }

    @Nullable
    private BackButtonListener mListener;

    public BackButtonAwareLinearLayout(Context context) {
        super(context);
    }

    public BackButtonAwareLinearLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public BackButtonAwareLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public void setBackButtonListener(@Nullable BackButtonListener listener) {
        mListener = listener;
    }

    @Override
    public boolean dispatchKeyEvent(KeyEvent event) {
        if (event != null && event.getKeyCode() == KeyEvent.KEYCODE_BACK
                && mListener != null) {
            mListener.onBackButtonPressed();
            return true;
        }
        return super.dispatchKeyEvent(event);
    }
}

基本上,覆盖 dispatchKeyEvent 对我们来说是一个技巧.然后在一些xml中使用它(我称之为chat_head_container.xml):

Basically, overriding dispatchKeyEvent is what does a trick for us here. Then make a use of it in some xml (I have called it chat_head_container.xml):

<?xml version="1.0" encoding="utf-8"?>
<com.pablo432.myapplication.BackButtonAwareLinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="48sp"
        android:text="Hello, world!"
        android:textColor="#000"
        android:background="#f5f5f5"
        android:gravity="center"/>

</com.pablo432.myapplication.BackButtonAwareLinearLayout>

接下来,创建一个将我们的视图添加到 WindowManager 的服务(虽然我想你知道怎么做,但为了完整起见,我还是会发布它):

Next, create a Service that adds our view to the WindowManager (though I suppose you know how to do it, I'll post it anyway for the sake of completeness):

public class ChatHeadService extends Service
        implements BackButtonAwareLinearLayout.BackButtonListener {

    private WindowManager mWindowManager;
    private BackButtonAwareLinearLayout mRootContainer;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
        LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mRootContainer = (BackButtonAwareLinearLayout) inflater.inflate(
                R.layout.chat_head_container, null, false);
        mRootContainer.setBackButtonListener(this);

        WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                PixelFormat.TRANSPARENT);

        mWindowManager.addView(mRootContainer, layoutParams);
    }

    @Override
    public void onBackButtonPressed() {
        mRootContainer.setBackButtonListener(null);
        mWindowManager.removeView(mRootContainer);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mRootContainer != null) mWindowManager.removeView(mRootContainer);
    }
}

长话短说,BackButtonAwareLinearLayout 公开了一个侦听器接口,我们的服务需要实现并订阅自己的 Layout.

So long story short, BackButtonAwareLinearLayout exposes a listener interface, that our service needs to implement and subscribe itself to the Layout.

还要记住,这解决了处理后退按钮的问题.要处理主页按钮,您可能需要查看 https://stackoverflow.com/a/31340960https://stackoverflow.com/a/33580971 - 基本上我的回答是这两个链接的一些总结 + https://stackoverflow.com/a/15980900 但包含一些调整(例如,您不能在 WindowManager.LayoutParams 中设置 FLAG_NOT_FOCUSABLE).

Also have in mind that this addresses handling back button. To handle home button, you may want to take a look at https://stackoverflow.com/a/31340960 and https://stackoverflow.com/a/33580971 - basically my answer is a bit of a summary from those two links + https://stackoverflow.com/a/15980900 but contains few tweaks (like, for example, you can't set FLAG_NOT_FOCUSABLE in WindowManager.LayoutParams).

当然你需要通过调用 startService 来启动你的服务,在 AndroidManifest.xml 中声明这个服务并添加一个 SYSTEM_ALERT_WINDOW 权限.

Of course you need to start your service somewhere by calling startService, declare this service in AndroidManifest.xml and add a SYSTEM_ALERT_WINDOW permission.

这篇关于如何从诸如信使聊天头服务之类的服务中检测后退按钮/主页按下?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆