如何在Android Studio的后台服务中检测屏幕是否被触摸?

9
我正在使用Android Studio开发一个项目。我需要在后台服务中检测屏幕是否被触摸(并弹出相应的消息)。但是,我在不影响用户使用智能手机的情况下,在后台服务中检测屏幕是否被触摸存在问题。
当我说“在后台检测”时,我的意思是应用程序的效果不会干扰用户在屏幕上所做的任何操作。下面是我的进展:
我制作了一个应用程序,通过在Android中实现onTouchListener并使用布局来检测用户在后台是否触摸了屏幕。我按照网站“http://kpbird.blogspot.com.au/2013/03/android-detect-global-touch-event.html”的说明进行操作,并对布局进行了一些更改,以覆盖整个屏幕,以便可以检测整个屏幕。
但是,当我运行创建保持检测屏幕触摸的服务的应用程序后,每次用户触摸屏幕时,该触摸都被我的服务(布局)吸收,因此用户无法正常使用他们的手机(如按图标启动其他应用程序)。这是因为布局覆盖整个屏幕并阻止任何触摸信息传递到它下面的图标(布局检测屏幕触摸),因此图标不知道有触摸事件发生,因此不会对用户做出反应。但是我希望我的应用程序和服务能够允许用户正常使用他们的手机。
我听说Android中的服务是设计为不与用户(即屏幕触摸)交互并在后台工作的,但我想知道是否有一种方法可以解决这个问题。
以下是我的服务代码:
public class GlobalTouchService extends Service implements OnTouchListener{

    private String TAG = this.getClass().getSimpleName();
    // window manager
    private WindowManager mWindowManager;
    // linear layout will use to detect touch event
    private LinearLayout touchLayout;
    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        // create linear layout
        touchLayout = new LinearLayout(this);
        // set layout width 30 px and height is equal to full screen
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        touchLayout.setLayoutParams(lp);
        // set color if you want layout visible on screen
        //touchLayout.setBackgroundColor(Color.CYAN);
        // set on touch listener
        touchLayout.setOnTouchListener(this);

        // fetch window manager object
        mWindowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
        // set layout parameter of window manager
        WindowManager.LayoutParams mParams = new WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT, // width is equal to full screen
                WindowManager.LayoutParams.MATCH_PARENT, // height is equal to full screen
                WindowManager.LayoutParams.TYPE_PHONE, // Type Phone, These are non-application windows providing user interaction with the phone (in particular incoming calls).
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, // this window won't ever get key input focus
                PixelFormat.TRANSLUCENT);
        mParams.gravity = Gravity.LEFT | Gravity.TOP;
        Log.i(TAG, "add View");

        mWindowManager.addView(touchLayout, mParams);

    }


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

    public void showAlert(View view) {
        AlertDialog.Builder myAlertBuilder = new AlertDialog.Builder(this);
        myAlertBuilder.setMessage(getString(R.string.alertMessage))
                .setTitle(getString(R.string.alertTitle))
                .setPositiveButton(getString(R.string.alertPositiveChoice), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                    }
                })
                .setNegativeButton(getString(R.string.alertNegativeChoice), new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        dialog.dismiss();
                        onDestroy();
                    }
                });
        AlertDialog myAlert = myAlertBuilder.create();
        myAlert.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        myAlert.show();
    }


    @Override
    public boolean onTouch(View v, MotionEvent event) {
        //if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP)
        //    Log.i(TAG, "Action :" + event.getAction() + "\t X :" + event.getRawX() + "\t Y :" + event.getRawY());
        ////////////////////
        View myView = null;
        //showAlert(myView);
        ///////////////////////
        return false;
    }
}
1个回答

1
你的 onTouch 方法中,只需返回 false,触摸事件就不会被你的应用程序所吸收。
请还要检查这个链接: https://dev59.com/LGw15IYBdhLWcg3w0fKh#6384443 编辑: 这可能不是你想要的,但如果你有 root 设备,你可以做类似于这样的事情:
adb shell getevent dev/input/event1

在我的情况下,event1负责触摸事件,但可能会有所不同。

1
现在onTouch方法返回false,但是当服务正在运行时,我仍然无法按下并打开主屏幕中的任何应用程序。我已经阅读了您发布的链接,也许ontouch()方法和onTouchEvent方法是不同的?我在我的服务类中实现了ontouch()方法,服务类实现了onTouchListener。 - Henry
在你所遵循的教程中,宽度被设置为30像素,而你将其设置为:WindowManager.LayoutParams.MATCH_PARENT。这就是为什么它覆盖了整个区域,你无法启动任何应用程序。尝试将布局的背景颜色设置为,这样你就可以看到它有多大了。 - user1723095
我正在制作一个应用程序,创建一个服务来检测屏幕上的任何触摸,因此我将宽度和高度设置为覆盖整个屏幕。现在的问题是,由用于检测屏幕触摸的服务创建的布局在我按下主屏幕中的其他应用程序图标时会消耗触摸事件。结果是,当服务正在运行时,我无法打开其他应用程序,也无法做任何事情。 - Henry
我不确定,但我认为在你的情况下发生的是,尽管你在布局中忽略了触摸事件(通过返回false),但触摸事件会传递给其父视图,而父视图无论如何都会消耗事件。也许你可以缩小这个区域并使用FLAG_WATCH_OUTSIDE_TOUCH,而不是覆盖整个屏幕。 - user1723095
我明白了。那么,我能否获取其父级并防止在那里消耗事件? - Henry
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接