diff --git a/.changelog/lang_ar.json b/.changelog/lang_ar.json index e6b61ab4..a27076ce 100644 --- a/.changelog/lang_ar.json +++ b/.changelog/lang_ar.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "وحدة Pinyin لتحويل النصوص الصينية إلى بينيين (راجع وثائق المشروع > [البينيين الصيني](https://docs.autojs6.com/#/pinyin))", "وحدة Pinyin4j لتحويل النصوص الصينية إلى بينيين (راجع وثائق المشروع > [البينيين الصيني](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_en.json b/.changelog/lang_en.json index 0fb0fd08..8aa3c279 100644 --- a/.changelog/lang_en.json +++ b/.changelog/lang_en.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "Pinyin module for Chinese Pinyin conversion (Refer to Project Documentation > [Chinese Pinyin](https://docs.autojs6.com/#/pinyin))", "Pinyin4j module for Chinese Pinyin conversion (Refer to Project Documentation > [Chinese Pinyin](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_es.json b/.changelog/lang_es.json index 510a98f7..fc4ae402 100644 --- a/.changelog/lang_es.json +++ b/.changelog/lang_es.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "Módulo Pinyin para la conversión de pinyin en chino (Consulte la documentación del proyecto > [Pinyin chino](https://docs.autojs6.com/#/pinyin))", "Módulo Pinyin4j para la conversión de pinyin en chino (Consulte la documentación del proyecto > [Pinyin chino](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_fr.json b/.changelog/lang_fr.json index 04cf75d8..b998e7b2 100644 --- a/.changelog/lang_fr.json +++ b/.changelog/lang_fr.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "Module Pinyin pour la conversion du pinyin chinois (Consultez la documentation du projet > [Pinyin chinois](https://docs.autojs6.com/#/pinyin))", "Module Pinyin4j pour la conversion du pinyin chinois (Consultez la documentation du projet > [Pinyin chinois](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_ja.json b/.changelog/lang_ja.json index 1655467b..a040d10c 100644 --- a/.changelog/lang_ja.json +++ b/.changelog/lang_ja.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "中国語のピンイン変換用の Pinyin モジュール (プロジェクトドキュメントを参照 > [中国語ピンイン](https://docs.autojs6.com/#/pinyin))", "中国語のピンイン変換用の Pinyin4j モジュール (プロジェクトドキュメントを参照 > [中国語ピンイン](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_ko.json b/.changelog/lang_ko.json index bf3d2bb8..853b3229 100644 --- a/.changelog/lang_ko.json +++ b/.changelog/lang_ko.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "중국어 병음 변환을 위한 Pinyin 모듈 (프로젝트 문서 참고 > [중국어 병음](https://docs.autojs6.com/#/pinyin))", "중국어 병음 변환을 위한 Pinyin4j 모듈 (프로젝트 문서 참고 > [중국어 병음](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_ru.json b/.changelog/lang_ru.json index cace4894..53edee64 100644 --- a/.changelog/lang_ru.json +++ b/.changelog/lang_ru.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "Модуль Pinyin для преобразования китайского пиньиня (См. документацию проекта > [Китайский Пиньинь](https://docs.autojs6.com/#/pinyin))", "Модуль Pinyin4j для преобразования китайского пиньиня (См. документацию проекта > [Китайский Пиньинь](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index dbd63ec5..293908e4 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -1,11 +1,12 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "pinyin 模块, 用于汉语拼音转换 (参阅 项目文档 > [汉语拼音](https://docs.autojs6.com/#/pinyin))", "pinyin4j 模块, 用于汉语拼音转换 (参阅 项目文档 > [汉语拼音](https://docs.autojs6.com/#/pinyin4j))", - "UiObject#isSimilar 及 UiObjectCollection#isSimilar 方法, 用于确定控件或控件集合是否相似" + "UiObject#isSimilar 及 UiObjectCollection#isSimilar 方法, 用于确定控件或控件集合是否相似", + "currentComponent 全局方法, 用于获取当前活动的组件名称信息" ], "fix": [ "部分环境因回退版本过低而无法正常编译项目的问题", @@ -16,6 +17,7 @@ "UiObjectCollection 实例缺失自身方法及属性的问题" ], "improvement": [ + "提升 currentPackage/currentActivity 识别准确性 (优先级: Shizuku > Root > A11Y)", "恢复日志活动窗口单个条目文本内容的双击或长按选择功能 _[`issue #280`](http://issues.autojs6.com/280)_", "脚本项目识别在 project.json 损坏情况下尽可能还原关键信息", "打包单文件时自动生成的包名后缀支持将简体中文转换为拼音 (支持多音字)", diff --git a/.changelog/lang_zh-Hant-HK.json b/.changelog/lang_zh-Hant-HK.json index 94fd6e77..75d0b9f3 100644 --- a/.changelog/lang_zh-Hant-HK.json +++ b/.changelog/lang_zh-Hant-HK.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "pinyin 模塊, 用於漢語拼音轉換 (參閲 項目文檔 > [漢語拼音](https://docs.autojs6.com/#/pinyin))", "pinyin4j 模塊, 用於漢語拼音轉換 (參閲 項目文檔 > [漢語拼音](https://docs.autojs6.com/#/pinyin4j))", diff --git a/.changelog/lang_zh-Hant-TW.json b/.changelog/lang_zh-Hant-TW.json index 2c2e7010..824810be 100644 --- a/.changelog/lang_zh-Hant-TW.json +++ b/.changelog/lang_zh-Hant-TW.json @@ -1,7 +1,7 @@ { "$data": { "v6.6.1": { - "released_date": "2024/12/27", + "released_date": "2025/01/01", "feature": [ "pinyin 模組, 用於漢語拼音轉換 (參閱 專案文件 > [漢語拼音](https://docs.autojs6.com/#/pinyin))", "pinyin4j 模組, 用於漢語拼音轉換 (參閱 專案文件 > [漢語拼音](https://docs.autojs6.com/#/pinyin4j))", diff --git a/app/src/main/aidl/org/autojs/autojs/core/shizuku/IUserService.aidl b/app/src/main/aidl/org/autojs/autojs/core/shizuku/IUserService.aidl index ace5800b..f9ddc64c 100644 --- a/app/src/main/aidl/org/autojs/autojs/core/shizuku/IUserService.aidl +++ b/app/src/main/aidl/org/autojs/autojs/core/shizuku/IUserService.aidl @@ -8,4 +8,9 @@ interface IUserService { String execCommand(String command) = 2; + String currentPackage() = 11; + String currentActivity() = 12; + String currentComponent() = 13; + String currentComponentShort() = 14; + } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/core/shizuku/UserService.kt b/app/src/main/java/org/autojs/autojs/core/shizuku/UserService.kt index a468ea04..49e658a4 100644 --- a/app/src/main/java/org/autojs/autojs/core/shizuku/UserService.kt +++ b/app/src/main/java/org/autojs/autojs/core/shizuku/UserService.kt @@ -1,58 +1,77 @@ -package org.autojs.autojs.core.shizuku; +package org.autojs.autojs.core.shizuku -import android.content.Context; -import android.os.RemoteException; -import android.util.Log; +import android.app.ActivityManager +import android.content.ComponentName +import android.content.Context +import android.os.RemoteException +import android.util.Log +import androidx.annotation.Keep +import org.autojs.autojs.runtime.api.AbstractShell +import org.autojs.autojs.runtime.api.ProcessShell -import androidx.annotation.Keep; +class UserService : IUserService.Stub { -import org.autojs.autojs.runtime.api.AbstractShell; -import org.autojs.autojs.runtime.api.ProcessShell; + private var mContext: Context? = null -public class UserService extends IUserService.Stub { + @Suppress("DEPRECATION") + private val currentActivity: ComponentName? + get() { + val manager = mContext?.getSystemService(ActivityManager::class.java) ?: return null + val tasks = manager.getRunningTasks(1) ?: return null + if (tasks.isEmpty()) return null + return tasks[0].topActivity + } /** * Constructor is required. */ - public UserService() { - Log.i("UserService", "constructor"); + constructor() { + Log.i("UserService", "constructor") } /** * Constructor with Context. This is only available from Shizuku API v13. - *

- * This method need to be annotated with {@link Keep} to prevent ProGuard from removing it. + * + * + * This method need to be annotated with [Keep] to prevent ProGuard from removing it. * * @param context Context created with createPackageContextAsUser - * @see code used to create the instance of this class + * @see [code used to create the instance of this class](https://github.com/RikkaApps/Shizuku-API/blob/672f5efd4b33c2441dbf609772627e63417587ac/server-shared/src/main/java/rikka/shizuku/server/UserService.java.L66) */ @Keep - public UserService(Context context) { - Log.i("UserService", "constructor with Context: context=" + context.toString()); + constructor(context: Context) { + Log.i("UserService", "constructor with Context: context=$context") + mContext = context } /** * Reserved destroy method */ - @Override - public void destroy() { - Log.i("UserService", "destroy"); + override fun destroy() { + Log.i("UserService", "destroy") } - @Override - public void exit() { - destroy(); + override fun exit() { + destroy() } - @Override - public String execCommand(String command) throws RemoteException { - try { - return ProcessShell - .execCommand(command.split("\n"), ProcessShell.getShellProcess()) - .toJson(); - } catch (Exception e) { - return new AbstractShell.Result(1, e).toJson(); + @Throws(RemoteException::class) + override fun execCommand(command: String): String { + return try { + ProcessShell + .execCommand(command.split("\n".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray(), ProcessShell.getShellProcess()) + .toJson() + } catch (e: Exception) { + AbstractShell.Result(1, e).toJson() } } + override fun currentPackage() = currentActivity?.packageName ?: "" + + override fun currentActivity() = currentActivity?.className ?: "" + + override fun currentComponent() = currentActivity?.flattenToString() ?: "" + + override fun currentComponentShort() = currentActivity?.flattenToShortString() ?: "" + } diff --git a/app/src/main/java/org/autojs/autojs/engine/RhinoJavaScriptEngine.kt b/app/src/main/java/org/autojs/autojs/engine/RhinoJavaScriptEngine.kt index 82238e0c..5878f082 100644 --- a/app/src/main/java/org/autojs/autojs/engine/RhinoJavaScriptEngine.kt +++ b/app/src/main/java/org/autojs/autojs/engine/RhinoJavaScriptEngine.kt @@ -195,6 +195,7 @@ open class RhinoJavaScriptEngine(private val scriptRuntime: ScriptRuntime, priva if (this is AutoJsContext) { rhinoJavaScriptEngine = this@RhinoJavaScriptEngine } + @Suppress("DEPRECATION") optimizationLevel = -1 languageVersion = Context.VERSION_ES6 locale = Locale.getDefault() diff --git a/app/src/main/java/org/autojs/autojs/rhino/AndroidContextFactory.kt b/app/src/main/java/org/autojs/autojs/rhino/AndroidContextFactory.kt index 22b95e7e..77550168 100644 --- a/app/src/main/java/org/autojs/autojs/rhino/AndroidContextFactory.kt +++ b/app/src/main/java/org/autojs/autojs/rhino/AndroidContextFactory.kt @@ -53,6 +53,7 @@ open class AndroidContextFactory(private val cacheDirectory: File) : ContextFact private fun setupContext(context: Context) { context.apply { instructionObserverThreshold = 10000 + @Suppress("DEPRECATION") optimizationLevel = -1 languageVersion = Context.VERSION_ES6 locale = Locale.getDefault() diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/Shell.java b/app/src/main/java/org/autojs/autojs/runtime/api/Shell.java index 19fa88da..88319219 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/Shell.java +++ b/app/src/main/java/org/autojs/autojs/runtime/api/Shell.java @@ -67,30 +67,24 @@ public class Shell extends AbstractShell { private volatile boolean mInitialized = false; private volatile boolean mWaitingExit = false; private volatile String mCommandOutput = null; - private final boolean mShouldReadOutput; private Callback mCallback; + public Shell(Context context, boolean root) { + super(context, root); + } + public Shell(Context context) { this(context, false); } - public Shell(Context context, boolean root) { - this(context, root, true); - } - - public Shell(Context context, boolean root, boolean shouldReadOutput) { - super(context, root); - mShouldReadOutput = shouldReadOutput; + public Shell(boolean root) { + this(ScriptRuntime.getApplicationContext(), root); } public Shell() { this(false); } - public Shell(boolean root) { - this(ScriptRuntime.getApplicationContext(), root); - } - @Override protected void init(final String initialCommand) { Handler uiHandler = new Handler(mContext.getMainLooper()); diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/WrappedShizuku.kt b/app/src/main/java/org/autojs/autojs/runtime/api/WrappedShizuku.kt index 47f423e5..bada59d0 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/WrappedShizuku.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/WrappedShizuku.kt @@ -53,10 +53,8 @@ object WrappedShizuku { } private val mUserServiceArgs = Shizuku.UserServiceArgs(ComponentName(BuildConfig.APPLICATION_ID, UserService::class.java.name)) + .processNameSuffix("shizuku-service-for-${BuildConfig.APPLICATION_ID.substringAfterLast(".")}") .daemon(false) - .processNameSuffix("service-for-${BuildConfig.APPLICATION_ID.split(".").lastOrNull() ?: BuildConfig.APPLICATION_ID}") - .debuggable(BuildConfig.DEBUG) - .version(BuildConfig.VERSION_CODE) private val mBinderReceivedListener = Shizuku.OnBinderReceivedListener { if (Shizuku.isPreV11()) { diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/automator/Auto.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/automator/Auto.kt index 07c58683..0ee6b7ab 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/automator/Auto.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/automator/Auto.kt @@ -31,6 +31,27 @@ import java.util.function.Supplier @Suppress("unused", "UNUSED_PARAMETER") class Auto(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable { + override val selfAssignmentFunctions = listOf( + ::start.name, + ::stop.name, + ::isRunning.name, + ::exists.name, + ::stateListener.name, + ::registerEvent.name, + ::registerEvents.name, + ::removeEvent.name, + ::removeEvents.name, + ::waitFor.name, + ::setMode.name, + ::setFlags.name, + ::setWindowFilter.name, + ::launchSettings.name, + ::clearCache.name, + ::currentPackage.name, + ::currentActivity.name, + ::currentComponent.name, + ) + override val selfAssignmentGetters = listOf>>( "service" to Supplier { scriptRuntime.accessibilityBridge.service @@ -52,24 +73,6 @@ class Auto(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime }, ) - override val selfAssignmentFunctions = listOf( - ::start.name, - ::stop.name, - ::isRunning.name, - ::exists.name, - ::stateListener.name, - ::registerEvent.name, - ::registerEvents.name, - ::removeEvent.name, - ::removeEvents.name, - ::waitFor.name, - ::setMode.name, - ::setFlags.name, - ::setWindowFilter.name, - ::launchSettings.name, - ::clearCache.name, - ) - override fun invoke(vararg args: Any?): Any = ensureArgumentsAtMost(args, 2) { when { it.isEmpty() -> invoke(null) @@ -134,21 +137,22 @@ class Auto(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime @RhinoRuntimeFunctionInterface fun stateListener(scriptRuntime: ScriptRuntime, args: Array): Undefined = ensureArgumentsAtMost(args, 1) { val (listener) = it - scriptRuntime.accessibilityBridge.setAccessibilityListener(when { - listener.isJsNullish() -> null - listener is AccessibilityServiceCallback -> listener - listener is ScriptableObject -> { - val adapter = NativeJavaObject.createInterfaceAdapter( - AccessibilityServiceCallback::class.java, listener - ) as AccessibilityServiceCallback + scriptRuntime.accessibilityBridge.setAccessibilityListener( + when { + listener.isJsNullish() -> null + listener is AccessibilityServiceCallback -> listener + listener is ScriptableObject -> { + val adapter = NativeJavaObject.createInterfaceAdapter( + AccessibilityServiceCallback::class.java, listener + ) as AccessibilityServiceCallback - object : AccessibilityServiceCallback { - override fun onConnected() = adapter.onConnected() - override fun onDisconnected() = adapter.onDisconnected() + object : AccessibilityServiceCallback { + override fun onConnected() = adapter.onConnected() + override fun onDisconnected() = adapter.onDisconnected() + } } - } - else -> throw WrappedIllegalArgumentException("Argument listener ($listener) is invalid for auto.setWindowFilter") - }) + else -> throw WrappedIllegalArgumentException("Argument listener ($listener) is invalid for auto.setWindowFilter") + }) UNDEFINED } @@ -157,19 +161,20 @@ class Auto(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime fun registerEvent(scriptRuntime: ScriptRuntime, args: Array) = ensureArgumentsLength(args, 2) { val (name, listener) = it require(!name.isJsNullish()) { "Argument \"name\" for auto.registerEvent cannot be nullish" } - scriptRuntime.automator.registerEvent(Context.toString(name), when { - listener.isJsNullish() -> null - listener is AccessibilityEventCallback -> listener - listener is ScriptableObject -> { - val adapter = NativeJavaObject.createInterfaceAdapter( - AccessibilityEventCallback::class.java, listener - ) as AccessibilityEventCallback - object : AccessibilityEventCallback { - override fun onAccessibilityEvent(event: AccessibilityEventWrapper) = adapter.onAccessibilityEvent(event) + scriptRuntime.automator.registerEvent( + Context.toString(name), when { + listener.isJsNullish() -> null + listener is AccessibilityEventCallback -> listener + listener is ScriptableObject -> { + val adapter = NativeJavaObject.createInterfaceAdapter( + AccessibilityEventCallback::class.java, listener + ) as AccessibilityEventCallback + object : AccessibilityEventCallback { + override fun onAccessibilityEvent(event: AccessibilityEventWrapper) = adapter.onAccessibilityEvent(event) + } } - } - else -> throw WrappedIllegalArgumentException("Argument listener ($listener) is invalid for auto.registerEvent") - }) + else -> throw WrappedIllegalArgumentException("Argument listener ($listener) is invalid for auto.registerEvent") + }) } @JvmStatic @@ -262,6 +267,26 @@ class Auto(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime accessibilityTool.clearCache() } + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentPackage(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + scriptRuntime.info.latestPackage + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentActivity(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + scriptRuntime.info.latestActivity + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentComponent(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + val latestPackage = scriptRuntime.info.latestPackage.takeUnless { it.isEmpty() } ?: return@ensureArgumentsIsEmpty "" + val latestActivity = scriptRuntime.info.latestActivity.takeUnless { it.isEmpty() } ?: return@ensureArgumentsIsEmpty "" + "$latestPackage/$latestActivity" + } + private fun ensureA11yServiceStarted(scriptRuntime: ScriptRuntime, isForcibleRestart: Any?) { if (isForcibleRestart !is Boolean) throw WrappedIllegalArgumentException("Argument isForcibleRestart must be of type Boolean") scriptRuntime.accessibilityBridge.ensureServiceStarted(isForcibleRestart) diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt index c3cbcac3..7f7c4847 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/global/Global.kt @@ -9,18 +9,22 @@ import org.autojs.autojs.extension.AnyExtensions.jsBrief import org.autojs.autojs.extension.NumberExtensions.string import org.autojs.autojs.extension.ScriptableExtensions.defineProp import org.autojs.autojs.extension.ScriptableExtensions.prop +import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.api.ScreenMetrics import org.autojs.autojs.runtime.api.augment.Augmentable +import org.autojs.autojs.runtime.api.augment.automator.Auto import org.autojs.autojs.runtime.api.augment.console.Console import org.autojs.autojs.runtime.api.augment.jsox.Numberx import org.autojs.autojs.runtime.api.augment.s13n.S13n import org.autojs.autojs.runtime.api.augment.selector.Selector +import org.autojs.autojs.runtime.api.augment.shell.Shell +import org.autojs.autojs.runtime.api.augment.shizuku.Shizuku import org.autojs.autojs.runtime.api.augment.toast.Toast import org.autojs.autojs.runtime.api.augment.util.Util -import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.runtime.exception.NotImplementedError import org.autojs.autojs.runtime.exception.ShouldNeverHappenException +import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.util.RhinoUtils import org.autojs.autojs.util.RhinoUtils.NOT_CONSTRUCTABLE import org.autojs.autojs.util.RhinoUtils.UNDEFINED @@ -79,6 +83,7 @@ class Global(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti ::getClip.name, ::currentPackage.name, ::currentActivity.name, + ::currentComponent.name, ::wait.name, ::waitForActivity.name, ::waitForPackage.name, @@ -295,14 +300,50 @@ class Global(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti @JvmStatic @RhinoRuntimeFunctionInterface - fun currentPackage(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { - scriptRuntime.info.latestPackage + fun currentPackage(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsAtMost(args, 1) { argList -> + val (o) = argList + when (parseComponentFetchMode(o)) { + ComponentFetchMode.ACCESSIBILITY -> Auto.currentPackage(scriptRuntime, emptyArray()) + ComponentFetchMode.SHIZUKU -> Shizuku.currentPackage(scriptRuntime, emptyArray()) + ComponentFetchMode.ROOT -> Shell.currentPackage(scriptRuntime, emptyArray()) + ComponentFetchMode.AUTOMATISM -> listOf( + { Shizuku.currentPackage(scriptRuntime, emptyArray()) }, + { Shell.currentPackage(scriptRuntime, emptyArray()) }, + { Auto.currentPackage(scriptRuntime, emptyArray()) } + ).firstNotNullOfOrNull { f -> f().takeUnless { it.isEmpty() } }.orEmpty() + } } @JvmStatic @RhinoRuntimeFunctionInterface - fun currentActivity(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { - scriptRuntime.info.latestActivity + fun currentActivity(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsAtMost(args, 1) { argList -> + val (o) = argList + when (parseComponentFetchMode(o)) { + ComponentFetchMode.ACCESSIBILITY -> Auto.currentActivity(scriptRuntime, emptyArray()) + ComponentFetchMode.SHIZUKU -> Shizuku.currentActivity(scriptRuntime, emptyArray()) + ComponentFetchMode.ROOT -> Shell.currentActivity(scriptRuntime, emptyArray()) + ComponentFetchMode.AUTOMATISM -> listOf( + { Shizuku.currentActivity(scriptRuntime, emptyArray()) }, + { Shell.currentActivity(scriptRuntime, emptyArray()) }, + { Auto.currentActivity(scriptRuntime, emptyArray()) } + ).firstNotNullOfOrNull { f -> f().takeUnless { it.isEmpty() } }.orEmpty() + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentComponent(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsAtMost(args, 1) { argList -> + val (o) = argList + when (parseComponentFetchMode(o)) { + ComponentFetchMode.ACCESSIBILITY -> Auto.currentComponent(scriptRuntime, emptyArray()) + ComponentFetchMode.SHIZUKU -> Shizuku.currentComponent(scriptRuntime, emptyArray()) + ComponentFetchMode.ROOT -> Shell.currentComponent(scriptRuntime, emptyArray()) + ComponentFetchMode.AUTOMATISM -> listOf( + { Shizuku.currentComponent(scriptRuntime, emptyArray()) }, + { Shell.currentComponent(scriptRuntime, emptyArray()) }, + { Auto.currentComponent(scriptRuntime, emptyArray()) } + ).firstNotNullOfOrNull { f -> f().takeUnless { it.isEmpty() } }.orEmpty() + } } @JvmStatic @@ -647,6 +688,20 @@ class Global(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunti else -> arrayOf(args.first()) } + private fun parseComponentFetchMode(o: Any?): ComponentFetchMode = when { + o.isJsNullish() -> ComponentFetchMode.AUTOMATISM + o is NativeObject -> parseComponentFetchMode(o.inquire(listOf("by", "mode"), ::coerceString, "")) + else -> when (coerceString(o, "").lowercase()) { + "", "auto", "automatic", "automatism" -> ComponentFetchMode.AUTOMATISM + "a11y", "accessibility" -> ComponentFetchMode.ACCESSIBILITY + "shizuku" -> ComponentFetchMode.SHIZUKU + "root" -> ComponentFetchMode.ROOT + else -> throw WrappedIllegalArgumentException("Unknown component fetch mode: ${coerceString(o)}") + } + } + + private enum class ComponentFetchMode { AUTOMATISM, ACCESSIBILITY, SHIZUKU, ROOT } + } } diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/shell/Shell.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/shell/Shell.kt index 46a6dc38..3c096416 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/shell/Shell.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/shell/Shell.kt @@ -1,5 +1,6 @@ package org.autojs.autojs.runtime.api.augment.shell +import android.util.Log import android.view.KeyEvent import androidx.annotation.IntRange import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface @@ -16,6 +17,7 @@ import org.autojs.autojs.util.RhinoUtils.coerceBoolean import org.autojs.autojs.util.RhinoUtils.coerceIntNumber import org.autojs.autojs.util.RhinoUtils.coerceString import org.autojs.autojs.util.RhinoUtils.undefined +import org.autojs.autojs.util.RootUtils import org.mozilla.javascript.NativeArray import org.mozilla.javascript.NativeObject import org.mozilla.javascript.Undefined @@ -28,6 +30,9 @@ class Shell(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim ::getCommand.name, ::fromIntent.name, ::kill.name, + ::currentPackage.name, + ::currentActivity.name, + ::currentComponent.name, ) override val globalAssignmentFunctions = listOf( @@ -56,6 +61,8 @@ class Shell(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim companion object : FlexibleArray() { + private val TAG = Shell::class.java.simpleName + @JvmStatic @RhinoRuntimeFunctionInterface fun execCommand(scriptRuntime: ScriptRuntime, args: Array): AbstractShell.Result = ensureArgumentsLengthInRange(args, 1..3) { argList -> @@ -80,12 +87,56 @@ class Shell(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim @JvmStatic @RhinoRuntimeFunctionInterface fun kill(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsOnlyOne(args) { app -> + if (!RootUtils.isRootAvailable()) return@ensureArgumentsOnlyOne false when (val packageName = App.getPackageName(scriptRuntime, arrayOf(app))) { null -> false else -> execCommand(scriptRuntime, arrayOf("am force-stop $packageName", true)).code == 0 } } + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentPackage(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + currentComponent(scriptRuntime, args).substringBefore("/") + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentActivity(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + val component = currentComponent(scriptRuntime, args) + val className = component.substringAfterLast("/") + when { + className.startsWith(".") -> component + else -> className + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentComponent(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + if (!RootUtils.isRootAvailable()) return@ensureArgumentsIsEmpty "" + try { + val process = Runtime.getRuntime().exec("su -c dumpsys activity activities") + process.inputStream.bufferedReader().useLines { lines -> + val resumedActivityLine = lines.find { + it.contains("Resumed:") || it.contains("ResumedActivity") + } + resumedActivityLine?.let { line -> + Log.d(TAG, "Found Resumed Activity: $line") + line.split("\\s+".toRegex()).firstOrNull { part -> + part.contains("/") + }?.let { part -> + Log.d(TAG, "current activity part: $part") + return@ensureArgumentsIsEmpty part.replace("\\W+$".toRegex(), "") + } + } + } + } catch (e: Exception) { + Log.e(TAG, "Error reading current component", e) + } + return@ensureArgumentsIsEmpty "" + } + @JvmStatic @RhinoRuntimeFunctionInterface fun Menu(scriptRuntime: ScriptRuntime, args: Array): Undefined = ensureArgumentsIsEmpty(args) { @@ -323,6 +374,17 @@ class Shell(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntim .replace(Regex("([a-z])([0-9])"), "$1-$2") // handle letters followed by numbers .lowercase() + private fun completeActivityNames(name: String): String { + val parts = name.split("/") + if (parts.size == 2) { + val (packageName, activityName) = parts + if (activityName.startsWith(".")) { + return "$packageName/$packageName$activityName" + } + } + return name + } + data class CommandArgumentsData(val arguments: String = "", val withRoot: Boolean = false, val withExit: Boolean = false) data class CommandData(val command: String, @IntRange(0, 1) val withRoot: Int = 0) diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/shizuku/Shizuku.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/shizuku/Shizuku.kt index b319ac80..06480a8a 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/shizuku/Shizuku.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/shizuku/Shizuku.kt @@ -3,9 +3,11 @@ package org.autojs.autojs.runtime.api.augment.shizuku import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface import org.autojs.autojs.runtime.ScriptRuntime import org.autojs.autojs.runtime.api.AbstractShell +import org.autojs.autojs.runtime.api.WrappedShizuku import org.autojs.autojs.runtime.api.augment.Augmentable import org.autojs.autojs.runtime.api.augment.Invokable -import org.autojs.autojs.runtime.api.augment.shell.Shell.Companion.getCommandData +import org.autojs.autojs.runtime.api.augment.app.App +import org.autojs.autojs.runtime.api.augment.shell.Shell @Suppress("unused", "UNUSED_PARAMETER") class Shizuku(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime), Invokable { @@ -13,6 +15,10 @@ class Shizuku(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt override val selfAssignmentFunctions = listOf( ::execCommand.name, ::getCommand.name, + ::kill.name, + ::currentPackage.name, + ::currentActivity.name, + ::currentComponent.name, ) override fun invoke(vararg args: Any?): AbstractShell.Result = execCommand(scriptRuntime, args) @@ -22,13 +28,50 @@ class Shizuku(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRunt @JvmStatic @RhinoRuntimeFunctionInterface fun execCommand(scriptRuntime: ScriptRuntime, args: Array): AbstractShell.Result = ensureArgumentsLengthInRange(args, 1..3) { argList -> - scriptRuntime.shizuku.execCommand(getCommandData(argList).command) + scriptRuntime.shizuku.execCommand(Shell.getCommandData(argList).command) } @JvmStatic @RhinoRuntimeFunctionInterface fun getCommand(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsLengthInRange(args, 1..3) { argList -> - getCommandData(argList).command + Shell.getCommandData(argList).command + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun kill(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsOnlyOne(args) { app -> + if (!WrappedShizuku.isOperational()) return@ensureArgumentsOnlyOne false + when (val packageName = App.getPackageName(scriptRuntime, arrayOf(app))) { + null -> false + else -> execCommand(scriptRuntime, arrayOf("am force-stop $packageName")).code == 0 + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentPackage(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + when { + !WrappedShizuku.isOperational() -> "" + else -> WrappedShizuku.service?.currentPackage() ?: "" + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentActivity(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + when { + !WrappedShizuku.isOperational() -> "" + else -> WrappedShizuku.service?.currentActivity() ?: "" + } + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun currentComponent(scriptRuntime: ScriptRuntime, args: Array): String = ensureArgumentsIsEmpty(args) { + when { + !WrappedShizuku.isOperational() -> "" + else -> WrappedShizuku.service?.currentComponent() ?: "" + } } } diff --git a/app/src/main/java/org/autojs/autojs/theme/preference/MaterialListPreference.kt b/app/src/main/java/org/autojs/autojs/theme/preference/MaterialListPreference.kt index d68d7919..89899bbb 100644 --- a/app/src/main/java/org/autojs/autojs/theme/preference/MaterialListPreference.kt +++ b/app/src/main/java/org/autojs/autojs/theme/preference/MaterialListPreference.kt @@ -9,7 +9,6 @@ import androidx.preference.Preference.SummaryProvider import com.afollestad.materialdialogs.MaterialDialog import org.autojs.autojs.core.pref.Pref import org.autojs.autojs.ui.common.NotAskAgainDialog -import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs6.R open class MaterialListPreference : MaterialDialogPreference { @@ -43,12 +42,12 @@ open class MaterialListPreference : MaterialDialogPreference { negativeText = getAttrString(a, R.styleable.MaterialListPreference_negativeText) ?: context.getString(R.string.dialog_button_cancel) getAttrTextArray(a, R.styleable.MaterialListPreference_itemKeys)?.also { mItemKeys = it.toList() } getAttrTextArray(a, R.styleable.MaterialListPreference_itemValues)?.also { mItemValues = it.toList() } - bundle.getString(key(R.string.key_pref_bundle_default_item), getAttrString(a, R.styleable.MaterialListPreference_itemDefaultKey))?.also { mItemDefaultKey = it } + bundle.getString(context.getString(R.string.key_pref_bundle_default_item), getAttrString(a, R.styleable.MaterialListPreference_itemDefaultKey))?.also { mItemDefaultKey = it } getAttrString(a, R.styleable.MaterialListPreference_onConfirmPrompt)?.also { mConfirmedPrompt = it } a.recycle() } - bundle.getIntegerArrayList(key(R.string.key_pref_bundle_disabled_items))?.map { context.getString(it) }?.let { disables -> + bundle.getIntegerArrayList(context.getString(R.string.key_pref_bundle_disabled_items))?.map { context.getString(it) }?.let { disables -> mItemKeys.forEachIndexed { index, it -> if (it in disables) mItemDisables += index } } diff --git a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenuWindow.java b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenuWindow.java index c93f57c6..e85e39b7 100644 --- a/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenuWindow.java +++ b/app/src/main/java/org/autojs/autojs/ui/floating/CircularMenuWindow.java @@ -220,10 +220,12 @@ public class CircularMenuWindow extends FloatyWindow { } public void savePosition() { - int x = mActionViewWindowBridge.getX(); - Pref.putFloatSync(KEY_POSITION_X_PERCENT, x / (float) ScreenMetrics.getDeviceScreenWidth()); - int y = mActionViewWindowBridge.getY(); - Pref.putFloatSync(KEY_POSITION_Y_PERCENT, y / (float) ScreenMetrics.getDeviceScreenHeight()); + if (mActionViewWindowBridge != null) { + int x = mActionViewWindowBridge.getX(); + Pref.putFloatSync(KEY_POSITION_X_PERCENT, x / (float) ScreenMetrics.getDeviceScreenWidth()); + int y = mActionViewWindowBridge.getY(); + Pref.putFloatSync(KEY_POSITION_Y_PERCENT, y / (float) ScreenMetrics.getDeviceScreenHeight()); + } } public void savePosition(@NotNull Configuration configuration) { diff --git a/version.properties b/version.properties index 24a7b93e..f379af7c 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Fri Dec 27 19:33:23 CST 2024 -BUILD_TIME=1735299203014 +#Wed Jan 01 11:40:23 CST 2025 +BUILD_TIME=1735702823631 COMPILE_SDK_VERSION=34 JAVA_VERSION=23 JAVA_VERSION_MIN_RADICAL=0 @@ -17,6 +17,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=34 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=2929 -VERSION_NAME=6.6.1 Alpha2 +VERSION_BUILD=2939 +VERSION_NAME=6.6.1 Alpha3 VSCODE_EXT_REQUIRED_VERSION=1.0.8