diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 69021987..25cf8379 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -13,6 +13,7 @@ "s13n.bytes 方法, 用于标准化字节数据 (参阅 项目文档 > [标准化](https://docs.autojs6.com/#/s13n))", "app.isDualInstalled 方法, 用于检测双开应用是否已安装 (需要 Shizuku 或 Root 权限) _[`issue #450`](http://issues.autojs6.com/450)_", "device.getSharedDeviceId 方法, 用于跨应用获取统一共享设备 ID _[`issue #455`](http://issues.autojs6.com/455)_", + "device.setPointerLocation 等 Toggleablle 系列方法, 用于设置或获取指针位置系统设置项 _[`issue #381`](http://issues.autojs6.com/381)_", "ui.getNavigationBarHeight 方法/navigationBarHeight 属性 (getter), 用于获取导航栏高度 _[`issue #456`](http://issues.autojs6.com/456)_", "ui.getVisible(Status/Navigation)BarHeight 方法/visible(Status/Navigation)BarHeight 属性 (getter), 用于快捷获取状态栏或导航栏可见高度 _[`issue #456`](http://issues.autojs6.com/456)_", "http 模块请求相关方法获取的 body 对象增加 stream/saveToFile/close 等方法 _[`issue #452`](http://issues.autojs6.com/452)_", diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/device/Device.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/device/Device.kt index 96027227..4d3b6454 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/device/Device.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/device/Device.kt @@ -1,10 +1,14 @@ package org.autojs.autojs.runtime.api.augment.device +import android.provider.Settings +import androidx.core.net.toUri import org.autojs.autojs.annotation.RhinoFunctionBody import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.AnyExtensions.jsBrief import org.autojs.autojs.extension.FlexibleArray +import org.autojs.autojs.extension.FlexibleArray.Companion.component1 +import org.autojs.autojs.extension.FlexibleArray.Companion.component2 import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.api.ScreenMetrics import org.autojs.autojs.runtime.api.augment.Augmentable @@ -14,12 +18,14 @@ import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.util.DeviceUtils import org.autojs.autojs.util.NetworkUtils import org.autojs.autojs.util.RhinoUtils.UNDEFINED +import org.autojs.autojs.util.RhinoUtils.coerceBoolean +import org.autojs.autojs.util.ShellUtils +import org.autojs.autojs.util.ShellUtils.PointerLocation import org.mozilla.javascript.Context import org.mozilla.javascript.NativeArray import org.mozilla.javascript.Undefined import java.util.function.Supplier import org.autojs.autojs.runtime.api.Device as ApiDevice -import androidx.core.net.toUri @Suppress("unused", "UNUSED_PARAMETER") class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { @@ -38,6 +44,13 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { ::isConnectedOrConnecting.name, ::isWifiAvailable.name, ::getSharedDeviceId.name, + + ::setPointerLocation.name, + ::setPointerLocationEnabled.name, + ::setPointerLocationDisabled.name, + ::isPointerLocationEnabled.name, + ::isPointerLocationDisabled.name, + ::togglePointerLocation.name, ) override val selfAssignmentGetters = listOf>>( @@ -50,6 +63,8 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { companion object : FlexibleArray() { + const val KEY_POINTER_LOCATION = "pointer_location" + @JvmStatic @RhinoRuntimeFunctionInterface fun summary(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { @@ -211,6 +226,70 @@ class Device(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { ?: throw WrappedIllegalArgumentException("Argument $it cannot be converted as a timing element for device.${::vibrate.name}") } + @JvmStatic + @RhinoRuntimeFunctionInterface + fun setPointerLocation(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsOnlyOne(args) { + val enabled = coerceBoolean(it, false) + + // @Hint by SuperMonster003 on Jan 10, 2025. + // ! Starting from Android API 23 (6.0) [M], in the android.provider.Settings.System source code, + // ! `PRIVATE_SETTINGS.add(POINTER_LOCATION);` means that `POINTER_LOCATION` is not settable, + // ! otherwise it will trigger an exception: + // ! "java.lang.IllegalArgumentException: You cannot change private secure settings.". + // ! zh-CN: + // ! Android API 23 (6.0) [M] 起, android.provider.Settings.System 源码中, + // ! `PRIVATE_SETTINGS.add(POINTER_LOCATION);` 意味着 `POINTER_LOCATION` 是不可设置的, + // ! 否则会触发异常: "java.lang.IllegalArgumentException: You cannot change private secure settings.". + // ! + // # if (SettingsCompat.canWriteSettings(globalContext)) { + // # try { + // # if (Settings.System.putInt(globalContext.contentResolver, KEY_POINTER_LOCATION, if (enabled) PointerLocation.ENABLED.value else PointerLocation.DISABLED.value)) { + // # return@ensureArgumentsOnlyOne true + // # } + // # } catch (e: Exception) { + // # if (e.message == null || !e.message!!.lowercase().contains("private secure settings")) { + // # e.printStackTrace() + // # } + // # } + // # } + + ShellUtils.checkPointerLocationState(globalContext, enabled) || ShellUtils.togglePointerLocation(globalContext) + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun setPointerLocationEnabled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsIsEmpty(args) { + setPointerLocation(scriptRuntime, arrayOf(true)) + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun setPointerLocationDisabled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsIsEmpty(args) { + setPointerLocation(scriptRuntime, arrayOf(false)) + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun isPointerLocationEnabled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsIsEmpty(args) { + try { + Settings.System.getInt(globalContext.contentResolver, KEY_POINTER_LOCATION, PointerLocation.DISABLED.value) == PointerLocation.ENABLED.value + } catch (e: Exception) { + ShellUtils.checkPointerLocationState(globalContext, true) + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun isPointerLocationDisabled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsIsEmpty(args) { + !isPointerLocationEnabled(scriptRuntime, args) + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun togglePointerLocation(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsIsEmpty(args) { + setPointerLocation(scriptRuntime, arrayOf(!isPointerLocationEnabled(scriptRuntime, args))) + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/util/ShellUtils.kt b/app/src/main/java/org/autojs/autojs/util/ShellUtils.kt index 97da77ab..2fe876ad 100644 --- a/app/src/main/java/org/autojs/autojs/util/ShellUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/ShellUtils.kt @@ -20,7 +20,8 @@ object ShellUtils { } } - private fun checkPointerLocationState(context: Context, aimState: Boolean) = when (aimState) { + @JvmStatic + fun checkPointerLocationState(context: Context, aimState: Boolean) = when (aimState) { true -> isPointerLocationEnabled(context) else -> isPointerLocationDisabled(context) } @@ -54,7 +55,7 @@ object ShellUtils { WrappedShizuku.execCommand(context, command) }.isSuccess - private enum class PointerLocation(val value: Int) { + enum class PointerLocation(val value: Int) { ENABLED(1), DISABLED(0) } diff --git a/version.properties b/version.properties index 8db49ad5..7e1cf656 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Fri Jan 09 23:39:38 CST 2026 -BUILD_TIME=1767973178586 +#Sat Jan 10 19:06:16 CST 2026 +BUILD_TIME=1768043176049 COMPILE_SDK_VERSION=36 IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_NDK_VERSION=26.1.10909125 @@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=36 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=3591 +VERSION_BUILD=3593 VERSION_NAME=6.7.0 Alpha14 VSCODE_EXT_REQUIRED_VERSION=1.0.13