diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 82068c38..9dce139b 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -48,6 +48,7 @@ "运行项目时 project.json 配置参数无法正常解析的问题", "修复项目配置文件中构建版本号或构建时间出现较大数字时可能导致应用崩溃的问题", "频繁获取或重建 ImageReader 时可能因缓冲区暂无可用帧导致应用崩溃的问题", + "输入事件观察器 InputEventObserver 可能导致应用启动时明显卡顿的问题", "打包应用无法正常使用 Paddle OCR 与 Rapid OCR 功能的问题", "版本历史页面部分系统因字体差别导致统计数据显示不完整的问题", "部分设备无法正常初始化 MLKit Google OCR 的问题 (试修) _[`issue #8`](http://issues.autojs6.com/8#issuecomment-3117061768)_", diff --git a/app/src/main/java/org/autojs/autojs/core/inputevent/InputDevices.kt b/app/src/main/java/org/autojs/autojs/core/inputevent/InputDevices.kt index b4deb362..0fb4f5be 100644 --- a/app/src/main/java/org/autojs/autojs/core/inputevent/InputDevices.kt +++ b/app/src/main/java/org/autojs/autojs/core/inputevent/InputDevices.kt @@ -45,9 +45,11 @@ object InputDevices { val result = ProcessShell.execCommand(cmd, true) if (result.code == 0) return@run result.result } - if (WrappedShizuku.isOperational()) { - val result = WrappedShizuku.execCommand(cmd) - if (result.code == 0) return@run result.result + if (WrappedShizuku.isRunning()) { + runCatching { + val result = WrappedShizuku.execCommand(cmd) + if (result.code == 0) return@run result.result + } } return -1 } diff --git a/app/src/main/java/org/autojs/autojs/core/inputevent/InputEventObserver.java b/app/src/main/java/org/autojs/autojs/core/inputevent/InputEventObserver.java index 5c611cb5..8992ebcc 100644 --- a/app/src/main/java/org/autojs/autojs/core/inputevent/InputEventObserver.java +++ b/app/src/main/java/org/autojs/autojs/core/inputevent/InputEventObserver.java @@ -32,9 +32,18 @@ public class InputEventObserver { public static InputEventObserver getGlobal(Context context) { if (sGlobal == null) { + // noinspection UnnecessaryLocalVariable InputEventObserver observer = new InputEventObserver(context); sGlobal = observer; - observer.observe(); + // @Hint by SuperMonster003 on Nov 16, 2025. + // ! If calling observe() here, it will synchronously create a Shell + // ! and block the main thread during app startup. + // ! Changed to lazy initialization, asynchronously call ensureObservedAsync() + // ! at appropriate time (like in GlobalKeyObserver constructor). + // ! zh-CN: + // ! 如果在此处调用 observe(), 会在应用启动时同步创建 Shell 并阻塞主线程. + // ! 修改为懒初始化, 在适当时机 (如 GlobalKeyObserver 构造函数中) 异步调用 ensureObservedAsync(). + // # observer.observe(); } return sGlobal; } @@ -109,6 +118,25 @@ public class InputEventObserver { }); } + // Ensure lazy start observation in background thread + // to avoid blocking the main thread/app startup. + // zh-CN: 确保在后台线程懒启动观察, 避免在主线程/应用启动期阻塞. + public void ensureObservedAsync() { + if (mShell != null) return; + synchronized (this) { + if (mShell != null) return; + new Thread(() -> { + try { + observe(); + } catch (Throwable ignored) { + // Do not throw exceptions to main thread to avoid affecting first screen; + // specific errors will be handled at the usage point. + // zh-CN: 启动失败时不抛到主线程, 避免影响首屏; 具体错误在使用处再处理. + } + }, "InputEventObserver-Init").start(); + } + } + public void onInputEvent(String eventStr) { if (!TextUtils.isEmpty(eventStr) && eventStr.startsWith("[")) { try { diff --git a/app/src/main/java/org/autojs/autojs/event/GlobalKeyObserver.java b/app/src/main/java/org/autojs/autojs/event/GlobalKeyObserver.java index 32c7c525..f77cd4d9 100644 --- a/app/src/main/java/org/autojs/autojs/event/GlobalKeyObserver.java +++ b/app/src/main/java/org/autojs/autojs/event/GlobalKeyObserver.java @@ -1,6 +1,7 @@ package org.autojs.autojs.event; import android.content.Context; +import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import org.autojs.autojs.AutoJs; @@ -31,7 +32,11 @@ public class GlobalKeyObserver implements OnKeyListener, ShellKeyObserver.KeyLis AccessibilityService.Companion.getStickOnKeyObserver().addListener(this); ShellKeyObserver observer = new ShellKeyObserver(); observer.setKeyListener(this); - InputEventObserver.getGlobal(applicationContext).addListener(observer); + InputEventObserver io = InputEventObserver.getGlobal(applicationContext); + io.addListener(observer); + // Starts getevent asynchronously with a delay to avoid blocking the first frame. + // zh-CN: 将底层 getevent 的启动改为异步, 并稍作延迟, 避免阻塞首帧. + new Handler(applicationContext.getMainLooper()).postDelayed(io::ensureObservedAsync, 240); } public static void initIfNeeded(Context applicationContext) {