AccessibilityService.kt
import android.accessibilityservice.AccessibilityService
import android.os.Handler
import android.os.Looper
import android.view.accessibility.AccessibilityEvent
import android.view.accessibility.AccessibilityNodeInfo
import android.view.accessibility.AccessibilityNodeInfo.ACTION_SCROLL_FORWARD
class MyAccessibilityService : AccessibilityService() {
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
}
override fun onInterrupt() {
}
override fun onServiceConnected() {
super.onServiceConnected()
performActionsForMaps()
}
private fun performActionsForMaps() {
performGlobalAction(GLOBAL_ACTION_HOME)
Handler(Looper.getMainLooper()).postDelayed({
scrollDownUntilTextAppears("Maps")
}, 2000)
}
private fun scrollDownUntilTextAppears(targetText: String) {
val maxScrollAttempts = 10
var scrollAttempts = 0
while (!isTextVisible(targetText) && scrollAttempts < maxScrollAttempts) {
val rootNode = rootInActiveWindow
val scrollableNode = findScrollableNode(rootNode)
if (scrollableNode != null) {
Handler(Looper.getMainLooper()).postDelayed({
scrollableNode.performAction(ACTION_SCROLL_FORWARD)
}, 1000)
}
scrollAttempts++
}
if (isTextVisible(targetText)) {
clickOnText(targetText)
}
}
private fun findScrollableNode(nodeInfo: AccessibilityNodeInfo?): AccessibilityNodeInfo? {
if (nodeInfo == null) return null
for (i in 0 until nodeInfo.childCount) {
val childNode = nodeInfo.getChild(i)
if (childNode != null && childNode.isScrollable) {
return childNode
}
val scrollableChild = findScrollableNode(childNode)
if (scrollableChild != null) {
return scrollableChild
}
}
return null
}
private fun isTextVisible(targetText: String): Boolean {
val rootNode = rootInActiveWindow
return isTextVisibleRecursive(rootNode, targetText)
}
private fun isTextVisibleRecursive(
nodeInfo: AccessibilityNodeInfo?,
targetText: String
): Boolean {
if (nodeInfo == null) return false
for (i in 0 until nodeInfo.childCount) {
val childNode = nodeInfo.getChild(i)
if (childNode != null) {
if (childNode.text != null && targetText.equals(
childNode.text.toString(),
ignoreCase = true
)
) {
return true
}
if (isTextVisibleRecursive(childNode, targetText)) {
return true
}
}
}
return false
}
private fun clickOnText(targetText: String) {
val rootNode = rootInActiveWindow
clickOnTextRecursive(rootNode, targetText)
}
private fun clickOnTextRecursive(nodeInfo: AccessibilityNodeInfo?, targetText: String) {
if (nodeInfo == null) return
for (i in 0 until nodeInfo.childCount) {
val childNode = nodeInfo.getChild(i)
if (childNode != null) {
if (childNode.text != null && targetText.equals(
childNode.text.toString(),
ignoreCase = true
)
) {
childNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)
return
}
clickOnTextRecursive(childNode, targetText)
}
}
}
companion object {
private const val TAG = "MyAccessibilityService"
}
}
I am using AccessibilityService to automatically go home, then scroll down till it finds "Maps". After finding Maps, tap on it to open the Maps application.
I want this to happen immediately once I allow that service in settings, reason being i make use of onServiceConnected().
Maybe you can try using
StartActivityto start the Map App instead of perform auto scroll and click the App icon?For example:
Refer to: https://developer.android.com/training/basics/intents/sending