diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 9f4d1079..2a7d80da 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -14,6 +14,7 @@ "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)_", + "images.loadAsync 方法, 用于异步获取网络图像资源 _[`issue #327`](http://issues.autojs6.com/327)_", "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/Images.java b/app/src/main/java/org/autojs/autojs/runtime/api/Images.java index 6ce4b7d4..fef8d265 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/Images.java +++ b/app/src/main/java/org/autojs/autojs/runtime/api/Images.java @@ -559,15 +559,11 @@ public class Images { }; } - public ImageWrapper load(String src) { - try { - HttpURLConnection connection = (HttpURLConnection) new URL(src).openConnection(); - connection.setDoInput(true); - connection.connect(); - return ImageWrapper.ofBitmap(mScriptRuntime, BitmapFactory.decodeStream(connection.getInputStream())); - } catch (IOException e) { - return null; - } + public ImageWrapper load(String src) throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(src).openConnection(); + connection.setDoInput(true); + connection.connect(); + return ImageWrapper.ofBitmap(mScriptRuntime, BitmapFactory.decodeStream(connection.getInputStream())); } public ImageWrapper invert(@NonNull ImageWrapper image) { diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt index 8b8360be..0b963d39 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/images/Images.kt @@ -51,6 +51,7 @@ import org.autojs.autojs.util.RhinoUtils.coerceIntNumber import org.autojs.autojs.util.RhinoUtils.coerceNumber import org.autojs.autojs.util.RhinoUtils.coerceString import org.autojs.autojs.util.RhinoUtils.coerceStringLowercase +import org.autojs.autojs.util.RhinoUtils.handleAsyncOperation import org.autojs.autojs.util.RhinoUtils.isBackgroundThread import org.autojs.autojs.util.RhinoUtils.isUiThread import org.autojs.autojs.util.RhinoUtils.newNativeObject @@ -86,6 +87,7 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt ::imread.name, ::copy.name, ::load.name, + ::loadAsync.name, ::clip.name, ::pixel.name, ::captureScreen.name to AS_GLOBAL, @@ -215,10 +217,17 @@ class Images(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), AsEmitt @JvmStatic @RhinoRuntimeFunctionInterface - fun load(scriptRuntime: ScriptRuntime, args: Array): ImageWrapper = ensureArgumentsOnlyOne(args) { src -> + fun load(scriptRuntime: ScriptRuntime, args: Array): ImageWrapper? = ensureArgumentsOnlyOne(args) { src -> scriptRuntime.images.load(coerceString(src)) } + @JvmStatic + @RhinoRuntimeFunctionInterface + fun loadAsync(scriptRuntime: ScriptRuntime, args: Array): NativeObject = ensureArgumentsOnlyOne(args) { src -> + val url = coerceString(src) + handleAsyncOperation(scriptRuntime) { scriptRuntime.images.load(url) } + } + @JvmStatic @RhinoRuntimeFunctionInterface fun clip(scriptRuntime: ScriptRuntime, args: Array): ImageWrapper = ensureArgumentsLengthInRange(args, 2..5) { diff --git a/app/src/main/java/org/autojs/autojs/util/RhinoUtils.kt b/app/src/main/java/org/autojs/autojs/util/RhinoUtils.kt index caf2f2ef..6e7e702b 100644 --- a/app/src/main/java/org/autojs/autojs/util/RhinoUtils.kt +++ b/app/src/main/java/org/autojs/autojs/util/RhinoUtils.kt @@ -17,6 +17,7 @@ import org.autojs.autojs.extension.ScriptableExtensions.defineProp import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.rhino.TopLevelScope import org.autojs.autojs.runtime.ScriptRuntime +import org.autojs.autojs.runtime.api.ScriptPromiseAdapter import org.autojs.autojs.runtime.exception.ScriptInterruptedException import org.autojs.autojs.runtime.exception.WrappedRuntimeException import org.autojs.autojs6.BuildConfig @@ -911,6 +912,37 @@ object RhinoUtils { return null } + fun handleAsyncOperation(scriptRuntime: ScriptRuntime, func: () -> Any?): NativeObject { + val promiseAdapter = ScriptPromiseAdapter() + + // Use Android Thread directly to avoid coupling with JS threads/loopers here. + // zh-CN: 直接使用 Android Thread, 避免在此处与 JS 线程/Looper 机制强耦合. + Thread { + try { + // Do the blocking work (e.g. network request) in background thread. + // zh-CN: 在后台线程执行阻塞式操作 (如网络请求). + val result = func.invoke() + + // Resolve on UI thread so that UI scripts can safely touch `ui.*` in then(). + // zh-CN: 在 UI 线程 resolve, 让 UI 脚本在 then() 中可安全操作 `ui.*`. + Handler(Looper.getMainLooper()).post { + promiseAdapter.resolve(result) + } + } catch (t: Throwable) { + // Reject on UI thread for consistent callback threading. + // zh-CN: 在 UI 线程 reject, 保持回调线程一致性. + Handler(Looper.getMainLooper()).post { + promiseAdapter.reject(t) + } + } + }.start() + + // Convert ScriptPromiseAdapter into a JavaScript Promise. + // zh-CN: 将 ScriptPromiseAdapter 转换为 JavaScript Promise. + return callFunction(scriptRuntime, scriptRuntime.js_ResultAdapter, "promise", arrayOf(promiseAdapter)) as NativeObject + } + + @JvmStatic fun Class<*>.getRhinoStandardFunctionMethods(): List { return this.declaredMethods.filter { diff --git a/version.properties b/version.properties index a01865f9..7b655998 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Mon Jan 12 17:10:46 CST 2026 -BUILD_TIME=1768209046850 +#Mon Jan 12 21:46:16 CST 2026 +BUILD_TIME=1768225576059 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=3598 +VERSION_BUILD=3599 VERSION_NAME=6.7.0 Alpha14 VSCODE_EXT_REQUIRED_VERSION=1.0.13