From e393ffc353d9fd419e1513ca8439b2ffe2c2e01e Mon Sep 17 00:00:00 2001 From: SuperMonster003 Date: Thu, 20 Nov 2025 16:22:05 +0800 Subject: [PATCH] =?UTF-8?q?6.7.0=20-=20Alpha11=20-=20=E6=96=B0=E5=A2=9E=20?= =?UTF-8?q?app.isDualInstalled=20=E6=96=B9=E6=B3=95,=20=E7=94=A8=E4=BA=8E?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E5=8F=8C=E5=BC=80=E5=BA=94=E7=94=A8=E6=98=AF?= =?UTF-8?q?=E5=90=A6=E5=B7=B2=E5=AE=89=E8=A3=85=20(=E9=9C=80=E8=A6=81=20Sh?= =?UTF-8?q?izuku=20=E6=88=96=20Root=20=E6=9D=83=E9=99=90)=20(issue=20#450)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changelog/lang_zh-Hans.json | 8 +- .../autojs/runtime/api/augment/app/App.kt | 139 +++++++++++---- .../org/autojs/autojs/util/RootUtils.java | 162 +++++++++++++----- app/src/main/res/values-ar/strings.xml | 2 +- app/src/main/res/values-en/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-ja/strings.xml | 2 +- app/src/main/res/values-ko/strings.xml | 2 +- app/src/main/res/values-ru/strings.xml | 2 +- app/src/main/res/values-zh-rHK/strings.xml | 2 +- app/src/main/res/values-zh-rTW/strings.xml | 2 +- app/src/main/res/values-zh/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 14 files changed, 236 insertions(+), 95 deletions(-) diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json index 00a356b8..4b1d70ff 100644 --- a/.changelog/lang_zh-Hans.json +++ b/.changelog/lang_zh-Hans.json @@ -1,7 +1,7 @@ { "$data": { "v6.7.0": { - "released_date": "2025/11/19", + "released_date": "2025/11/20", "feature": [ "cvt 模块, 用于数据单位转换 (参阅 项目文档 > [单位转换](https://docs.autojs6.com/#/cvt))", "fmt 模块, 用于数据格式化 (参阅 项目文档 > [格式化](https://docs.autojs6.com/#/fmt))", @@ -10,6 +10,7 @@ "cvt.bytes 方法, 用于字节数据单位转换 (参阅 项目文档 > [单位转换](https://docs.autojs6.com/#/cvt))", "fmt.bytes 方法, 用于字节数据格式化 (参阅 项目文档 > [数据格式化](https://docs.autojs6.com/#/fmt))", "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)_", "ui.navigationBarHeight 属性 (getter), 用于获取导航栏高度 _[`issue #456`](http://issues.autojs6.com/456)_", "http 模块请求相关方法获取的 body 对象增加 stream/saveToFile/close 方法 _[`issue #452`](http://issues.autojs6.com/452)_", @@ -31,7 +32,7 @@ "notice 方法参数数量及类型限制错误 _[`issue #462`](http://issues.autojs6.com/462)_", "isJavaClass/isJavaPackage 等全局方法无效的问题", "timers.keepAlive 方法 timeout 参数功能无效的问题", - "floaty.window/rawWindow 方法无法接受字符串参数的问题", + "floaty.window/rawWindow 方法无法接受字符串参数的问题 _[`issue #467`](http://issues.autojs6.com/467)_", "util.class[Name]/getClass[Name] 可能返回错误结果的问题", "threads.disposable() 返回的对象在存取数据时可能被意外装箱的问题 _[`issue #435`](http://issues.autojs6.com/435)_", "console.build 方法多次调用时, 日志浮动窗口样式选项未能正常重置的问题", @@ -47,7 +48,7 @@ "images 部分相关方法出现异常时 oneShot 标记功能失效的问题 _[`issue #372`](http://issues.autojs6.com/372)_", "images 部分相关方法可能引发内存泄露的问题 _[`issue #372`](http://issues.autojs6.com/372)_", "ocr 部分重载方法可能无法正常使用的问题", - "ocr.detect 方法获得的结果可能与 ocr.mode 不匹配的问题", + "ocr.detect 方法获得的结果可能与 ocr.mode 不匹配的问题 _[`issue #468`](http://issues.autojs6.com/468)_", "Android 10 UiObject#child 方法可能出现 ArrayIndexOutOfBoundsException 异常的问题 _[`issue #416`](http://issues.autojs6.com/416)_", "运行项目时 project.json 配置参数无法正常解析的问题", "项目配置文件中构建版本号或构建时间出现较大数字时可能导致应用崩溃的问题", @@ -66,6 +67,7 @@ "ui.statusBarHeight 属性 (getter) 增强一定程度的兼容性", "console.log 等方法打印全局对象 (images, app, ocr 等) 时支持显示详细信息", "android.graphics.Paint#setColor 支持正常解析 ColorInt/ColorHex/ColorName 等颜色参数", + "app.launchDual/startDualActivity 等方法提升执行效率并增强兼容性", "内置模块相关方法实参类型的异常消息增加类型摘要信息", "控制台浮动窗口倒计时起始值由 6 秒增加到 9 秒", "控制台浮动窗口内部实现进行无锁化及队列化处理以提升其参数设置效率与成功率", diff --git a/app/src/main/java/org/autojs/autojs/runtime/api/augment/app/App.kt b/app/src/main/java/org/autojs/autojs/runtime/api/augment/app/App.kt index eb8f2043..c219d502 100644 --- a/app/src/main/java/org/autojs/autojs/runtime/api/augment/app/App.kt +++ b/app/src/main/java/org/autojs/autojs/runtime/api/augment/app/App.kt @@ -15,6 +15,8 @@ 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.extension.ScriptableExtensions.defineProp import org.autojs.autojs.extension.ScriptableExtensions.deleteProp import org.autojs.autojs.extension.ScriptableExtensions.prop @@ -22,10 +24,14 @@ import org.autojs.autojs.extension.ScriptableObjectExtensions.inquire import org.autojs.autojs.external.receiver.BaseBroadcastReceiver import org.autojs.autojs.ipc.LayoutInspectEventBus import org.autojs.autojs.runtime.ScriptRuntime +import org.autojs.autojs.runtime.api.AbstractShell import org.autojs.autojs.runtime.api.AppUtils.Companion.ActivityShortForm import org.autojs.autojs.runtime.api.AppUtils.Companion.BroadcastShortForm import org.autojs.autojs.runtime.api.WrappedShizuku import org.autojs.autojs.runtime.api.augment.Augmentable +import org.autojs.autojs.runtime.api.augment.app.App.Companion.ShellAction.Companion.toFallbackShellAction +import org.autojs.autojs.runtime.api.augment.app.App.Companion.ShellAction.Companion.toRootShellAction +import org.autojs.autojs.runtime.api.augment.app.App.Companion.ShellAction.Companion.toShizukuShellAction import org.autojs.autojs.runtime.api.augment.shell.Shell import org.autojs.autojs.runtime.exception.ShouldNeverHappenException import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException @@ -82,6 +88,8 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { ::launchDualSettings.name to AS_GLOBAL, ::openAppSetting.name to AS_GLOBAL, ::openDualAppSetting.name to AS_GLOBAL, + ::isInstalled.name to AS_GLOBAL, + ::isDualInstalled.name to AS_GLOBAL, ::uninstall.name to AS_GLOBAL, ::uninstallDual.name to AS_GLOBAL, ::viewFile.name, @@ -140,14 +148,14 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { options is NativeObject -> obj.configure(scriptRuntime, options).let { configuredIntent -> when { checkDualProperty(options) -> startDualActivity(scriptRuntime, args) - checkRootProperty(options) && RootUtils.isRootAvailable() -> { - val tmpIntent = configuredIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - Shell.execCommand(scriptRuntime, arrayOf("am start ${intentToShellRhino(tmpIntent)}", /* withRoot = */ true)).throwIfError() - } - checkShizukuProperty(options) && WrappedShizuku.isOperational() -> { + checkShizukuProperty(options) -> { val tmpIntent = configuredIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) WrappedShizuku.execCommand("am start ${intentToShellRhino(tmpIntent)}").throwIfError() } + checkRootProperty(options) -> { + val tmpIntent = configuredIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + Shell.execCommand(scriptRuntime, arrayOf("am start ${intentToShellRhino(tmpIntent)}", /* withRoot = */ true)).throwIfError() + } else -> startActivityWithGlobalContext(configuredIntent) } } @@ -165,15 +173,15 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { } when { checkDualProperty(opt) -> startDualActivity(scriptRuntime, args) - checkRootProperty(opt) && RootUtils.isRootAvailable() -> { - val tmpIntent = intentRhinoWithRuntime(scriptRuntime, opt).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } - Shell.execCommand(scriptRuntime, arrayOf("am start ${intentToShellRhino(tmpIntent)}", /* withRoot = */ true)).throwIfError() - } - checkShizukuProperty(opt) && WrappedShizuku.isOperational() -> { + checkShizukuProperty(opt) -> { val tmpIntent = intentRhinoWithRuntime(scriptRuntime, opt).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } val intentCommand = intentToShellRhino(tmpIntent) WrappedShizuku.execCommand("am start $intentCommand").throwIfError() } + checkRootProperty(opt) -> { + val tmpIntent = intentRhinoWithRuntime(scriptRuntime, opt).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } + Shell.execCommand(scriptRuntime, arrayOf("am start ${intentToShellRhino(tmpIntent)}", /* withRoot = */ true)).throwIfError() + } else -> startActivityWithGlobalContext(scriptRuntime, opt) } } @@ -775,12 +783,13 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { @RhinoRuntimeFunctionInterface fun kill(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLength(args, 1) { argList -> val packageName = getPackageName(scriptRuntime, argList) ?: return@ensureArgumentsLength false - val command = "am force-stop $packageName" - when { - RootUtils.isRootAvailable() -> Shell.execCommand(scriptRuntime, arrayOf(command, /* withRoot = */ true)) - WrappedShizuku.isOperational() -> WrappedShizuku.execCommand(command) - else -> Shell.execCommand(scriptRuntime, arrayOf(command, /* withRoot = */ false)) - }.code == 0 + with("am force-stop $packageName") { + listOf( + toShizukuShellAction(), + toRootShellAction(scriptRuntime), + toFallbackShellAction(scriptRuntime), + ).first { it.condition() }.execute().code == 0 + } } // @Hint by SuperMonster003 on Oct 30, 2024. @@ -792,7 +801,30 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { fun killDual(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsLength(args, 1) { argList -> val packageName = getPackageName(scriptRuntime, argList) ?: return@ensureArgumentsLength false val command = "am force-stop $packageName" - runCatching { execCommandForDualUser(scriptRuntime, command, RootUtils.isRootAvailable(), WrappedShizuku.isOperational()) }.isSuccess + runCatching { execCommandForDualUser(scriptRuntime, command) }.isSuccess + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun isInstalled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsOnlyOne(args) { o -> + val packageName = getPackageName(scriptRuntime, arrayOf(o)) ?: return@ensureArgumentsOnlyOne false + scriptRuntime.app.isInstalled(packageName) + } + + @JvmStatic + @RhinoRuntimeFunctionInterface + fun isDualInstalled(scriptRuntime: ScriptRuntime, args: Array): Boolean = ensureArgumentsOnlyOne(args) { o -> + val packageName = getPackageName(scriptRuntime, arrayOf(o)) ?: return@ensureArgumentsOnlyOne false + isDualInstalledInternal(scriptRuntime, packageName) + } + + private fun isDualInstalledInternal(scriptRuntime: ScriptRuntime, packageName: String): Boolean { + val command = "cmd package list packages %USER_ID% $packageName" + return runCatching { + execCommandForDualUser(scriptRuntime, command)?.let { result -> + result.code == 0 && result.result.contains("package:$packageName") + } ?: false + }.getOrElse { false } } private fun parseClassName(o: NativeObject): String { @@ -890,16 +922,16 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { val intent = intentRhinoWithRuntime(scriptRuntime, o).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) } val command = "am start ${intentToShellRhino(intent)}" when (o) { - is NativeObject -> { - val withRoot = o.inquire("root", ::coerceBoolean, true) - val withShizuku = o.inquire("shizuku", ::coerceBoolean, true) - execCommandForDualUser(scriptRuntime, command, withRoot, withShizuku) - } + is NativeObject -> execCommandForDualUser(scriptRuntime, command, o) else -> execCommandForDualUser(scriptRuntime, command) } } - private fun execCommandForDualUser(scriptRuntime: ScriptRuntime, command: String, withRoot: Boolean = true, withShizuku: Boolean = true) { + private fun execCommandForDualUser( + scriptRuntime: ScriptRuntime, + command: String, + options: NativeObject? = null, + ): AbstractShell.Result? { val userManager = globalContext.getSystemService(Class.forName("android.os.UserManager")) val getUserProfilesMethod = userManager.javaClass.getDeclaredMethod("getUserProfiles") @@ -911,19 +943,46 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { val userHandleClass = Class.forName("android.os.UserHandle") val getIdentifierMethod = userHandleClass.getDeclaredMethod("getIdentifier") - val processUserIdentifier = getIdentifierMethod.invoke(processUserHandle) as Int + val currentUserId = getIdentifierMethod.invoke(processUserHandle) as Int + var lastResult: AbstractShell.Result? = null + + @Suppress("LocalVariableName") for (userHandle in userProfiles) { - val currentUserIdentifier = getIdentifierMethod.invoke(userHandle) as Int - if (currentUserIdentifier != processUserIdentifier) { - val niceCommand = "$command --user $currentUserIdentifier" - when { - withRoot && RootUtils.isRootAvailable() -> Shell.execCommand(scriptRuntime, arrayOf(niceCommand, /* withRoot = */ true)) - withShizuku && WrappedShizuku.isOperational() -> WrappedShizuku.execCommand(niceCommand) - else -> Shell.execCommand(scriptRuntime, arrayOf(niceCommand, /* withRoot = */ false)) - }.throwIfError() + val uid = getIdentifierMethod.invoke(userHandle) as Int + if (uid == currentUserId) continue + + val cmd = when { + command.contains("%USER_ID%") -> command.replace("%USER_ID%", "--user $uid") + Regex("""\s--user\s+\d+""").containsMatchIn(command) -> command + else -> "$command --user $uid" + } + + val shizuku = cmd.toShizukuShellAction() + val root = cmd.toRootShellAction(scriptRuntime) + val fallback = cmd.toFallbackShellAction(scriptRuntime) + + val SRF = listOf(shizuku, root, fallback) + val RSF = listOf(root, shizuku, fallback) + + val actions = when (options) { + is NativeObject -> { + val preferShizuku = options.prop("shizuku").takeUnless { it.isJsNullish() }?.let { coerceBoolean(it) } + val preferRoot = options.prop("root").takeUnless { it.isJsNullish() }?.let { coerceBoolean(it) } + when (preferShizuku) { + null -> if (preferRoot == true) RSF else SRF + true -> SRF + else -> if (preferRoot == false) SRF else RSF + } + } + else -> SRF + } + + if (actions.first { it.condition() }.execute().also { lastResult = it }.code == 0) { + break } } + return lastResult?.apply { throwIfError() } } private fun getAppByAliasRhino(o: Any?): PresetApp? { @@ -953,11 +1012,11 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { }) } - private fun checkRootProperty(o: NativeObject) = o.inquire("root", ::coerceBoolean, false) + private fun checkDualProperty(o: NativeObject) = o.inquire("dual", ::coerceBoolean, false) private fun checkShizukuProperty(o: NativeObject) = o.inquire("shizuku", ::coerceBoolean, false) && WrappedShizuku.isOperational() - private fun checkDualProperty(o: NativeObject) = o.inquire("dual", ::coerceBoolean, false) + private fun checkRootProperty(o: NativeObject) = o.inquire("root", ::coerceBoolean, false) && RootUtils.isRootAvailable() private fun Intent.configure(scriptRuntime: ScriptRuntime, o: NativeObject): Intent { val intent = this @@ -1055,6 +1114,18 @@ class App(scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) { return intent } + private data class ShellAction(val cmd: String, val condition: () -> Boolean, private val action: (cmd: String) -> AbstractShell.Result) { + + fun execute() = action(cmd) + + companion object { + fun String.toShizukuShellAction() = ShellAction(this, { WrappedShizuku.isOperational() }, { WrappedShizuku.execCommand(it) }) + fun String.toRootShellAction(scriptRuntime: ScriptRuntime) = ShellAction(this, { RootUtils.isRootAvailable() }, { Shell.execCommand(scriptRuntime, arrayOf(it, /* withRoot = */ true)) }) + fun String.toFallbackShellAction(scriptRuntime: ScriptRuntime) = ShellAction(this, { true }, { Shell.execCommand(scriptRuntime, arrayOf(it, /* withRoot = */ false)) }) + } + + } + } } \ No newline at end of file diff --git a/app/src/main/java/org/autojs/autojs/util/RootUtils.java b/app/src/main/java/org/autojs/autojs/util/RootUtils.java index ccb0d3c8..484a8b44 100644 --- a/app/src/main/java/org/autojs/autojs/util/RootUtils.java +++ b/app/src/main/java/org/autojs/autojs/util/RootUtils.java @@ -1,26 +1,132 @@ package org.autojs.autojs.util; +import androidx.annotation.NonNull; +import com.stericson.RootShell.RootShell; +import org.autojs.autojs.core.pref.Pref; +import org.autojs.autojs6.R; + +import java.io.File; +import java.text.MessageFormat; +import java.util.HashSet; +import java.util.Set; + import static org.autojs.autojs.util.StringUtils.getStringByLanguageTag; import static org.autojs.autojs.util.StringUtils.key; import static org.autojs.autojs.util.StringUtils.str; -import androidx.annotation.NonNull; - -import com.stericson.RootShell.RootShell; - -import org.autojs.autojs.core.pref.Pref; -import org.autojs.autojs6.R; - -import java.text.MessageFormat; - /** * Created by Stardust on Jan 26, 2018. * Modified by SuperMonster003 as of March 10, 2022. */ public class RootUtils { + private static final String[] COMMON_SU_PATHS = new String[]{ + "/system/xbin/su", + "/system/bin/su", + "/vendor/bin/su", + "/system_ext/bin/su", + "/odm/bin/su", + "/sbin/su", + "/su/bin/su", + "/system/su" + }; private static String runtimeOverriddenRootMode = RootMode.AUTO_DETECT.key; + public static void setRootMode(RootMode mode, boolean isWriteInfoPreference) { + if (isWriteInfoPreference) { + Pref.setRootMode(mode); + } else { + runtimeOverriddenRootMode = mode.key; + } + } + + public static void resetRuntimeOverriddenRootModeState() { + runtimeOverriddenRootMode = RootMode.AUTO_DETECT.key; + } + + public static RootMode getRootMode() { + if (runtimeOverriddenRootMode.equals(RootMode.AUTO_DETECT.key)) { + return Pref.getRootMode(); + } + return RootMode.getRootMode(runtimeOverriddenRootMode); + } + + public static void setRootMode(RootMode mode) { + setRootMode(mode, false); + } + + public static boolean isRootAvailable() { + RootMode rootMode = getRootMode(); + return rootMode == RootMode.AUTO_DETECT + ? isSuPresentFast() || getRootStateWithRootShell() + : rootMode == RootMode.FORCE_ROOT; + } + + private static boolean isSuPresentFast() { + try { + // 1. Check common su paths. + // zh-CN: 1. 检查常见 su 路径. + for (String path : COMMON_SU_PATHS) { + if (isExecutableFile(path)) { + return true; + } + } + + // 2. Check su in PATH environment. + // zh-CN: 2. 检查 PATH 环境中的 su. + String envPath = System.getenv("PATH"); + if (envPath != null && !envPath.isEmpty()) { + String[] paths = envPath.split(":"); + Set uniq = new HashSet<>(); + for (String p : paths) { + if (p == null || p.isEmpty()) continue; + if (!uniq.add(p)) continue; + String su = (p.endsWith("/") ? p : (p + "/")) + "su"; + if (isExecutableFile(su)) { + return true; + } + } + } + } catch (Throwable e) { + e.printStackTrace(); + } + return false; + } + + private static boolean isExecutableFile(String absolutePath) { + File f = new File(absolutePath); + if (!(f.exists() && f.isFile())) return false; + + // Quick check using File.canExecute(). + // zh-CN: 先用 File.canExecute() 快速判定. + if (f.canExecute()) { + return true; + } + + // Try an equivalent check using Os.access (using reflection to avoid class resolution issues). + // zh-CN: 再尝试一次 Os.access 的等效判定 (使用反射避免类解析问题). + try { + Class osClass = Class.forName("android.system.Os"); + Class osConstantsClass = Class.forName("android.system.OsConstants"); + int xOk = osConstantsClass.getField("X_OK").getInt(null); + osClass.getMethod("access", String.class, Integer.TYPE).invoke(null, absolutePath, xOk); + return true; + } catch (Throwable ignored) { + // Reflection failed or class/method/field not found, consider as non-executable. + // zh-CN: 反射失败或无此类/方法/字段, 视为不可执行. + } + return false; + } + + private static boolean getRootStateWithRootShell() { + try { + return RootShell.isRootAvailable(); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + public enum RootMode { FORCE_ROOT(key(R.string.key_root_mode_force_root), getStringByLanguageTag(R.string.entry_root_mode_force_root, "en")), FORCE_NON_ROOT(key(R.string.key_root_mode_force_non_root), getStringByLanguageTag(R.string.entry_root_mode_force_non_root, "en")), @@ -50,43 +156,5 @@ public class RootUtils { } - public static void setRootMode(RootMode mode) { - setRootMode(mode, false); - } - - public static void setRootMode(RootMode mode, boolean isWriteInfoPreference) { - if (isWriteInfoPreference) { - Pref.setRootMode(mode); - } else { - runtimeOverriddenRootMode = mode.key; - } - } - - public static void resetRuntimeOverriddenRootModeState() { - runtimeOverriddenRootMode = RootMode.AUTO_DETECT.key; - } - - public static RootMode getRootMode() { - if (runtimeOverriddenRootMode.equals(RootMode.AUTO_DETECT.key)) { - return Pref.getRootMode(); - } - return RootMode.getRootMode(runtimeOverriddenRootMode); - } - - public static boolean isRootAvailable() { - RootMode rootMode = getRootMode(); - return rootMode == RootMode.AUTO_DETECT - ? getRootStateWithRootShell() - : rootMode == RootMode.FORCE_ROOT; - } - - private static boolean getRootStateWithRootShell() { - try { - return RootShell.isRootAvailable(); - } catch (Exception e) { - e.printStackTrace(); - return false; - } - } } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index b8701ad6..533a953c 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -932,7 +932,7 @@ نتيجة قم بإلغاء الوصول إلى AutoJs6 في تطبيق Shizuku تغليف الأنواع البدائية في Java - فحص الجذر مجموعة القوة + التحقق من صلاحيات الروت يجري على البطارية تغيرت على التمهيد diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 9e1a99d4..6d04d89d 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -927,7 +927,7 @@ Result Revoke AutoJs6 access in Shizuku app Java primitive wrapping - Force set root check + Root access check Run On battery changed On booted diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index fe97cdc6..a24e66eb 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -930,7 +930,7 @@ Resultado Revocar privilegios de AutoJs6 en una aplicación Shizuku Envoltorio de primitivos de Java - Forzar la comprobación de root + Comprobación de acceso root Ejecutar Al cambiar la batería Al arrancar diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 41fc03db..f926a325 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -930,7 +930,7 @@ Résultat Révoquer les privilèges AutoJs6 dans une application Shizuku Encapsulation des types primitifs Java - Force set root check + Vérification de l\'accès root Exécuter Sur changement de batterie Sur démarrage diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index a648c628..2f40aca9 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -931,7 +931,7 @@ 結果 Shizuku アプリケーションで AutoJs6 権限を取り消す Java プリミティブ型のラップ - 強制的に root にするチェック + Root 権限の確認 実行 バッテリー交換時 起動したとき diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 196f3ccc..4e865d76 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -932,7 +932,7 @@ 결과 Shizuku 애플리케이션에서 AutoJs6 권한 취소하기 Java 원시 타입 래핑 - 강제 설정 루트 검사 + 루트 권한 확인 운영 배터리가 변경되었습니다 부팅 diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index fa8ed5e5..ecb6cf1a 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -930,7 +930,7 @@ Результат Отмена привилегий AutoJs6 в приложении Shizuku Обёртка примитивов Java - Проверка принудительной установки root + Проверка прав root Запустить При смене батареи При загрузке diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 5d0195b6..91029ae4 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -928,7 +928,7 @@ 結果 在 Shizuku 應用中撤銷 AutoJs6 權限 Java 原始類型包裝 - 強制 Root 權限檢查 + Root 權限檢查 運行 電量變化時 開機時 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 71f02365..79e2b9f3 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -928,7 +928,7 @@ 結果 在 Shizuku 應用中撤銷 AutoJs6 許可權 Java 原始型別包裝 - 強制 Root 許可權檢查 + Root 許可權檢查 執行 電量變化時 開機時 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 6fb6de44..45ca0450 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -928,7 +928,7 @@ 结果 在 Shizuku 应用中撤销 AutoJs6 权限 Java 原始类型包装 - 强制 Root 权限检查 + Root 权限检查 运行 电量变化时 开机时 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b11dccfe..b002b3fc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1181,7 +1181,7 @@ Result Revoke AutoJs6 access in Shizuku app Java primitive wrapping - Force set root check + Root access check Run On battery changed On booted