辅助服务点击不在预期坐标中

问题描述 投票:0回答:1

所以我尝试基于这个存储库在android studio中创建一个带有辅助功能服务的自动点击器。

我有以下这样的辅助服务配置。

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canPerformGestures="true"
    android:canRetrieveWindowContent="true"
    android:notificationTimeout="100"
    android:description="@string/accessibility_service_description"
/>

这些是 kotlin 文件

FloatingClickService.kt

class FloatingClickService : Service() {
    private lateinit var manager: WindowManager
    
    private lateinit var view: View
    private lateinit var clickView: View
    
    private lateinit var params: WindowManager.LayoutParams
    private lateinit var clickParams: WindowManager.LayoutParams
    
    private var startDragDistance: Int = 0
    
    private var timer: Timer? = null
    
    private lateinit var btnStart: ImageButton
    private lateinit var btnSetting: ImageButton
    private lateinit var btnMove: ImageButton

    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        startDragDistance = dp2px(10f)
        manager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        view = createView(R.layout.widget)
        clickView = createView(R.layout.edittext_widget)

        //setting the layout parameters
        params = createLayoutParams()
        clickParams = createLayoutParams(true)

        //getting windows services and adding the floating view to it
        manager.addView(view, params)
        manager.addView(clickView, clickParams)
        
        btnStart = view.findViewById(R.id.btn_start)   
        btnSetting = view.findViewById(R.id.btn_setting)   
        btnMove = view.findViewById(R.id.btn_move)
        
        updateView()
        
        btnStart.setOnClickListener { 
            viewOnStart()
        }
        
        btnSetting.setOnClickListener {
            // setting action
        }
        
        setOnTouchListener()
    }

    private var isOn = false
    
    private fun createLayoutParams(custom: Boolean = false): WindowManager.LayoutParams {
        val overlayParam =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }

        return WindowManager.LayoutParams(
            if (custom) dp2px(48f) else WindowManager.LayoutParams.WRAP_CONTENT,
            if (custom) dp2px(48f) else WindowManager.LayoutParams.WRAP_CONTENT,
            overlayParam,
            WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
            PixelFormat.TRANSLUCENT)
    }
    
    private fun createView(layoutId: Int): View {
        val view = LayoutInflater.from(this).inflate(layoutId, null)

        //setting the layout parameters
        params = createLayoutParams(false)
        clickParams = createLayoutParams(true)

        //getting windows services and adding the floating view to it
        manager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        return view
    }
    
    private fun updateView() {
        if (isOn) {
            btnSetting.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.settings))
            btnSetting.isEnabled = false
            btnStart.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.pause))
        } else {
            btnSetting.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.setting_active))
            btnSetting.isEnabled = true
            btnStart.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.play))
        }
    }
    private fun viewOnStart() {
        if (isOn) {
            timer?.cancel()
            setOnTouchListener()
        } else {
            timer = fixedRateTimer(
                initialDelay = 0,
                period = 3000L
            ) {
                val location = IntArray(2)
                clickView.getLocationOnScreen(location)
                
                autoClickService?.click(location[0] + clickView.right, location[1] + clickView.bottom)
            }
            removeTouchListener()
        }
        isOn = !isOn
        updateView()
    }
    
    private fun removeView() {
        manager.removeView(view)
        manager.removeView(clickView)
    }
    
    @SuppressLint("ClickableViewAccessibility")
    private fun setOnTouchListener() {
        clickView.setOnTouchListener(
            TouchAndDragListener(clickParams, startDragDistance) {
                manager.updateViewLayout(clickView, clickParams)
            }
        )

        btnMove.setOnTouchListener(
            TouchAndDragListener(params, startDragDistance) {
                manager.updateViewLayout(view, params)
            }
        )
    }

    @SuppressLint("ClickableViewAccessibility")
    private fun removeTouchListener() {
        clickView.setOnTouchListener(null)
        btnMove.setOnTouchListener(null)
    }

    override fun onDestroy() {
        timer?.cancel()
        removeView()
        super.onDestroy()
    }
}

AutoClickService.kt

var autoClickService: AutoClickService? = null

class AutoClickService : AccessibilityService() {

    override fun onInterrupt() {
        // NO-OP
    }

    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        
    }

    override fun onServiceConnected() {
        autoClickService = this
        startActivity(
            Intent(this, MainActivity::class.java)
            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
    }

    fun click(x: Int, y: Int) {
        val path = Path()
        path.moveTo(x.toFloat(), y.toFloat())
        val builder = GestureDescription.Builder()
        val gestureDescription = builder
            .addStroke(GestureDescription.StrokeDescription(path, 10, 10))
            .build()
        dispatchGesture(gestureDescription, null, null)
    }
}

像这样启动服务

val serviceIntent = Intent(
    this@MainActivity,
    FloatingClickService::class.java
)
startService(serviceIntent)

实际结果是,点击的位置不是在视图的中心,而是在视图的右下角。如何让点击发生在clickView的中心?

我尝试获取视图的中心 x 和 y,但没有点击。我的期望是点击的图块应该与点视图相同。 (我希望点击发生在点视图的中心)

android accessibilityservice
1个回答
0
投票

我和你有同样的问题,我也使用了Nestorm001的源代码。 所以问题是因为当我们使用 PNG(像您使用的圆形),并且在该自定义布局中添加 onTouchListener 时,该侦听器将吸收辅助功能单击操作(如果您单击视图的中心)。我们仍然可以单击 PNG 的 4 个角,因为它是透明的,这会将单击操作传递到下面的视图。

我疯了两天,终于发现问题所在了。因此,如果您想修复它,在调用 Accessibility to click 之前,您必须更新该自定义布局的布局参数,如下所示:

layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; // important - disable touch event
wm.updateViewLayout(your_custom_view, layoutParams);

然后,当您想要停止自动单击时,请将标志更改为 FLAG_NOT_FOCUSABLE,以便您可以再次拖动并移动该自定义布局。

快乐编码。顺便说一句,对不起我的英语。

© www.soinside.com 2019 - 2024. All rights reserved.