6.7.0 - Alpha2 - 修复 Android 10 UiObject#child 异常 (issue #416); 移除 UiObject#hashCode/equals 覆写; 新增 UiObject#isShifted 方法
This commit is contained in:
@@ -1,15 +1,17 @@
|
||||
{
|
||||
"$data": {
|
||||
"v6.7.0": {
|
||||
"released_date": "2025/06/15",
|
||||
"released_date": "2025/06/23",
|
||||
"feature": [
|
||||
"zip 模块, 用于文件压缩与解压缩操作 (Ref to [Auto.js Pro](https://g.pro.autojs.org/)) (参阅 项目文档 > [Zip](https://docs.autojs6.com/#/zip))",
|
||||
"mediainfo 模块, 用于查看媒体文件的详细信息 (参阅 项目文档 > [媒体信息](https://docs.autojs6.com/#/mediainfo))"
|
||||
"mediainfo 模块, 用于查看媒体文件的详细信息 (参阅 项目文档 > [媒体信息](https://docs.autojs6.com/#/mediainfo))",
|
||||
"UiObject#isShifted 方法, 用于检测控件位置变化"
|
||||
],
|
||||
"fix": [
|
||||
"使用 XML 语法将 JavaScript 表达式作为属性值时, this 对象可能出现指向错误的问题",
|
||||
"调用 images.requestScreenCapture 时用户取消授权可能导致应用崩溃的问题",
|
||||
"images 部分相关方法出现异常时 oneShot 标记功能失效的问题 _[`issue #372`](http://issues.autojs6.com/372)_",
|
||||
"Android 10 UiObject#child 方法可能出现 ArrayIndexOutOfBoundsException 异常的问题 _[`issue #416`](http://issues.autojs6.com/416)_",
|
||||
"打包应用无法正常使用 Paddle OCR 与 Rapid OCR 功能的问题",
|
||||
"版本历史页面部分系统因字体差别导致统计数据显示不完整的问题"
|
||||
],
|
||||
@@ -19,6 +21,7 @@
|
||||
"内置模块相关方法实参类型的异常消息增加类型摘要信息"
|
||||
],
|
||||
"dependency": [
|
||||
"附加 Androidx Core (KTX) 版本 1.16.0",
|
||||
"升级 Gradle 版本 8.14 -> 8.14.2",
|
||||
"升级 Apache Commons 版本 3.16.0 -> 3.17.0",
|
||||
"升级 Retrofit2 Retrofit 版本 2.11.0 -> 2.12.0",
|
||||
@@ -31,7 +34,8 @@
|
||||
"升级 Jsoup 版本 1.19.1 -> 1.20.1",
|
||||
"升级 Junit Jupiter 版本 5.10.3 -> 5.13.0",
|
||||
"升级 Androidx AppCompat 版本 1.7.0 -> 1.7.1",
|
||||
"升级 Material Progressbar 版本 1.4.2 -> 1.6.1"
|
||||
"升级 Material Progressbar 版本 1.4.2 -> 1.6.1",
|
||||
"升级 Androidx Room 版本 2.7.1 -> 2.7.2"
|
||||
]
|
||||
},
|
||||
"v6.6.4": {
|
||||
|
||||
@@ -27,6 +27,11 @@ val buildTypeRelease = "release"
|
||||
val buildActionAssemble = "assemble"
|
||||
val templateName = "template"
|
||||
|
||||
val taskNames = gradle.startParameter.taskNames
|
||||
val isAppAssembleTaskRequested = taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble", IGNORE_CASE)) }
|
||||
val isInrtAssembleTaskRequested = taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble$flavorNameInrt", IGNORE_CASE)) }
|
||||
val isInrtTaskRequested = taskNames.any { it.contains(flavorNameInrt, true) }
|
||||
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("com.google.devtools.ksp")
|
||||
@@ -40,6 +45,9 @@ dependencies /* Unclassified */ {
|
||||
// Kotlin reflect
|
||||
implementation(kotlin("reflect"))
|
||||
|
||||
// Androidx Core
|
||||
implementation("androidx.core:core-ktx:1.16.0")
|
||||
|
||||
// LeakCanary
|
||||
debugImplementation("com.squareup.leakcanary:leakcanary-android:2.14")
|
||||
|
||||
@@ -218,9 +226,9 @@ dependencies /* Unclassified */ {
|
||||
implementation(files("$rootDir/libs/tiny-sign-0.9.jar"))
|
||||
|
||||
// Room
|
||||
implementation("androidx.room:room-runtime:2.7.1")
|
||||
implementation("androidx.room:room-ktx:2.7.1")
|
||||
ksp("androidx.room:room-compiler:2.7.1")
|
||||
implementation("androidx.room:room-runtime:2.7.2")
|
||||
implementation("androidx.room:room-ktx:2.7.2")
|
||||
ksp("androidx.room:room-compiler:2.7.2")
|
||||
|
||||
// ApkSig
|
||||
// implementation("com.android.tools.build:apksig:8.7.3")
|
||||
@@ -549,10 +557,10 @@ android {
|
||||
}
|
||||
|
||||
androidResources {
|
||||
if (gradle.startParameter.taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble")) }) {
|
||||
if (isAppAssembleTaskRequested) {
|
||||
ignoreAssetsPatterns.addAll(listOf(".idea", "declarations", "sample/declarations"))
|
||||
}
|
||||
if (gradle.startParameter.taskNames.any { it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble$flavorNameInrt", IGNORE_CASE)) }) {
|
||||
if (isInrtAssembleTaskRequested) {
|
||||
// @Hint by SuperMonster003 on Oct 16, 2023.
|
||||
// ! Runtime assets will be copied from flavor "app"
|
||||
// ! while building an apk on org.autojs.autojs.ui.project.BuildActivity.
|
||||
@@ -635,7 +643,7 @@ android {
|
||||
"EmojiReference.txt",
|
||||
).let { resources.excludes.addAll(it) }
|
||||
|
||||
if (gradle.startParameter.taskNames.any { it.contains(flavorNameInrt, true) }) {
|
||||
if (isInrtTaskRequested) {
|
||||
listOf(
|
||||
"**/prob_emit.txt", // Jieba Analysis (zh-CN: 结巴分词)
|
||||
"**/dict-chinese-*.db.gzip", // Jieba Analysis (zh-CN: 结巴分词)
|
||||
@@ -742,9 +750,7 @@ android {
|
||||
// Configures multiple APKs based on ABI.
|
||||
abi {
|
||||
// Enables building multiple APKs per ABI.
|
||||
isEnable = /* isNotAssembleInrt */ gradle.startParameter.taskNames.none {
|
||||
it.contains(Regex("^(:?$flavorNameApp:)?$buildActionAssemble$flavorNameInrt", IGNORE_CASE))
|
||||
}
|
||||
isEnable = !isInrtAssembleTaskRequested
|
||||
// By default, all ABIs are included, so use reset() and include to specify that we only
|
||||
// want APKs for x86 and x86_64.
|
||||
// Resets the list of ABIs that Gradle should create APKs for to none.
|
||||
@@ -788,7 +794,7 @@ tasks {
|
||||
|
||||
rename { name ->
|
||||
Utils.digestCRC32(file("${src}/$name")).let { digest ->
|
||||
name.replace("^(.+?)(\\.$ext)\$".toRegex(), "\$1-$digest\$2")
|
||||
name.replace(Regex("^(.+?)(\\.$ext)$"), "$1-$digest$2")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,10 @@ import org.autojs.autojs.core.accessibility.AccessibilityNodeInfoHelper
|
||||
import org.autojs.autojs.core.accessibility.UiSelector
|
||||
import org.autojs.autojs.extension.AnyExtensions.isJsNullish
|
||||
import org.autojs.autojs.extension.AnyExtensions.isJsUndefined
|
||||
import org.autojs.autojs.extension.ArrayExtensions.toHashCode
|
||||
import org.autojs.autojs.extension.AnyExtensions.jsBrief
|
||||
import org.autojs.autojs.extension.ArrayExtensions.toNativeArray
|
||||
import org.autojs.autojs.runtime.ScriptRuntime
|
||||
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
|
||||
import org.autojs.autojs.util.DisplayUtils.toRoundIntX
|
||||
import org.autojs.autojs.util.DisplayUtils.toRoundIntY
|
||||
import org.autojs.autojs.util.RhinoUtils
|
||||
@@ -24,9 +25,9 @@ import org.autojs.autojs.util.StringUtils.str
|
||||
import org.autojs.autojs6.R
|
||||
import org.mozilla.javascript.BaseFunction
|
||||
import org.mozilla.javascript.Context
|
||||
import org.mozilla.javascript.Scriptable
|
||||
import org.opencv.core.Point
|
||||
import org.opencv.core.Size
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
@@ -56,32 +57,45 @@ open class UiObject(
|
||||
indexInParent: Int = -1,
|
||||
) : this(info, null, depth, indexInParent)
|
||||
|
||||
open fun parent(): UiObject? = try {
|
||||
open fun parent(): UiObject? = runCatching {
|
||||
super.getParent()?.let { node ->
|
||||
UiObject(node.unwrap(), depth - 1, node.parent?.run {
|
||||
// @Dubious by SuperMonster003 on May 26, 2022.
|
||||
// ! May lead to poor performance?
|
||||
// ! zh-CN: 可能导致性能不佳?
|
||||
(0 until childCount).firstOrNull { getChild(it) == node } ?: -1
|
||||
(0 until childCount).firstOrNull { child(it) == node } ?: -1
|
||||
} ?: 0)
|
||||
}
|
||||
} catch (e: IllegalStateException) {
|
||||
}.onFailure {
|
||||
// FIXME by Stardust on May 5, 2017.
|
||||
null.also { e.printStackTrace() }
|
||||
it.printStackTrace()
|
||||
}.getOrNull()
|
||||
|
||||
fun parent(i: Int): UiObject? {
|
||||
require(i >= 0) { "Index for UiObject#parent cannot be negative ($i)" }
|
||||
return compass("p$i")
|
||||
}
|
||||
|
||||
fun parent(i: Int): UiObject? = if (i < 0) throw Exception("i < 0") else compass("p$i")
|
||||
|
||||
open fun child(i: Int): UiObject? {
|
||||
if (i < 0) {
|
||||
return (i + childCount).takeIf { it >= 0 }?.let { child(it) }
|
||||
open fun child(i: Int): UiObject? = when {
|
||||
i >= childCount -> {
|
||||
null
|
||||
}
|
||||
return try {
|
||||
super.getChild(i)?.run { UiObject(unwrap(), depth + 1, i) }
|
||||
} catch (e: IllegalStateException) {
|
||||
i < 0 -> when (val targetIdx = i + childCount) {
|
||||
in 0 until childCount -> child(targetIdx)
|
||||
else -> null
|
||||
}
|
||||
else -> runCatching {
|
||||
// @Caution by SuperMonster003 on Jun 19, 2025.
|
||||
// ! `super.getChild` may cause ArrayIndexOutOfBoundsException when `i` is out of range of [0..childCound).
|
||||
// ! zh-CN: 当 `i` 超出 [0..childCount) 范围时可能导致 ArrayIndexOutOfBoundsException 异常.
|
||||
// @Dubious by SuperMonster003 on Jun 19, 2025.
|
||||
// ! It seems that the situation above only happens on API Level 29 (Android 10) [Q] ?
|
||||
// ! zh-CN: 似乎上述情况只发生在 API Level 29 (Android 10) [Q] ?
|
||||
super.getChild(i)?.let { UiObject(it.unwrap(), depth + 1, i) }
|
||||
}.onFailure {
|
||||
// FIXME by Stardust on May 5, 2017.
|
||||
null.also { e.printStackTrace() }
|
||||
}
|
||||
it.printStackTrace()
|
||||
}.getOrNull()
|
||||
}
|
||||
|
||||
// @Deprecated by SuperMonster003 on Jul 20, 2023.
|
||||
@@ -413,10 +427,13 @@ open class UiObject(
|
||||
false.also { e.printStackTrace() }
|
||||
}
|
||||
|
||||
override fun getChild(index: Int): AccessibilityNodeInfoCompat =
|
||||
allocator?.getChild(this, index) ?: super.getChild(index)
|
||||
override fun getChild(index: Int): AccessibilityNodeInfoCompat {
|
||||
return allocator?.getChild(this, index) ?: super.getChild(index)
|
||||
}
|
||||
|
||||
override fun getParent(): AccessibilityNodeInfoCompat? = allocator?.getParent(this) ?: super.getParent()
|
||||
override fun getParent(): AccessibilityNodeInfoCompat? {
|
||||
return allocator?.getParent(this) ?: super.getParent()
|
||||
}
|
||||
|
||||
override fun findAccessibilityNodeInfosByText(text: String): List<AccessibilityNodeInfoCompat> {
|
||||
return allocator?.findAccessibilityNodeInfosByText(this, text)
|
||||
@@ -492,49 +509,7 @@ open class UiObject(
|
||||
return "[${UiObject::class.java.simpleName}] $simpledClassName ${summary()}"
|
||||
}
|
||||
|
||||
override fun hashCode() = listOf(
|
||||
"${packageName()}",
|
||||
"$parent",
|
||||
"${id()}",
|
||||
"${fullId()}",
|
||||
"${idHex()}",
|
||||
"${desc()}",
|
||||
text(),
|
||||
"${bounds()}",
|
||||
"${className()}",
|
||||
"${clickable()}",
|
||||
"${longClickable()}",
|
||||
"${scrollable()}",
|
||||
"${indexInParent()}",
|
||||
"${childCount()}",
|
||||
"${depth()}",
|
||||
"${checked()}",
|
||||
"${enabled()}",
|
||||
"${editable()}",
|
||||
"${focusable()}",
|
||||
"${checkable()}",
|
||||
"${selected()}",
|
||||
"$isDismissable",
|
||||
"${visibleToUser()}",
|
||||
"$isContextClickable",
|
||||
"${focused()}",
|
||||
"$isAccessibilityFocused",
|
||||
"${rowCount()}",
|
||||
"${columnCount()}",
|
||||
"${row()}",
|
||||
"${column()}",
|
||||
"${rowSpan()}",
|
||||
"${columnSpan()}",
|
||||
"$drawingOrder",
|
||||
"${actionNames()}",
|
||||
"${isSingleton()}",
|
||||
"${firstSibling()}",
|
||||
"${lastSibling()}",
|
||||
"${firstChild()}",
|
||||
"${lastChild()}",
|
||||
).toHashCode()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
fun isSimilar(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is UiObject) return false
|
||||
|
||||
@@ -543,6 +518,7 @@ open class UiObject(
|
||||
val info = unwrap() ?: return false
|
||||
|
||||
return info == other.unwrap() &&
|
||||
bounds() == other.bounds() &&
|
||||
packageName() == other.packageName() &&
|
||||
parent == other.parent &&
|
||||
id() == other.id() &&
|
||||
@@ -550,7 +526,6 @@ open class UiObject(
|
||||
idHex() == other.idHex() &&
|
||||
desc() == other.desc() &&
|
||||
text() == other.text() &&
|
||||
bounds() == other.bounds() &&
|
||||
className() == other.className() &&
|
||||
clickable() == other.clickable() &&
|
||||
longClickable() == other.longClickable() &&
|
||||
@@ -578,26 +553,32 @@ open class UiObject(
|
||||
drawingOrder == other.drawingOrder &&
|
||||
actionNames() == other.actionNames() &&
|
||||
isSingleton() == other.isSingleton() &&
|
||||
"${firstSibling()}" == "${other.firstSibling()}" &&
|
||||
"${lastSibling()}" == "${other.lastSibling()}" &&
|
||||
"${firstChild()}" == "${other.firstChild()}" &&
|
||||
"${lastChild()}" == "${other.lastChild()}"
|
||||
"${firstSibling() ?: ""}" == "${other.firstSibling()}" &&
|
||||
"${lastSibling() ?: ""}" == "${other.lastSibling()}" &&
|
||||
"${firstChild() ?: ""}" == "${other.firstChild()}" &&
|
||||
"${lastChild() ?: ""}" == "${other.lastChild()}"
|
||||
}
|
||||
|
||||
fun isSimilar(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null) return false
|
||||
when (other) {
|
||||
is Scriptable -> {
|
||||
val thisHashCode = hashCode()
|
||||
val otherHashCode = RhinoUtils.hashCodeOfScriptable(other) ?: return false
|
||||
return thisHashCode == otherHashCode
|
||||
fun isShifted(other: UiObject) = bounds() == other.bounds()
|
||||
|
||||
fun isShifted(other: UiObject, tolerance: Double): Boolean {
|
||||
val a = bounds()
|
||||
val b = other.bounds()
|
||||
return when {
|
||||
tolerance < 0 -> throw WrappedIllegalArgumentException(
|
||||
"Argument \"tolerance\" ${tolerance.jsBrief()} for UiObject#isShifted must be greater than or equal to 0",
|
||||
)
|
||||
tolerance < 1 -> (width() to height()).let { (w, h) ->
|
||||
return@let abs(a.left - b.left) > tolerance * w
|
||||
|| abs(a.top - b.top) > tolerance * h
|
||||
|| abs(a.right - b.right) > tolerance * w
|
||||
|| abs(a.bottom - b.bottom) > tolerance * h
|
||||
}
|
||||
else -> {
|
||||
return when {
|
||||
other.javaClass != UiObject::class.java -> false
|
||||
else -> hashCode() == other.hashCode()
|
||||
}
|
||||
else -> let {
|
||||
return@let abs(a.left - b.left) > tolerance
|
||||
|| abs(a.top - b.top) > tolerance
|
||||
|| abs(a.right - b.right) > tolerance
|
||||
|| abs(a.bottom - b.bottom) > tolerance
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#Sun Jun 15 14:16:44 CST 2025
|
||||
BUILD_TIME=1749968204434
|
||||
#Mon Jun 23 16:34:06 CST 2025
|
||||
BUILD_TIME=1750667646268
|
||||
COMPILE_SDK_VERSION=35
|
||||
IMAGE_QUANT_CMAKE_VERSION=3.22.1
|
||||
IMAGE_QUANT_NDK_VERSION=26.1.10909125
|
||||
@@ -19,6 +19,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
|
||||
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
|
||||
TARGET_SDK_VERSION=35
|
||||
TARGET_SDK_VERSION_INRT=29
|
||||
VERSION_BUILD=3293
|
||||
VERSION_BUILD=3302
|
||||
VERSION_NAME=6.7.0 Alpha2
|
||||
VSCODE_EXT_REQUIRED_VERSION=1.0.8
|
||||
|
||||
Reference in New Issue
Block a user