Android - Use SYSTEM_OVERLAY to change touch events

China☆狼群 提交于 2020-01-16 04:37:11

问题


My question is pretty much similar to this one. The question was asked almost 3 years ago and was not answered yet.

My goal is to catch all touch-events using a system-overlay (see code below), change the event's parameters (i.e. event.x = event.getX()+5) and pass it on to the current running application (any application).

Currently, I can catch all MotionEvent's by using the TYPE_PHONE flag OR pass all of the events to to the current application by using the TYPE_SYSTEM_OVERLAY, but not both.

The application is used for accessibility purpose so using any accessibility ability is also an option.

The basic code for the overlay service:

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.os.IBinder;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.Toast;


public class OverlayService extends Service {
    OverlayView oView;

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

    @Override
    public void onCreate() {
        super.onCreate();

        oView = new OverlayView(this);
        WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.FILL_PARENT,
                WindowManager.LayoutParams.FILL_PARENT,
                WindowManager.LayoutParams.TYPE_PHONE, // TYPE_SYSTEM_OVERLAY
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
              | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
              | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT);

        params.gravity = Gravity.CENTER;
        WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
        wm.addView(oView, params);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if(oView != null)
        {
            ((WindowManager) getSystemService(WINDOW_SERVICE)).removeView(oView);
            oView = null;
        }
    }

}

class OverlayView extends View {
    private Paint mLoadPaint;

    public OverlayView(Context context) {
        super(context);
        setBackgroundColor(Color.BLUE);
        getBackground().setAlpha(128);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN){
            Toast.makeText(getContext(), "Touch", Toast.LENGTH_SHORT).show();

            //********************** THIS IS WHERE I NEED YOUR HELP *************
        }
        return false;
    }
}

Any advise will be much appreciated.


回答1:


My goal is to catch all touch-events using a system-overlay (see code below), change the event's parameters (i.e. event.x = event.getX()+5) and pass it on to the current running application (any application).

That is not possible, for privacy and security reasons.

Currently, I can catch all MotionEvent's by using the TYPE_PHONE flag OR pass all of the events to to the current application by using the TYPE_SYSTEM_OVERLAY, but not both.

Correct. That was the fix added in Android 4.0 to defend against tapjacking attacks, which is what you are trying to do whether you realize it or not.

The application is used for accessibility purpose so using any accessibility ability is also an option.

I cannot rule out that possibility, though I don't see low-level touch events in AccessibilityEvent, let alone modifying them. This would be a fairly radical departure from the approach that you are taking and as such would warrant a separate Stack Overflow question.



来源:https://stackoverflow.com/questions/29156556/android-use-system-overlay-to-change-touch-events

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