增加无障碍事件
This commit is contained in:
@@ -64,6 +64,12 @@ module.exports = function (scriptRuntime, scope) {
|
||||
stateListener(listener) {
|
||||
return a11yBridge.setAccessibilityListener(listener);
|
||||
},
|
||||
registerEvents(name, listener) {
|
||||
return rtAutomator.registerEvents(name, listener);
|
||||
},
|
||||
removeEvents(name) {
|
||||
return rtAutomator.removeEvents(name);
|
||||
},
|
||||
waitFor(timeout) {
|
||||
automator.waitForService(timeout);
|
||||
},
|
||||
|
||||
@@ -9,16 +9,17 @@ import android.view.accessibility.AccessibilityEvent.TYPE_VIEW_FOCUSED
|
||||
import android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
|
||||
import android.view.accessibility.AccessibilityNodeInfo
|
||||
import org.autojs.autojs.AutoJs
|
||||
import org.autojs.autojs.core.automator.AccessibilityEventWrapper
|
||||
import org.autojs.autojs.event.EventDispatcher
|
||||
import org.autojs.autojs.pref.Pref
|
||||
import java.util.TreeMap
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
interface AccessibilityServiceCallback {
|
||||
fun onServiceConnected()
|
||||
fun onServiceDisconnected()
|
||||
fun onConnected()
|
||||
fun onDisconnected()
|
||||
}
|
||||
/**
|
||||
* Created by Stardust on 2017/5/2.
|
||||
@@ -28,16 +29,38 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ
|
||||
val keyInterrupterObserver = KeyInterceptor.Observer()
|
||||
var fastRootInActiveWindow: AccessibilityNodeInfo? = null
|
||||
var bridge: AccessibilityBridge? = null
|
||||
private val eventBox = TreeMap<Int, AccessibilityEventCallback>()
|
||||
|
||||
private val gestureEventDispatcher = EventDispatcher<GestureListener>()
|
||||
|
||||
private val eventExecutor by lazy { Executors.newSingleThreadExecutor() }
|
||||
|
||||
private fun eventNameToType(str: String): Int {
|
||||
return try {
|
||||
val sb = StringBuilder()
|
||||
sb.append("TYPE_")
|
||||
val upperCase = str.uppercase(Locale.getDefault())
|
||||
sb.append(upperCase)
|
||||
AccessibilityEvent::class.java.getField(sb.toString()).get(null) as Int
|
||||
} catch (unused: NoSuchFieldException) {
|
||||
throw IllegalArgumentException("unknown event type: $str")
|
||||
}
|
||||
}
|
||||
|
||||
fun addAccessibilityEventCallback(name: String, callback: AccessibilityEventCallback) {
|
||||
eventBox[eventNameToType(name)] = callback
|
||||
}
|
||||
|
||||
fun removeAccessibilityEventCallback(name: String) {
|
||||
eventBox.remove(eventNameToType(name))
|
||||
}
|
||||
|
||||
override fun onAccessibilityEvent(event: AccessibilityEvent) {
|
||||
if (instance != this) {
|
||||
instance = this
|
||||
}
|
||||
val type = event.eventType
|
||||
eventBox[type]?.onAccessibilityEvent(AccessibilityEventWrapper(event))
|
||||
if (containsAllEventTypes || eventTypes.contains(type)) {
|
||||
if (type == TYPE_WINDOW_STATE_CHANGED || type == TYPE_VIEW_FOCUSED) {
|
||||
rootInActiveWindow?.also { fastRootInActiveWindow = it }
|
||||
@@ -90,7 +113,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ
|
||||
instance = null
|
||||
bridge = null
|
||||
eventExecutor.shutdownNow()
|
||||
callback?.onServiceDisconnected()
|
||||
callback?.onDisconnected()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
@@ -107,7 +130,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ
|
||||
}
|
||||
}
|
||||
}
|
||||
callback?.onServiceConnected()
|
||||
callback?.onConnected()
|
||||
super.onServiceConnected()
|
||||
|
||||
LOCK.lock()
|
||||
@@ -147,6 +170,7 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ
|
||||
fun isNotRunning() = !isRunning()
|
||||
|
||||
fun addDelegate(uniquePriority: Int, delegate: AccessibilityDelegate) {
|
||||
//用于记录eventTypes中的事件id
|
||||
delegates[uniquePriority] = delegate
|
||||
val set = delegate.eventTypes
|
||||
if (set == null) {
|
||||
@@ -184,7 +208,9 @@ open class AccessibilityService : android.accessibilityservice.AccessibilityServ
|
||||
LOCK.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
fun clearAccessibilityEventCallback() {
|
||||
instance?.eventBox?.clear()
|
||||
}
|
||||
fun setCallback(listener: AccessibilityServiceCallback) {
|
||||
callback = listener
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import androidx.annotation.RequiresApi
|
||||
import androidx.core.view.accessibility.AccessibilityNodeInfoCompat
|
||||
import org.autojs.autojs.annotation.ScriptInterface
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityService.Companion.isRunning
|
||||
import org.autojs.autojs.core.automator.AccessibilityEventWrapper
|
||||
import org.autojs.autojs.core.automator.GlobalActionAutomator
|
||||
import org.autojs.autojs.core.automator.UiObject
|
||||
import org.autojs.autojs.core.automator.action.ActionFactory
|
||||
@@ -27,7 +28,11 @@ import org.autojs.autojs.runtime.accessibility.AccessibilityConfig
|
||||
import org.autojs.autojs.runtime.api.ScreenMetrics
|
||||
import org.autojs.autojs.runtime.api.ScriptPromiseAdapter
|
||||
import org.autojs.autojs.util.DeveloperUtils
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
interface AccessibilityEventCallback {
|
||||
fun onAccessibilityEvent(event: AccessibilityEventWrapper)
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by Stardust on 2017/4/2.
|
||||
@@ -182,6 +187,18 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge
|
||||
@ScriptInterface
|
||||
fun ensureService() = accessibilityBridge.ensureServiceEnabled()
|
||||
|
||||
//todo:优化实现方式
|
||||
fun registerEvents(eventName: String,callback: AccessibilityEventCallback) {
|
||||
ensureService()
|
||||
val service = org.autojs.autojs.core.accessibility.AccessibilityService.instance
|
||||
service?.addAccessibilityEventCallback(eventName,callback)
|
||||
}
|
||||
|
||||
fun removeEvents(eventName: String) {
|
||||
val service = org.autojs.autojs.core.accessibility.AccessibilityService.instance
|
||||
service?.removeAccessibilityEventCallback(eventName)
|
||||
}
|
||||
|
||||
private fun performAction(simpleAction: SimpleAction): Boolean {
|
||||
ensureService()
|
||||
if (AccessibilityConfig.isUnintendedGuardEnabled() && isRunningPackageSelf) {
|
||||
@@ -239,7 +256,7 @@ class SimpleActionAutomator(private val accessibilityBridge: AccessibilityBridge
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
val accessibilityDelegateCounter = AtomicInteger(1000)
|
||||
val TAG: String = SimpleActionAutomator::class.java.name
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.autojs.autojs.core.automator
|
||||
|
||||
import android.view.accessibility.AccessibilityEvent
|
||||
|
||||
class AccessibilityEventWrapper(event: AccessibilityEvent) {
|
||||
private val node = event.source
|
||||
|
||||
val source = if (node != null) UiObject(node, null, getDepth(), getIndexInParent()) else null
|
||||
|
||||
private fun getDepth(): Int {
|
||||
var depth = 0
|
||||
if (node == null) return 0
|
||||
while (node.parent != null) {
|
||||
depth++
|
||||
}
|
||||
return depth
|
||||
}
|
||||
|
||||
private fun getIndexInParent(): Int {
|
||||
val parent = node!!.parent
|
||||
var index = 0
|
||||
while (parent.getChild(index) != node) {
|
||||
index++
|
||||
}
|
||||
return index
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import org.autojs.autojs.AutoJs;
|
||||
import org.autojs.autojs.annotation.ScriptVariable;
|
||||
import org.autojs.autojs.concurrent.VolatileDispose;
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityBridge;
|
||||
import org.autojs.autojs.core.accessibility.AccessibilityService;
|
||||
import org.autojs.autojs.core.accessibility.SimpleActionAutomator;
|
||||
import org.autojs.autojs.core.accessibility.UiSelector;
|
||||
import org.autojs.autojs.core.activity.ActivityInfoProvider;
|
||||
@@ -527,7 +528,8 @@ public class ScriptRuntime {
|
||||
console.hideDelayed();
|
||||
}
|
||||
});
|
||||
|
||||
//清空无障碍事件
|
||||
ignoresException(AccessibilityService.Companion::clearAccessibilityEventCallback);
|
||||
ignoresException(RootUtils::resetRuntimeOverriddenRootModeState);
|
||||
ignoresException(ImageWrapper::recycleAll);
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Mon Jul 10 09:35:09 CST 2023
|
||||
BUILD_TIME=1688952909391
|
||||
#Mon Jul 10 18:23:10 CST 2023
|
||||
BUILD_TIME=1688984590330
|
||||
COMPILE_SDK_VERSION=33
|
||||
JAVA_VERSION=20
|
||||
MIN_SDK_VERSION=24
|
||||
TARGET_SDK_VERSION=33
|
||||
VERSION_BUILD=2000
|
||||
VERSION_BUILD=2006
|
||||
VERSION_NAME=6.3.2
|
||||
|
||||
Reference in New Issue
Block a user