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