Android 辅助功能应用程序未执行滑动手势

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

我一直致力于创建一个 Android 应用程序,该应用程序可以每 5 秒在屏幕上执行一次向上滑动手势。这个想法是让它滚动任何打开的应用程序,例如 Instagram 上的 reels、Facebook 时间线或 Pintrest。

我已确保为应用程序提供所需的所有权限,正确设置 Android 清单,并配置辅助功能服务。我还整理了我认为 GestureAccessibilityService 类的正确代码。

但它没有做它应该做的事情。我一直在试图找出代码有什么问题。请帮忙。

accessibility_service_config.xml

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

Android 清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"> 

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.ThumbD"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <service
            android:name=".ScrollAccessibilityService"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            android:exported="false">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
                android:name=".ScrollAccessibilityService"
                android:resource="@xml/accessibility_service_config"/>
        </service>
    </application>

</manifest>

GestureAccessibilityService.kt

class GestureAccessibilityService:AccessibilityService() {

    private val TAG = "GESTURE"

    private val handler = Handler(Looper.getMainLooper())
    private val gestureRunnable = object : Runnable {
        override fun run() {
            performSwipeUp()
            //dispatch(0f,0f,0f,200f, applicationContext)
            handler.postDelayed(this, 5000) // Repeat every 5 seconds (5000 milliseconds)
        }
    }
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
    }

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

    override fun onServiceConnected() {
        super.onServiceConnected()
        "onServiceConnected".logd()
        handler.postDelayed(gestureRunnable, 0)
    }

    override fun onDestroy() {
        super.onDestroy()
        // Stop the repeating gesture when the service is destroyed
        handler.removeCallbacks(gestureRunnable)
    }

    private fun performSwipeUp() {
        val displayMetrics = resources.displayMetrics
        val screenHeight = displayMetrics.heightPixels

        val gestureDescription = GestureDescription.Builder()
            .addStroke(
                GestureDescription.StrokeDescription(
                    Path().apply {
                        moveTo(displayMetrics.widthPixels / 2f, screenHeight * 0.8f)
                        lineTo(displayMetrics.widthPixels / 2f, screenHeight * 0.2f)
                    },
                    0,
                    500
                )
            )
            .build()

        val result = dispatchGesture(gestureDescription, object : GestureResultCallback() {
            override fun onCompleted(gestureDescription: GestureDescription?) {
                super.onCompleted(gestureDescription)
                "Gesture completed".logd()
            }

            override fun onCancelled(gestureDescription: GestureDescription?) {
                super.onCancelled(gestureDescription)
                "Gesture cancelled".logd()
            }
        }, null)
        "STATUS $result".logd()
    }

    fun dispatch(x: Float, y: Float,xx: Float, yy: Float, context:Context): Boolean {
        try {
            val accessibilityManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager

            val isEnabled = accessibilityManager.isEnabled
            if (isEnabled) {
                val result = dispatchGesture(
                    buildSwipe(x, y, xx, yy),
                    object : GestureResultCallback() {
                        override fun onCompleted(gestureDescription: GestureDescription?) {
                            super.onCompleted(gestureDescription)
                            "Gesture completed".logd()
                        }

                        override fun onCancelled(gestureDescription: GestureDescription?) {
                            super.onCancelled(gestureDescription)
                            "Gesture cancelled".logd()
                        }
                    },
                    null
                )

                "STATUS $result".logd()
                return result
            } else {
                // Accessibility service is not enabled
                return false
            }
        }catch (e: Exception) {
            "Error dispatching gesture: ${e.message}".logd()
            e.printStackTrace()
            return false
        }
    }

    private fun buildSwipe(
        startX: Float,
        startY: Float,
        endX: Float,
        endY: Float
    ): GestureDescription {
        val swipePath = Path()
        swipePath.apply {
            moveTo(startX, startY)
            lineTo(endX, endY)
        }
        val swipeBuilder = GestureDescription.Builder()
        swipeBuilder.addStroke(GestureDescription.StrokeDescription(swipePath, 0, 100L))
        return swipeBuilder.build()
    }

}

MainActivity.kt

class MainActivity : AppCompatActivity() {
 
    private lateinit var binding: ActivityMainBinding
  
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)  

        /*Permissions*/
        val permissions = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
            listOf(
                Manifest.permission.FOREGROUND_SERVICE_SPECIAL_USE,
                Manifest.permission.BIND_ACCESSIBILITY_SERVICE
            )
        } else {
            listOf(Manifest.permission.BIND_ACCESSIBILITY_SERVICE)
        }

        checkPermissions(permissions) 

        if(isAccessibilityServiceEnabled(this)){
            "started sevices------->".logd()
        }
    }

    fun permissionAccessServices(view: View){
        openAccessibilitySettings(this)
    }

    
    private fun checkPermissions(permissions: List<String>){
        PermissionX.init(this)
            .permissions(permissions)
            .request { allGranted, grantedList, deniedList ->
                if (allGranted) {
                    Log.d("Permission","SuccessFull");
                } else {
                    Log.d("Permission","Failed $deniedList");
                }
            }
    }

    private fun isAccessibilityServiceEnabled(mContext: Context): Boolean {
        var accessibilityEnabled = 0
        val service: String = mContext.packageName + "/" + GestureAccessibilityService::class.java.canonicalName
        try {
            accessibilityEnabled = Settings.Secure.getInt(
                mContext.applicationContext.contentResolver,
                Settings.Secure.ACCESSIBILITY_ENABLED
            )
            "accessibilityEnabled = $accessibilityEnabled".logd()

        } catch (e: Settings.SettingNotFoundException) {
            "Error finding setting, default accessibility to not found: ${e.message}".logd()
        }
        val mStringColonSplitter = TextUtils.SimpleStringSplitter(':')
        if (accessibilityEnabled == 1) {
            "Accessibility Is Enabled".logd()
            val settingValue: String = Settings.Secure.getString(
                mContext.applicationContext.contentResolver,
                Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
            )
            if (settingValue != null) {
                mStringColonSplitter.setString(settingValue)
                while (mStringColonSplitter.hasNext()) {
                    val accessibilityService = mStringColonSplitter.next()
                    "AccessibilityService :: $accessibilityService $service".logd()
                    if (accessibilityService.equals(service, ignoreCase = true)) {
                        "accessibility is switched on!".logd()
                        return true
                    }
                }
            }
        } else {
            "accessibility is disabled".logd()
        }
        return false
    }
}
android kotlin accessibility accessibilityservice
1个回答
0
投票

因此,Android Manifest 中存在错误。元标记的值不正确。如果有人想要创建自动滚动器,他们只需复制上面提供的代码并将以下代码片段添加到他们的 Android 清单中即可。通过此调整,他们将拥有一个能够在任何应用程序上执行手势的功能应用程序。

<service
            android:name=".GestureAccessibilityService"
            android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
            android:enabled="true"
            android:exported="true"
            android:foregroundServiceType="specialUse"
            android:process=":AccessibilityService">
            <intent-filter>
                <action android:name="android.accessibilityservice.AccessibilityService"/>
            </intent-filter>
            <meta-data
            <-- android:name=".GestureAccessibilityService" -->
                android:name="android.accessibilityservice" // this is correct
                android:resource="@xml/accessibility_service_config"/>
        </service>
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.