How to detect auto clicker app used by android user?

限于喜欢 提交于 2021-02-07 11:00:43

问题


Some android user using auto-clicker apps available on play-store to click multiple time.

So I want to detect/block user who tries to use auto-clicker.Is there any way in android to detect such users?If yes, then how we can detect those users?


回答1:


There is no API to detect if an autoclicker is running. All autoclickers use accessibility services to emulate clicks, and there is an API that allows you to detect if any accessibility service is running. The problem is, those services also include screen readers and other useful tools for disabled people. You definitely shouldn't block your users just because they're using accessibility services.

However, you can also detect "unnatural" clicks and gestures. No human can perform several gestures starting at exactly the same point on the screen, finishing at exactly the same point and spending exactly the same amount of time on each gesture.

And when you detect that user is
a) using an accessibility service
b) performing unnatural clicks
you can reasonably assume that he is using an autoclicker. You can then block his touches or do whatever you want to do.

In order to detect unnatural touches you'll have to analyze all incoming touch events. Easiest way to get all those touches is to override onInterceptTouchEvent method of your root container.

E.g., create this class and use it as root for your layout:

class AutoclickerFrameLayout @JvmOverloads constructor(
        context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : FrameLayout(context, attrs, defStyleAttr) {

    override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
        AutoclickerDetector.recordEvent(event)
        // If you return true in this method touches will be blocked
        return false
    }

}

When analyzing MotionEvents keep in mind that even for autoclicker, reported coordinates and time can carry very slightly. For example, you can use this implementation:

object AutoclickerDetector {

    fun isAccessibilityServiceEnabled(context: Context): Boolean {
        val am = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
        val enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
        return enabledServices.isNotEmpty()
    }

    var isDetectingSimilarGestures = false
        private set

    private data class Touch(
            val x: Float,
            val y: Float,
            val time: Long
    ) {

        fun isSimilar(other: Touch): Boolean {
            return abs(this.x - other.x) < 1.0f
                    && abs(this.y - other.y) < 1.0f
        }

    }

    private data class Gesture(
            val start: Touch,
            val end: Touch
    ) {

        val duration: Long = end.time - start.time

        fun isSimilar(other: Gesture): Boolean {
            return this.start.isSimilar(other.start)
                    && this.end.isSimilar(other.end)
                    && abs(this.duration - other.duration) < 50
        }

    }

    private var gestureStart: Touch? = null
    private val recentGestures = ArrayList<Gesture>()

    fun recordEvent(event: MotionEvent) {
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                gestureStart = Touch(event.rawX, event.rawY, System.currentTimeMillis())
            }
            MotionEvent.ACTION_UP -> {
                gestureStart?.let { gestureStart ->
                    val gestureEnd = Touch(event.rawX, event.rawY, System.currentTimeMillis())
                    recentGestures.add(Gesture(gestureStart, gestureEnd))
                    trimGestureHistory()
                    checkSimilarGestures()
                }
                gestureStart = null
            }
        }
    }

    private const val HISTORY_SIZE = 20

    private fun trimGestureHistory() {
        while (recentGestures.size > HISTORY_SIZE) {
            recentGestures.removeAt(0)
        }
    }

    private fun checkSimilarGestures() {
        recentGestures.forEachIndexed { i, searchGesture ->
            var similarCount = 0
            recentGestures.forEachIndexed { j, compareGesture ->
                if (i != j && searchGesture.isSimilar(compareGesture)) {
                    similarCount++
                }
            }
            if (similarCount > 2) {
                // There is no way user can physically perform almost exactly the same gesture
                // 3 times amongst 20 last gestures
                isDetectingSimilarGestures = true
                return
            }
        }
        isDetectingSimilarGestures = false
    }

}

Then in your main code you can check if autoclicker is currently working:

AutoclickerDetector.isAccessibilityServiceEnabled(context) 
    && AutoclickerDetector.isDetectingSimilarGestures


来源:https://stackoverflow.com/questions/61772506/how-to-detect-auto-clicker-app-used-by-android-user

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