From 0d88a12cbad93e6b0a40439eb15db08696337168 Mon Sep 17 00:00:00 2001 From: hyb1996 <946994919@qq.com> Date: Wed, 23 Jan 2019 22:08:55 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20=E6=8E=A7=E4=BB=B6?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=93=8D=E4=BD=9C=E6=8A=A5=E9=94=99=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/caches/build_file_checksums.ser | Bin 733 -> 733 bytes .../autojs/autojs/api/timing/TimedTasks.kt | 23 ++ .../accessibility/SimpleActionAutomator.java | 281 ------------------ .../accessibility/SimpleActionAutomator.kt | 261 ++++++++++++++++ .../autojs/core/accessibility/UiSelector.java | 3 + .../automator/GlobalActionAutomator.kt | 37 +-- 6 files changed, 303 insertions(+), 302 deletions(-) create mode 100644 app/src/main/java/org/autojs/autojs/autojs/api/timing/TimedTasks.kt delete mode 100644 autojs/src/main/java/com/stardust/autojs/core/accessibility/SimpleActionAutomator.java create mode 100644 autojs/src/main/java/com/stardust/autojs/core/accessibility/SimpleActionAutomator.kt diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 829c685001c47f1a45b273e8d24a3eb7f1548181..f1f23d22f499af13a58c8382b55857e38dff728d 100644 GIT binary patch delta 245 zcmcc1dY5&=bk>Y2i{+Om&M6mItyr+)vc9=`Ez5-d%M-TfOjc&}5m=X(cct-T&(~#5 z?4A12>)%bTXS5KQkb6y`rufr*ajkTLAR(^rlaDhhr(HQbyGNGskEZydH=3_H9%hv= z@FbOH=A`JQ7bT|Tq?Q&k)G@FzFfa%-zq>!-`=9uvwYA@M>fSSIlrRY7TQ=oJ*@ z7o--IWTqA)6dwq0VuFUZmj!3Mp(zKEoOcjvKO=={$&A#FxcjPs12&zLBLPehoY#xsozsqE zvmOER;f^yjlYap?5Zz+AF3MA>=G%<&CXEwfxRb{LBW7PsDC@EW-wXZ_JisgJHA{2= z3}SU@Y-BEHa$#g_Wp!}?egFml000n>r0HfPW`7O69hb<%_JSC601#|%V_|GAaB^>O zWpZ?BWpj0L0Db@l0000G(?GG}j>(=SBE90{q%m=$lTZR45Sgt$g>#Mh6qiNCaU(*v v43mBWAP~TK7#2h@(mU!C#X8Bx$HcDy71Z8F=O+1kW* roots = mAccessibilityBridge.windowRoots(); - if (roots.isEmpty()) - return false; - Log.v(TAG, "performAction: " + simpleAction + " windowRoots = " + roots); - boolean succeed = true; - for (AccessibilityNodeInfo root : roots) { - succeed &= simpleAction.perform(UiObject.Companion.createRoot(root)); - } - return succeed; - } - - private boolean isRunningPackageSelf() { - return DeveloperUtils.isSelfPackage(mAccessibilityBridge.getInfoProvider().getLatestPackage()); - } - - public void setScreenMetrics(ScreenMetrics metrics) { - mScreenMetrics = metrics; - if (mGlobalActionAutomator != null) - mGlobalActionAutomator.setScreenMetrics(metrics); - } - -} diff --git a/autojs/src/main/java/com/stardust/autojs/core/accessibility/SimpleActionAutomator.kt b/autojs/src/main/java/com/stardust/autojs/core/accessibility/SimpleActionAutomator.kt new file mode 100644 index 00000000..4912bfda --- /dev/null +++ b/autojs/src/main/java/com/stardust/autojs/core/accessibility/SimpleActionAutomator.kt @@ -0,0 +1,261 @@ +package com.stardust.autojs.core.accessibility + +import android.accessibilityservice.AccessibilityService +import android.accessibilityservice.GestureDescription +import android.graphics.Rect +import android.os.Build +import android.os.Handler +import android.view.accessibility.AccessibilityNodeInfo +import androidx.annotation.RequiresApi +import com.stardust.autojs.annotation.ScriptInterface +import com.stardust.autojs.runtime.ScriptRuntime +import com.stardust.autojs.runtime.accessibility.AccessibilityConfig +import com.stardust.automator.GlobalActionAutomator +import com.stardust.automator.UiObject +import com.stardust.automator.simple_action.ActionFactory +import com.stardust.automator.simple_action.ActionTarget +import com.stardust.automator.simple_action.SimpleAction +import com.stardust.util.DeveloperUtils +import com.stardust.util.ScreenMetrics + +/** + * Created by Stardust on 2017/4/2. + */ + +class SimpleActionAutomator(private val mAccessibilityBridge: AccessibilityBridge, private val mScriptRuntime: ScriptRuntime) { + + private lateinit var mGlobalActionAutomator: GlobalActionAutomator + + private var mScreenMetrics: ScreenMetrics? = null + + private val isRunningPackageSelf: Boolean + get() = DeveloperUtils.isSelfPackage(mAccessibilityBridge.infoProvider.latestPackage) + + @ScriptInterface + fun text(text: String, i: Int): ActionTarget { + return ActionTarget.TextActionTarget(text, i) + } + + @ScriptInterface + fun bounds(left: Int, top: Int, right: Int, bottom: Int): ActionTarget { + return ActionTarget.BoundsActionTarget(Rect(left, top, right, bottom)) + } + + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @ScriptInterface + fun editable(i: Int): ActionTarget { + ScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP) + return ActionTarget.EditableActionTarget(i) + } + + @ScriptInterface + fun id(id: String): ActionTarget { + return ActionTarget.IdActionTarget(id) + } + + @ScriptInterface + fun click(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_CLICK)) + } + + @ScriptInterface + fun longClick(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_LONG_CLICK)) + } + + @ScriptInterface + fun scrollUp(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD)) + } + + @ScriptInterface + fun scrollDown(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) + } + + @ScriptInterface + fun scrollBackward(i: Int): Boolean { + return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD, i)) + } + + @ScriptInterface + fun scrollForward(i: Int): Boolean { + return performAction(ActionFactory.createScrollAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD, i)) + } + + @ScriptInterface + fun scrollMaxBackward(): Boolean { + return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD)) + } + + @ScriptInterface + fun scrollMaxForward(): Boolean { + return performAction(ActionFactory.createScrollMaxAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) + } + + @ScriptInterface + fun focus(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_FOCUS)) + } + + @ScriptInterface + fun select(target: ActionTarget): Boolean { + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SELECT)) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + fun setText(target: ActionTarget, text: String): Boolean { + ScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP) + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_SET_TEXT, text)) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + fun appendText(target: ActionTarget, text: String): Boolean { + ScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP) + return performAction(target.createAction(UiObject.ACTION_APPEND_TEXT, text)) + } + + @ScriptInterface + fun back(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK) + } + + @ScriptInterface + fun home(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_HOME) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + fun powerDialog(): Boolean { + ScriptRuntime.requiresApi(Build.VERSION_CODES.LOLLIPOP) + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG) + } + + @ScriptInterface + fun notifications(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_NOTIFICATIONS) + } + + @ScriptInterface + fun quickSettings(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_QUICK_SETTINGS) + } + + @ScriptInterface + fun recents(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_RECENTS) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun splitScreen(): Boolean { + return performGlobalAction(AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun gesture(start: Long, duration: Long, vararg points: IntArray): Boolean { + prepareForGesture() + return mGlobalActionAutomator.gesture(start, duration, *points) + } + + @RequiresApi(api = Build.VERSION_CODES.N) + fun gestureAsync(start: Long, duration: Long, vararg points: IntArray) { + prepareForGesture() + mGlobalActionAutomator.gestureAsync(start, duration, *points) + } + + @RequiresApi(api = Build.VERSION_CODES.N) + fun gestures(strokes: Any): Boolean { + prepareForGesture() + @Suppress("UNCHECKED_CAST") + return mGlobalActionAutomator.gestures(*strokes as Array) + } + + //如果这里用GestureDescription.StrokeDescription[]为参数,安卓7.0以下会因为找不到这个类而报错 + @RequiresApi(api = Build.VERSION_CODES.N) + fun gesturesAsync(strokes: Any) { + prepareForGesture() + @Suppress("UNCHECKED_CAST") + mGlobalActionAutomator.gesturesAsync(*strokes as Array) + } + + private fun prepareForGesture() { + ScriptRuntime.requiresApi(24) + if (!::mGlobalActionAutomator.isInitialized) { + mGlobalActionAutomator = GlobalActionAutomator(Handler(mScriptRuntime.loopers.servantLooper)) { + ensureAccessibilityServiceEnabled() + return@GlobalActionAutomator mAccessibilityBridge.service!! + } + } + mGlobalActionAutomator.setScreenMetrics(mScreenMetrics) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun click(x: Int, y: Int): Boolean { + prepareForGesture() + return mGlobalActionAutomator.click(x, y) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun press(x: Int, y: Int, delay: Int): Boolean { + prepareForGesture() + return mGlobalActionAutomator.press(x, y, delay) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun longClick(x: Int, y: Int): Boolean { + prepareForGesture() + return mGlobalActionAutomator.longClick(x, y) + } + + @ScriptInterface + @RequiresApi(api = Build.VERSION_CODES.N) + fun swipe(x1: Int, y1: Int, x2: Int, y2: Int, delay: Int): Boolean { + prepareForGesture() + return mGlobalActionAutomator.swipe(x1, y1, x2, y2, delay.toLong()) + } + + private fun performGlobalAction(action: Int): Boolean { + ensureAccessibilityServiceEnabled() + val service = mAccessibilityBridge.service ?: return false + return service.performGlobalAction(action) + } + + @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2) + @ScriptInterface + fun paste(target: ActionTarget): Boolean { + ScriptRuntime.requiresApi(18) + return performAction(target.createAction(AccessibilityNodeInfo.ACTION_PASTE)) + } + + private fun ensureAccessibilityServiceEnabled() { + mAccessibilityBridge.ensureServiceEnabled() + } + + private fun performAction(simpleAction: SimpleAction): Boolean { + ensureAccessibilityServiceEnabled() + if (AccessibilityConfig.isUnintendedGuardEnabled() && isRunningPackageSelf) { + return false + } + val roots = mAccessibilityBridge.windowRoots().filter { it != null } + if (roots.isEmpty()) + return false + var succeed = true + for (root in roots) { + succeed = succeed and simpleAction.perform(UiObject.createRoot(root)) + } + return succeed + } + + fun setScreenMetrics(metrics: ScreenMetrics) { + mScreenMetrics = metrics + } + +} diff --git a/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiSelector.java b/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiSelector.java index b6785efb..c9d8701b 100644 --- a/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiSelector.java +++ b/autojs/src/main/java/com/stardust/autojs/core/accessibility/UiSelector.java @@ -105,6 +105,9 @@ public class UiSelector extends UiGlobalSelector { } List result = new ArrayList<>(); for (AccessibilityNodeInfo root : roots) { + if (root == null) { + continue; + } if (root.getPackageName() != null && mAccessibilityBridge.getConfig().whiteListContains(root.getPackageName().toString())) { Log.d(TAG, "package in white list, return null"); return UiObjectCollection.Companion.getEMPTY(); diff --git a/automator/src/main/java/com/stardust/automator/GlobalActionAutomator.kt b/automator/src/main/java/com/stardust/automator/GlobalActionAutomator.kt index 79685976..0d6fa416 100644 --- a/automator/src/main/java/com/stardust/automator/GlobalActionAutomator.kt +++ b/automator/src/main/java/com/stardust/automator/GlobalActionAutomator.kt @@ -17,16 +17,14 @@ import com.stardust.util.ScreenMetrics * Created by Stardust on 2017/5/16. */ -class GlobalActionAutomator(private val mHandler: Handler?) { +class GlobalActionAutomator(private val mHandler: Handler?, private val serviceProvider: () -> AccessibilityService) { + + private val service: AccessibilityService + get() = serviceProvider() - private var mService: AccessibilityService? = null private var mScreenMetrics: ScreenMetrics? = null - fun setService(service: AccessibilityService) { - mService = service - } - - fun setScreenMetrics(screenMetrics: ScreenMetrics) { + fun setScreenMetrics(screenMetrics: ScreenMetrics?) { mScreenMetrics = screenMetrics } @@ -44,7 +42,7 @@ class GlobalActionAutomator(private val mHandler: Handler?) { } private fun performGlobalAction(globalAction: Int): Boolean { - return if (mService == null) false else mService!!.performGlobalAction(globalAction) + return service.performGlobalAction(globalAction) } fun notifications(): Boolean { @@ -88,23 +86,22 @@ class GlobalActionAutomator(private val mHandler: Handler?) { @RequiresApi(api = Build.VERSION_CODES.N) fun gestures(vararg strokes: GestureDescription.StrokeDescription): Boolean { - if (mService == null) - return false val builder = GestureDescription.Builder() for (stroke in strokes) { builder.addStroke(stroke) } - return if (mHandler == null) { + val handler = mHandler + return if (handler == null) { gesturesWithoutHandler(builder.build()) } else { - gesturesWithHandler(builder.build()) + gesturesWithHandler(handler, builder.build()) } } @RequiresApi(api = Build.VERSION_CODES.N) - private fun gesturesWithHandler(description: GestureDescription): Boolean { + private fun gesturesWithHandler(handler: Handler, description: GestureDescription): Boolean { val result = VolatileDispose() - mService!!.dispatchGesture(description, object : AccessibilityService.GestureResultCallback() { + service.dispatchGesture(description, object : AccessibilityService.GestureResultCallback() { override fun onCompleted(gestureDescription: GestureDescription) { result.setAndNotify(true) } @@ -112,7 +109,7 @@ class GlobalActionAutomator(private val mHandler: Handler?) { override fun onCancelled(gestureDescription: GestureDescription) { result.setAndNotify(false) } - }, mHandler) + }, handler) return result.blockedGet() } @@ -121,7 +118,7 @@ class GlobalActionAutomator(private val mHandler: Handler?) { prepareLooperIfNeeded() val result = VolatileBox(false) val handler = Handler(Looper.myLooper()) - mService!!.dispatchGesture(description, object : AccessibilityService.GestureResultCallback() { + service.dispatchGesture(description, object : AccessibilityService.GestureResultCallback() { override fun onCompleted(gestureDescription: GestureDescription) { result.set(true) quitLoop() @@ -138,13 +135,11 @@ class GlobalActionAutomator(private val mHandler: Handler?) { @RequiresApi(api = Build.VERSION_CODES.N) fun gesturesAsync(vararg strokes: GestureDescription.StrokeDescription) { - if (mService == null) - return val builder = GestureDescription.Builder() for (stroke in strokes) { builder.addStroke(stroke) } - mService!!.dispatchGesture(builder.build(), null, null) + service.dispatchGesture(builder.build(), null, null) } private fun quitLoop() { @@ -174,11 +169,11 @@ class GlobalActionAutomator(private val mHandler: Handler?) { } private fun scaleX(x: Int): Int { - return if (mScreenMetrics == null) x else mScreenMetrics!!.scaleX(x) + return mScreenMetrics?.scaleX(x) ?: x } private fun scaleY(y: Int): Int { - return if (mScreenMetrics == null) y else mScreenMetrics!!.scaleY(y) + return mScreenMetrics?.scaleX(y) ?: y } @RequiresApi(api = Build.VERSION_CODES.N)