问题
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.
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?)
回答1:
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);
}
}
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>
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);
}
}
So long story short, BackButtonAwareLinearLayout exposes a listener interface, that our service needs to implement and subscribe itself to the Layout.
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).
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.
来源:https://stackoverflow.com/questions/42821520/how-to-detect-backbutton-home-press-from-a-service-like-messenger-chat-head-serv