Overlay App that reacts only on some touch events

一世执手 提交于 2019-12-07 18:26:17

问题


I'm currently diving into Android development and recently came up against a difficulty. I'd like to create an overlay app, which lies on top of all other apps. It should listen for a three finger swipe, whereas all other Touch Events should be handled by the OS (e.g. an underlying app).

Is that even possible?

I already found out that I need to add the LayoutParam TYPE_PHONE instead of SYSTEM_ALERT since the latter one will consume all touch events. So my class looks like this now:

package [...]

public class Overlay extends Service {

    private TView mView;
    private ThreeFingerSwipeDetector detector = new ThreeFingerSwipeDetector() {

        @Override
        public void onThreeFingerTap() {
            Toast.makeText(getBaseContext(), "Three Fingers recognized.", Toast.LENGTH_SHORT).show();
        }
    };

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

    @Override
    public void onCreate() {
        super.onCreate();
        Toast.makeText(getBaseContext(), "Launched! :-)", Toast.LENGTH_SHORT).show();

        mView = new TView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.WRAP_CONTENT,
                WindowManager.LayoutParams.WRAP_CONTENT,
                // PHONE, because SYSTEM_ALERT will consume _ALL_ touch events
                WindowManager.LayoutParams.TYPE_PHONE,
                WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                      | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                      | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);
        params.gravity = Gravity.RIGHT | Gravity.TOP;
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(mView, params);
    }



    @Override
    public void onDestroy() {
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.removeView(mView);
        mView = null;
        super.onDestroy();
    }





    // inner class 
    class TView extends ViewGroup {

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

        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
        }

        @Override
        protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
        }



        @Override
        public boolean onTouchEvent(MotionEvent event) {
            if(detector.onTouchEvent(event)) {
                return true;
            }

            //TODO: what am I supposed to do when it's not a 3 finger swipe (aka the detector doesn't recognize it as one)
// something like super.onInterceptTouchEvent(event) or so?
            }
    }
    }

The detector will correctly detect a 3 finger swipe but my app in its current state will block all other user interaction with the underlying UI until I kill the app.

Is there any system call that can be called with MotionEvent as parameter where my TODO annotation is now? Or do I want something that is just not possible?

Best regards and thank you very much!

Edit: The ThreeFingerSwipeDetector Class looks like this:

[Import, ...]    
public abstract class ThreeFingerSwipeDetector {


    public boolean onTouchEvent(MotionEvent event) {
        int t = event.getActionMasked();
        switch(event.getActionMasked()) {
        case MotionEvent.ACTION_POINTER_DOWN:
            if(event.getPointerCount() == 3)
                onThreeFingerTap();
                return true;
        case MotionEvent.ACTION_DOWN:
            if(event.getPointerCount() == 3)  {
                onThreeFingerTap();
                return true;
        }               
      }

        return false;
    }

    public abstract void onThreeFingerTap();
}

Actually it's not a swipe recognizer yet but it only checks for three finger taps for now. Anyways the logic in there should be quite the same.


回答1:


I'll answer my own question: It's simply not possible. According to THIS post and the Android documentation you can either consume all touch events or none since version 4.0.3. So it's not possible to handle only some touch events and to let others go through the overlay.



来源:https://stackoverflow.com/questions/25917844/overlay-app-that-reacts-only-on-some-touch-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!