Skip to content

Commit a860027

Browse files
committed
新增:
- 手势长按方法longPressByGesture - 长按并自动粘贴方法(适合无法通过api直接输入内容的输入框)longPressGestureAutoPaste - web端同步支持长按并自动粘贴longPressGestureAutoPaste 修复: - 示例点击逻辑错误问题
1 parent d8d6395 commit a860027

File tree

6 files changed

+173
-31
lines changed

6 files changed

+173
-31
lines changed

assists-web/src/main/java/com/ven/assists/web/ASJavascriptInterface.kt

Lines changed: 57 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.ven.assists.AssistsCore.getBoundsInScreen
3030
import com.ven.assists.AssistsCore.getChildren
3131
import com.ven.assists.AssistsCore.getNodes
3232
import com.ven.assists.AssistsCore.longClick
33+
import com.ven.assists.AssistsCore.longPressGestureAutoPaste
3334
import com.ven.assists.AssistsCore.nodeGestureClick
3435
import com.ven.assists.AssistsCore.paste
3536
import com.ven.assists.AssistsCore.scrollBackward
@@ -86,6 +87,50 @@ class ASJavascriptInterface(val webView: WebView) {
8687
runCatching {
8788
val request = GsonUtils.fromJson<CallRequest<JsonObject>>(requestJson, object : TypeToken<CallRequest<JsonObject>>() {}.type)
8889
when (request.method) {
90+
CallMethod.longPressGestureAutoPaste -> {
91+
CoroutineWrapper.launch {
92+
val matchedPackageName = request.arguments?.get("matchedPackageName")?.asString
93+
val text = request.arguments?.get("text")?.asString ?: ""
94+
val matchedText = request.arguments?.get("matchedText")?.asString ?: "粘贴"
95+
val timeoutMillis = request.arguments?.get("timeoutMillis")?.asLong ?: 1500
96+
val longPressDuration = request.arguments?.get("longPressDuration")?.asLong ?: 600
97+
val point = request.arguments?.get("point")?.asJsonObject ?: JsonObject()
98+
99+
val switchWindowIntervalDelay = request.arguments?.get("switchWindowIntervalDelay")?.asLong ?: 250
100+
AssistsWindowManager.nonTouchableByAll()
101+
delay(switchWindowIntervalDelay)
102+
103+
val x = point.get("x")?.asFloat ?: 0f
104+
val y = point.get("y")?.asFloat ?: 0f
105+
var result = false
106+
if (request.node?.nodeId.isNullOrEmpty()) {
107+
result = AssistsCore.longPressGestureAutoPaste(
108+
x = x,
109+
y = y,
110+
text = text,
111+
matchedPackageName = matchedPackageName,
112+
matchedText = matchedText,
113+
timeoutMillis = timeoutMillis,
114+
longPressDuration = longPressDuration
115+
)
116+
} else {
117+
result = NodeCacheManager.get(request?.node?.nodeId ?: "")?.longPressGestureAutoPaste(
118+
text = text,
119+
matchedPackageName = matchedPackageName,
120+
matchedText = matchedText,
121+
timeoutMillis = timeoutMillis,
122+
longPressDuration = longPressDuration
123+
) ?: false
124+
}
125+
AssistsWindowManager.touchableByAll()
126+
callback(CallResponse(code = if (result) 0 else 1, data = result, callbackId = request.callbackId))
127+
128+
}
129+
result = GsonUtils.toJson(CallResponse<JsonObject>(code = 0, data = JsonObject().apply {
130+
addProperty("resultType", "callback")
131+
}))
132+
}
133+
89134
CallMethod.getAppInfo -> {
90135
val packageName = request.arguments?.get("packageName")?.asString ?: ""
91136
CoroutineWrapper.launch {
@@ -96,7 +141,9 @@ class ASJavascriptInterface(val webView: WebView) {
96141
callback(CallResponse(code = 0, data = JsonObject(), callbackId = request.callbackId))
97142
}
98143
}
99-
144+
result = GsonUtils.toJson(CallResponse<JsonObject>(code = 0, data = JsonObject().apply {
145+
addProperty("resultType", "callback")
146+
}))
100147
}
101148

102149
CallMethod.loadWebViewOverlay -> {
@@ -222,17 +269,15 @@ class ASJavascriptInterface(val webView: WebView) {
222269
path.moveTo(startPoint.get("x").asFloat, startPoint.get("y").asFloat)
223270
path.lineTo(endPoint.get("x").asFloat, endPoint.get("y").asFloat)
224271
val switchWindowIntervalDelay = request.arguments?.get("switchWindowIntervalDelay")?.asLong ?: 250
225-
CoroutineWrapper.launch {
226-
AssistsWindowManager.nonTouchableByAll()
227-
delay(switchWindowIntervalDelay)
228-
val result =
229-
AssistsCore.gesture(path = path, startTime = 0, duration = request.arguments?.get("duration")?.asLong ?: 1000)
230-
AssistsWindowManager.touchableByAll()
231-
if (result) {
232-
callback(CallResponse<Boolean>(code = 0, data = true, callbackId = request.callbackId))
233-
} else {
234-
callback(CallResponse<Boolean>(code = -1, data = false, callbackId = request.callbackId))
235-
}
272+
AssistsWindowManager.nonTouchableByAll()
273+
delay(switchWindowIntervalDelay)
274+
val result =
275+
AssistsCore.gesture(path = path, startTime = 0, duration = request.arguments?.get("duration")?.asLong ?: 1000)
276+
AssistsWindowManager.touchableByAll()
277+
if (result) {
278+
callback(CallResponse<Boolean>(code = 0, data = true, callbackId = request.callbackId))
279+
} else {
280+
callback(CallResponse<Boolean>(code = -1, data = false, callbackId = request.callbackId))
236281
}
237282
}
238283
result = GsonUtils.toJson(CallResponse<JsonObject>(code = 0, data = JsonObject().apply {

assists-web/src/main/java/com/ven/assists/web/CallMethod.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ object CallMethod {
4242
const val clickNodeByGesture = "clickNodeByGesture"
4343
const val doubleClickNodeByGesture = "doubleClickNodeByGesture"
4444
const val performLinearGesture = "performLinearGesture"
45+
const val longPressGestureAutoPaste = "longPressGestureAutoPaste"
4546

4647
const val getAppInfo = "getAppInfo"
4748
}

assists/src/main/java/com/ven/assists/AssistsCore.kt

Lines changed: 104 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import android.text.TextUtils
1919
import android.util.Log
2020
import android.view.Display
2121
import android.view.View
22+
import android.view.accessibility.AccessibilityEvent
2223
import android.view.accessibility.AccessibilityNodeInfo
2324
import androidx.annotation.RequiresApi
2425
import androidx.core.os.bundleOf
@@ -28,11 +29,13 @@ import com.blankj.utilcode.util.LogUtils
2829
import com.blankj.utilcode.util.PathUtils
2930
import com.blankj.utilcode.util.ScreenUtils
3031
import com.ven.assists.service.AssistsService
32+
import com.ven.assists.service.AssistsServiceListener
3133
import com.ven.assists.utils.CoroutineWrapper
3234
import com.ven.assists.utils.NodeClassValue
3335
import com.ven.assists.utils.runMain
3436
import com.ven.assists.window.AssistsWindowManager
3537
import kotlinx.coroutines.CompletableDeferred
38+
import kotlinx.coroutines.Job
3639
import kotlinx.coroutines.delay
3740
import java.io.File
3841
import java.util.concurrent.Executors
@@ -385,7 +388,7 @@ object AssistsCore {
385388
}
386389
}
387390
nodeList = viewId?.let {
388-
if (it.isEmpty())return@let nodeList
391+
if (it.isEmpty()) return@let nodeList
389392
return@let arrayListOf<AccessibilityNodeInfo>().apply {
390393
addAll(nodeList.filter {
391394
return@filter it.viewIdResourceName == viewId
@@ -396,15 +399,15 @@ object AssistsCore {
396399
}
397400

398401
nodeList = text?.let {
399-
if (it.isEmpty())return@let nodeList
402+
if (it.isEmpty()) return@let nodeList
400403
return@let arrayListOf<AccessibilityNodeInfo>().apply {
401404
addAll(nodeList.filter {
402405
return@filter it.txt() == text
403406
})
404407
}
405408
} ?: let { return@let nodeList }
406409
nodeList = des?.let {
407-
if (it.isEmpty())return@let nodeList
410+
if (it.isEmpty()) return@let nodeList
408411
return@let arrayListOf<AccessibilityNodeInfo>().apply {
409412
addAll(nodeList.filter {
410413
return@filter it.des() == des
@@ -671,6 +674,21 @@ object AssistsCore {
671674
)
672675
}
673676

677+
/**
678+
* 通过手势长按
679+
*/
680+
suspend fun longPressByGesture(
681+
x: Float,
682+
y: Float,
683+
duration: Long = 600
684+
): Boolean {
685+
return gesture(
686+
floatArrayOf(x, y), floatArrayOf(x, y),
687+
0,
688+
duration,
689+
)
690+
}
691+
674692
/**
675693
* 在元素位置执行点击手势
676694
* @param offsetX X轴偏移量
@@ -821,6 +839,89 @@ object AssistsCore {
821839
return false
822840
}
823841

842+
/**
843+
* 长按当前节点并自动粘贴
844+
* ⚠️当前仅对小米10,澎湃OS 1.0.5.0进行测试,其他机型系统版本请自行测试
845+
*/
846+
suspend fun AccessibilityNodeInfo.longPressGestureAutoPaste(
847+
text: String,
848+
matchedText: String = "粘贴",
849+
matchedPackageName: String? = null,
850+
timeoutMillis: Long = 1500,
851+
longPressDuration: Long = 600,
852+
): Boolean {
853+
854+
val rect = getBoundsInScreen()
855+
856+
return this@AssistsCore.longPressGestureAutoPaste(
857+
x = rect.left.toFloat() + rect.width() / 2,
858+
y = rect.top.toFloat() + rect.height() / 2,
859+
text = text,
860+
matchedText = matchedText,
861+
matchedPackageName = matchedPackageName,
862+
timeoutMillis = timeoutMillis,
863+
longPressDuration = longPressDuration,
864+
)
865+
}
866+
867+
/**
868+
* 长按并自动粘贴
869+
* ⚠️当前仅对小米10,澎湃OS 1.0.5.0进行测试,其他机型系统版本请自行测试
870+
*/
871+
suspend fun longPressGestureAutoPaste(
872+
x: Float,
873+
y: Float,
874+
text: String,
875+
matchedText: String = "粘贴",
876+
matchedPackageName: String? = null,
877+
timeoutMillis: Long = 1500,
878+
longPressDuration: Long = 600,
879+
): Boolean {
880+
881+
val completableDeferred = CompletableDeferred<Boolean>()
882+
883+
val serviceListener = object : AssistsServiceListener {
884+
override fun onAccessibilityEvent(event: AccessibilityEvent) {
885+
runCatching {
886+
if (event.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED &&
887+
event.text.contains(matchedText) &&
888+
(matchedPackageName == null || event.packageName.toString() == matchedPackageName)
889+
) {
890+
val source = event.source
891+
source?.getNodes()?.forEach { node ->
892+
if (node.isClickable && node.containsText(matchedText)) {
893+
val result = node.click()
894+
completableDeferred.complete(result)
895+
return@runCatching result
896+
}
897+
}
898+
}
899+
return@runCatching false
900+
}
901+
}
902+
}
903+
AssistsService.listeners.add(serviceListener)
904+
val timeoutJob = CoroutineWrapper.launch {
905+
delay(timeoutMillis)
906+
completableDeferred.complete(false)
907+
}
908+
AssistsService.instance?.let {
909+
val clipboard = it.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
910+
val clip = ClipData.newPlainText("label", text)
911+
clipboard.setPrimaryClip(clip)
912+
}
913+
CoroutineWrapper.launch {
914+
val result = longPressByGesture(x, y, duration = longPressDuration)
915+
if (!result) {
916+
completableDeferred.complete(false)
917+
}
918+
}
919+
val result = completableDeferred.await()
920+
AssistsService.listeners.remove(serviceListener)
921+
timeoutJob.cancel()
922+
return result
923+
}
924+
824925
/**
825926
* 选择元素中的文本
826927
* @param selectionStart 选择起始位置

build.gradle

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ buildscript {
99
targetSdk = 33
1010

1111
// 应用版本
12-
versionCode = 11
13-
versionName = "3.2.172"
14-
mavenVersion = "3.2.172"
12+
versionCode = 12
13+
versionName = "3.2.173"
14+
mavenVersion = "3.2.173"
1515

1616
// 依赖库版本
1717
coreKtxVersion = "1.13.1"

simple/build.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ android {
1414

1515
ndk {
1616
//noinspection ChromeOsAbiSupport
17-
abiFilters "armeabi-v7a", "arm64-v8a"
17+
// abiFilters "armeabi-v7a", "arm64-v8a"
18+
abiFilters "arm64-v8a"
1819
}
1920
}
2021

simple/src/main/java/com/ven/assists/simple/overlays/OverlayBasic.kt

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import com.blankj.utilcode.util.TimeUtils
1616
import com.ven.assists.AssistsCore
1717
import com.ven.assists.AssistsCore.click
1818
import com.ven.assists.AssistsCore.longClick
19+
import com.ven.assists.AssistsCore.longPressGestureAutoPaste
1920
import com.ven.assists.AssistsCore.nodeGestureClick
2021
import com.ven.assists.AssistsCore.scrollBackward
2122
import com.ven.assists.AssistsCore.scrollForward
@@ -44,18 +45,11 @@ object OverlayBasic : AssistsServiceListener {
4445
//点击
4546
btnClick.setOnClickListener {
4647
CoroutineWrapper.launch {
47-
// AssistsService.instance?.startActivity(Intent(AssistsService.instance, TestActivity::class.java).apply {
48-
// flags = Intent.FLAG_ACTIVITY_NEW_TASK
49-
// })
50-
// delay(1000)
51-
// AssistsCore.findById("com.ven.assists.demo:id/btn_test").firstOrNull()?.click()
52-
53-
val file = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
54-
val bitmap = AssistsCore.takeScreenshot()
55-
LogUtils.d(bitmap)
56-
} else {
57-
TODO("VERSION.SDK_INT < R")
58-
}
48+
AssistsService.instance?.startActivity(Intent(AssistsService.instance, TestActivity::class.java).apply {
49+
flags = Intent.FLAG_ACTIVITY_NEW_TASK
50+
})
51+
delay(1000)
52+
AssistsCore.findById("com.ven.assists.demo:id/btn_test").firstOrNull()?.click()
5953
}
6054

6155
}

0 commit comments

Comments
 (0)