6.7.0 - Alpha10 - autojs.(restart/exit) 方法支持应用重启时自动运行其参数指定的脚本 (issue #460)

This commit is contained in:
SuperMonster003
2025-11-03 13:19:47 +08:00
parent 3439c0c224
commit bc2f580e1c
19 changed files with 279 additions and 87 deletions

View File

@@ -1,7 +1,7 @@
{ {
"$data": { "$data": {
"v6.7.0": { "v6.7.0": {
"released_date": "2025/11/01", "released_date": "2025/11/02",
"feature": [ "feature": [
"cvt 模块, 用于数据单位转换 (参阅 项目文档 > [单位转换](https://docs.autojs6.com/#/cvt))", "cvt 模块, 用于数据单位转换 (参阅 项目文档 > [单位转换](https://docs.autojs6.com/#/cvt))",
"fmt 模块, 用于数据格式化 (参阅 项目文档 > [格式化](https://docs.autojs6.com/#/fmt))", "fmt 模块, 用于数据格式化 (参阅 项目文档 > [格式化](https://docs.autojs6.com/#/fmt))",
@@ -17,7 +17,7 @@
"http 模块请求相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_", "http 模块请求相关方法支持不安全选项参数 (isInsecure/insecure), 用于忽略证书相关异常 _[`issue #417`](http://issues.autojs6.com/417)_",
"http 模块请求相关方法支持 options.client 选项, 用于配置 OkHttpClient.Builder (如 followRedirects 等) _[`issue #454`](http://issues.autojs6.com/454)_", "http 模块请求相关方法支持 options.client 选项, 用于配置 OkHttpClient.Builder (如 followRedirects 等) _[`issue #454`](http://issues.autojs6.com/454)_",
"runtime.(set/is)JavaPrimitiveWrap 方法, 用于设置或获取 Java 原始类型包装策略 _[`issue #435`](http://issues.autojs6.com/435)_", "runtime.(set/is)JavaPrimitiveWrap 方法, 用于设置或获取 Java 原始类型包装策略 _[`issue #435`](http://issues.autojs6.com/435)_",
"autojs.(restart/exit) 方法, 用于重启或退出 AutoJs6 应用", "autojs.(restart/exit) 方法, 用于重启或退出 AutoJs6 应用, 并支持应用重启时自动运行其参数指定的脚本 _[`issue #460`](http://issues.autojs6.com/460)_",
"UiObject#isShifted 方法, 用于检测控件位置变化", "UiObject#isShifted 方法, 用于检测控件位置变化",
"structuredClone 全局方法, 用于深拷贝 JavaScript 对象 (参阅 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/structuredClone))", "structuredClone 全局方法, 用于深拷贝 JavaScript 对象 (参阅 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/structuredClone))",
"设置页面增加 \"Java 原始类型包装\" 设置选项 _[`issue #435`](http://issues.autojs6.com/435)_", "设置页面增加 \"Java 原始类型包装\" 设置选项 _[`issue #435`](http://issues.autojs6.com/435)_",

View File

@@ -5,6 +5,7 @@ import android.content.SharedPreferences
import android.content.SharedPreferences.OnSharedPreferenceChangeListener import android.content.SharedPreferences.OnSharedPreferenceChangeListener
import android.content.res.Resources import android.content.res.Resources
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.core.content.edit
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.gson.Gson import com.google.gson.Gson
import org.autojs.autojs.App.Companion.app import org.autojs.autojs.App.Companion.app
@@ -200,12 +201,12 @@ object Pref {
fun refreshLastUpdatesAutoCheckedTimestamp() = updateTimestamp(R.string.key_last_updates_auto_checked) fun refreshLastUpdatesAutoCheckedTimestamp() = updateTimestamp(R.string.key_last_updates_auto_checked)
@JvmStatic @JvmStatic
fun clearUpdatesCheckedStates() = sPref.edit() fun clearUpdatesCheckedStates() = sPref.edit {
.remove(key(R.string.key_last_no_newer_updates)) remove(key(R.string.key_last_no_newer_updates))
.remove(key(R.string.key_last_updates_postponed)) .remove(key(R.string.key_last_updates_postponed))
.remove(key(R.string.key_last_updates_checked)) .remove(key(R.string.key_last_updates_checked))
.remove(key(R.string.key_last_updates_auto_checked)) .remove(key(R.string.key_last_updates_auto_checked))
.apply() }
@JvmStatic @JvmStatic
fun shouldStartA11yServiceWithRoot() = getBoolean( fun shouldStartA11yServiceWithRoot() = getBoolean(
@@ -240,7 +241,10 @@ object Pref {
fun putString(@KeyRes keyRes: Int, value: String?) = putString(key(keyRes), value) fun putString(@KeyRes keyRes: Int, value: String?) = putString(key(keyRes), value)
@JvmStatic @JvmStatic
fun putString(key: String, value: String?) = sPref.edit().putString(key, value).apply() fun putString(key: String, value: String?) = sPref.edit { putString(key, value) }
@JvmStatic
fun putStringSync(key: String, value: String?) = sPref.edit(commit = true) { putString(key, value) }
@JvmStatic @JvmStatic
fun getString(@KeyRes keyRes: Int, @KeyRes defKeyRes: Int): String = sPref.getString(key(keyRes), key(defKeyRes))!! fun getString(@KeyRes keyRes: Int, @KeyRes defKeyRes: Int): String = sPref.getString(key(keyRes), key(defKeyRes))!!
@@ -264,10 +268,10 @@ object Pref {
fun putBooleanSync(@KeyRes keyRes: Int, value: Boolean) = putBooleanSync(key(keyRes), value) fun putBooleanSync(@KeyRes keyRes: Int, value: Boolean) = putBooleanSync(key(keyRes), value)
@JvmStatic @JvmStatic
fun putBoolean(key: String, value: Boolean) = sPref.edit().putBoolean(key, value).apply() fun putBoolean(key: String, value: Boolean) = sPref.edit { putBoolean(key, value) }
@JvmStatic @JvmStatic
fun putBooleanSync(key: String, value: Boolean) = sPref.edit().putBoolean(key, value).commit() fun putBooleanSync(key: String, value: Boolean) = sPref.edit(commit = true) { putBoolean(key, value) }
@JvmStatic @JvmStatic
fun getBoolean(@KeyRes keyRes: Int, defValue: Boolean) = getBoolean(key(keyRes), defValue) fun getBoolean(@KeyRes keyRes: Int, defValue: Boolean) = getBoolean(key(keyRes), defValue)
@@ -282,16 +286,16 @@ object Pref {
fun putInt(@KeyRes keyRes: Int, value: Int) = putInt(key(keyRes), value) fun putInt(@KeyRes keyRes: Int, value: Int) = putInt(key(keyRes), value)
@JvmStatic @JvmStatic
fun putInt(key: String, value: Int) = sPref.edit().putInt(key, value).apply() fun putInt(key: String, value: Int) = sPref.edit { putInt(key, value) }
@JvmStatic @JvmStatic
fun putIntSync(key: String, value: Int) = sPref.edit().putInt(key, value).commit() fun putIntSync(key: String, value: Int) = sPref.edit(commit = true) { putInt(key, value) }
@JvmStatic @JvmStatic
fun putFloat(key: String, value: Float) = sPref.edit().putFloat(key, value).apply() fun putFloat(key: String, value: Float) = sPref.edit { putFloat(key, value) }
@JvmStatic @JvmStatic
fun putFloatSync(key: String, value: Float) = sPref.edit().putFloat(key, value).commit() fun putFloatSync(key: String, value: Float) = sPref.edit(commit = true) { putFloat(key, value) }
@JvmStatic @JvmStatic
fun getInt(@KeyRes keyRes: Int, defValue: Int): Int = getInt(key(keyRes), defValue) fun getInt(@KeyRes keyRes: Int, defValue: Int): Int = getInt(key(keyRes), defValue)
@@ -303,13 +307,13 @@ object Pref {
fun getFloat(key: String, defValue: Float): Float = sPref.getFloat(key, defValue) fun getFloat(key: String, defValue: Float): Float = sPref.getFloat(key, defValue)
@JvmStatic @JvmStatic
fun putLong(@KeyRes keyRes: Int, value: Long) = sPref.edit().putLong(key(keyRes), value).apply() fun putLong(@KeyRes keyRes: Int, value: Long) = sPref.edit { putLong(key(keyRes), value) }
@JvmStatic @JvmStatic
fun getLong(@KeyRes keyRes: Int, defValue: Long) = sPref.getLong(key(keyRes), defValue) fun getLong(@KeyRes keyRes: Int, defValue: Long) = sPref.getLong(key(keyRes), defValue)
@JvmStatic @JvmStatic
fun putStringSet(@KeyRes keyRes: Int, values: MutableSet<String>) = sPref.edit().putStringSet(key(keyRes), values).apply() fun putStringSet(@KeyRes keyRes: Int, values: MutableSet<String>) = sPref.edit { putStringSet(key(keyRes), values) }
@JvmStatic @JvmStatic
fun getStringSet(@KeyRes keyRes: Int, defValues: MutableSet<String>?): MutableSet<String>? = sPref.getStringSet(key(keyRes), defValues) fun getStringSet(@KeyRes keyRes: Int, defValues: MutableSet<String>?): MutableSet<String>? = sPref.getStringSet(key(keyRes), defValues)
@@ -324,7 +328,7 @@ object Pref {
fun containsKey(key: String): Boolean = sPref.all.containsKey(key) fun containsKey(key: String): Boolean = sPref.all.containsKey(key)
@JvmStatic @JvmStatic
fun remove(key: String) = sPref.edit().remove(key).apply() fun remove(key: String) = sPref.edit { remove(key) }
@JvmStatic @JvmStatic
fun getLinkedHashSet(@KeyRes keyRes: Int): LinkedHashSet<String> = when { fun getLinkedHashSet(@KeyRes keyRes: Int): LinkedHashSet<String> = when {

View File

@@ -94,8 +94,8 @@ class DynamicBroadcastReceivers(private val context: Context) {
} }
mReceiverRegistries.clear() mReceiverRegistries.clear()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.unregisterReceiver(mDefaultActionReceiver) runCatching { context.unregisterReceiver(mDefaultActionReceiver) }
context.unregisterReceiver(mPackageActionReceiver) runCatching { context.unregisterReceiver(mPackageActionReceiver) }
} }
} }

View File

@@ -4,9 +4,13 @@ import android.Manifest
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.provider.Settings import android.provider.Settings
import android.provider.Settings.System import android.provider.Settings.System
import org.autojs.autojs.annotation.RhinoSingletonFunctionInterface import org.autojs.autojs.annotation.RhinoRuntimeFunctionInterface
import org.autojs.autojs.extension.AnyExtensions.isJsNullish import org.autojs.autojs.extension.AnyExtensions.isJsNullish
import org.autojs.autojs.extension.AnyExtensions.isJsString
import org.autojs.autojs.extension.AnyExtensions.jsBrief
import org.autojs.autojs.extension.FlexibleArray 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.defineProp
import org.autojs.autojs.extension.ScriptableExtensions.prop import org.autojs.autojs.extension.ScriptableExtensions.prop
import org.autojs.autojs.rhino.ProxyObject import org.autojs.autojs.rhino.ProxyObject
@@ -17,6 +21,7 @@ import org.autojs.autojs.runtime.api.augment.Augmentable
import org.autojs.autojs.runtime.api.augment.util.Util.checkStringArgument import org.autojs.autojs.runtime.api.augment.util.Util.checkStringArgument
import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException import org.autojs.autojs.runtime.exception.WrappedIllegalArgumentException
import org.autojs.autojs.theme.ThemeColorManager import org.autojs.autojs.theme.ThemeColorManager
import org.autojs.autojs.util.FileUtils
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.RhinoUtils.NOT_CONSTRUCTABLE import org.autojs.autojs.util.RhinoUtils.NOT_CONSTRUCTABLE
import org.autojs.autojs.util.RhinoUtils.UNDEFINED import org.autojs.autojs.util.RhinoUtils.UNDEFINED
@@ -24,7 +29,6 @@ import org.autojs.autojs.util.RhinoUtils.coerceIntNumber
import org.autojs.autojs.util.RhinoUtils.coerceString import org.autojs.autojs.util.RhinoUtils.coerceString
import org.autojs.autojs.util.RhinoUtils.newBaseFunction import org.autojs.autojs.util.RhinoUtils.newBaseFunction
import org.autojs.autojs.util.RhinoUtils.newNativeObject import org.autojs.autojs.util.RhinoUtils.newNativeObject
import org.autojs.autojs.util.RhinoUtils.undefined
import org.autojs.autojs.util.RootUtils import org.autojs.autojs.util.RootUtils
import org.autojs.autojs.util.RootUtils.RootMode import org.autojs.autojs.util.RootUtils.RootMode
import org.autojs.autojs6.BuildConfig import org.autojs.autojs6.BuildConfig
@@ -38,7 +42,8 @@ import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
import android.content.Context as AndroidContext import android.content.Context as AndroidContext
class Autojs(private val scriptRuntime: ScriptRuntime) : Augmentable() { @Suppress("unused")
class Autojs(private val scriptRuntime: ScriptRuntime) : Augmentable(scriptRuntime) {
private val mCachedR = mutableMapOf<String, NativeObject>() private val mCachedR = mutableMapOf<String, NativeObject>()
@@ -103,32 +108,32 @@ class Autojs(private val scriptRuntime: ScriptRuntime) : Augmentable() {
companion object : FlexibleArray() { companion object : FlexibleArray() {
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun isScreenPortrait(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun isScreenPortrait(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
ScreenMetrics.isScreenPortrait ScreenMetrics.isScreenPortrait
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun isScreenLandscape(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun isScreenLandscape(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
ScreenMetrics.isScreenLandscape ScreenMetrics.isScreenLandscape
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun isRootAvailable(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun isRootAvailable(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
RootUtils.isRootAvailable() RootUtils.isRootAvailable()
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun getRootMode(args: Array<out Any?>): RootMode = ensureArgumentsIsEmpty(args) { fun getRootMode(scriptRuntime: ScriptRuntime, args: Array<out Any?>): RootMode = ensureArgumentsIsEmpty(args) {
RootUtils.getRootMode() RootUtils.getRootMode()
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun setRootMode(args: Array<out Any?>): Undefined = ensureArgumentsLengthInRange(args, 1..2) { fun setRootMode(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsLengthInRange(args, 1..2) {
val (modeArg, isWriteIntoPrefArg) = it val (modeArg, isWriteIntoPrefArg) = it
val isWriteIntoPref = when { val isWriteIntoPref = when {
@@ -173,45 +178,71 @@ class Autojs(private val scriptRuntime: ScriptRuntime) : Augmentable() {
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun canModifySystemSettings(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun canModifySystemSettings(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
System.canWrite(globalContext) System.canWrite(globalContext)
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun canWriteSecureSettings(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun canWriteSecureSettings(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
globalContext.checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) == PackageManager.PERMISSION_GRANTED globalContext.checkCallingOrSelfPermission(Manifest.permission.WRITE_SECURE_SETTINGS) == PackageManager.PERMISSION_GRANTED
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun canDisplayOverOtherApps(args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) { fun canDisplayOverOtherApps(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Boolean = ensureArgumentsIsEmpty(args) {
Settings.canDrawOverlays(globalContext) Settings.canDrawOverlays(globalContext)
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun getLanguage(args: Array<out Any?>): Locale = ensureArgumentsIsEmpty(args) { fun getLanguage(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Locale = ensureArgumentsIsEmpty(args) {
org.autojs.autojs.core.pref.Language.getPrefLanguage().locale org.autojs.autojs.core.pref.Language.getPrefLanguage().locale
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun getLanguageTag(args: Array<out Any?>): String = ensureArgumentsIsEmpty(args) { fun getLanguageTag(scriptRuntime: ScriptRuntime, args: Array<out Any?>): String = ensureArgumentsIsEmpty(args) {
getLanguage(arrayOf()).toLanguageTag() getLanguage(scriptRuntime, arrayOf()).toLanguageTag()
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun restart(args: Array<out Any?>): Undefined = ensureArgumentsIsEmpty(args) { fun restart(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsAtMost(args, 1) { argList ->
undefined { IntentUtils.App.restart(globalContext) } val (scripts) = argList
when {
scripts.isJsNullish() -> IntentUtils.App.restart(globalContext)
scripts.isJsString() -> IntentUtils.App.restart(globalContext, scriptsAfterRestart = listOf(coerceString(scripts).normalizeScriptName(scriptRuntime)))
scripts is List<*> -> IntentUtils.App.restart(globalContext, scriptsAfterRestart = scripts.normalizeScriptNames(scriptRuntime))
else -> throw WrappedIllegalArgumentException("Argument \"scriptsAfterRestart\" ${scripts.jsBrief()} is invalid for autojs.restart")
}
UNDEFINED
} }
@JvmStatic @JvmStatic
@RhinoSingletonFunctionInterface @RhinoRuntimeFunctionInterface
fun exit(args: Array<out Any?>): Undefined = ensureArgumentsIsEmpty(args) { fun exit(scriptRuntime: ScriptRuntime, args: Array<out Any?>): Undefined = ensureArgumentsAtMost(args, 1) { argList ->
undefined { IntentUtils.App.exit(globalContext) } val (scripts) = argList
when {
scripts.isJsNullish() -> IntentUtils.App.exit(globalContext)
scripts.isJsString() -> IntentUtils.App.exit(globalContext, scriptsAfterRestart = listOf(coerceString(scripts).normalizeScriptName(scriptRuntime)))
scripts is List<*> -> IntentUtils.App.exit(globalContext, scriptsAfterRestart = scripts.normalizeScriptNames(scriptRuntime))
else -> throw WrappedIllegalArgumentException("Argument \"scriptsAfterRestart\" ${scripts.jsBrief()} is invalid for autojs.exit")
}
UNDEFINED
}
private fun String.normalizeScriptName(scriptRuntime: ScriptRuntime): String {
val jsExt = FileUtils.TYPE.JAVASCRIPT.extensionWithDot
return when (val s = this.trim()) {
"@" -> scriptRuntime.engines.myEngine().source.fullPath
else -> s.let { if (it.endsWith(jsExt)) it else "$it$jsExt" }
}
}
private fun List<Any?>.normalizeScriptNames(scriptRuntime: ScriptRuntime): List<String> {
return this.mapNotNull { it?.toString()?.normalizeScriptName(scriptRuntime) }
} }
} }

View File

@@ -53,6 +53,7 @@ import org.autojs.autojs.ui.main.task.TaskManagerFragment
import org.autojs.autojs.ui.settings.PreferencesActivity import org.autojs.autojs.ui.settings.PreferencesActivity
import org.autojs.autojs.ui.widget.DrawerAutoClose import org.autojs.autojs.ui.widget.DrawerAutoClose
import org.autojs.autojs.ui.widget.SearchViewItem import org.autojs.autojs.ui.widget.SearchViewItem
import org.autojs.autojs.util.IntentUtils
import org.autojs.autojs.util.StringUtils.key import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs.util.UpdateUtils import org.autojs.autojs.util.UpdateUtils
import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils
@@ -147,6 +148,7 @@ class MainActivity : BaseActivity(), DelegateHost, HostActivity {
override fun onPostResume() { override fun onPostResume() {
recreateIfNeeded() recreateIfNeeded()
UpdateUtils.autoCheckForUpdatesIfNeededWithSnackbar(this) UpdateUtils.autoCheckForUpdatesIfNeededWithSnackbar(this)
IntentUtils.App.runAfterRestartIfNeeded(this)
super.onPostResume() super.onPostResume()
} }

View File

@@ -1,5 +1,6 @@
package org.autojs.autojs.util package org.autojs.autojs.util
import android.app.ActivityManager
import android.app.AlarmManager import android.app.AlarmManager
import android.app.PendingIntent import android.app.PendingIntent
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
@@ -7,7 +8,6 @@ import android.content.Context
import android.content.Context.ALARM_SERVICE import android.content.Context.ALARM_SERVICE
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Process
import android.os.SystemClock import android.os.SystemClock
import android.provider.OpenableColumns import android.provider.OpenableColumns
import android.provider.Settings import android.provider.Settings
@@ -15,19 +15,33 @@ import android.view.View
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.work.Constraints
import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.afollestad.materialdialogs.MaterialDialog
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.huaban.analysis.jieba.CharsDictionaryDatabase import com.huaban.analysis.jieba.CharsDictionaryDatabase
import com.huaban.analysis.jieba.PhrasesDictionaryDatabase import com.huaban.analysis.jieba.PhrasesDictionaryDatabase
import com.huaban.analysis.jieba.WordDictionaryDatabase import com.huaban.analysis.jieba.WordDictionaryDatabase
import org.autojs.autojs.AutoJs import org.autojs.autojs.AutoJs
import org.autojs.autojs.core.image.capture.ScreenCapturerForegroundService import org.autojs.autojs.core.image.capture.ScreenCapturerForegroundService
import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.execution.ExecutionConfig
import org.autojs.autojs.external.fileprovider.AppFileProvider import org.autojs.autojs.external.fileprovider.AppFileProvider
import org.autojs.autojs.model.script.ScriptFile
import org.autojs.autojs.runtime.api.Mime import org.autojs.autojs.runtime.api.Mime
import org.autojs.autojs.runtime.api.WrappedShizuku import org.autojs.autojs.runtime.api.WrappedShizuku
import org.autojs.autojs.ui.enhancedfloaty.FloatyService import org.autojs.autojs.ui.enhancedfloaty.FloatyService
import org.autojs.autojs.ui.floating.FloatyWindowManger import org.autojs.autojs.ui.floating.FloatyWindowManger
import org.autojs.autojs.util.StringUtils.key
import org.autojs.autojs6.R import org.autojs.autojs6.R
import java.io.File import java.io.File
import java.io.FileNotFoundException
import java.util.concurrent.TimeUnit
import kotlin.system.exitProcess
object IntentUtils { object IntentUtils {
@@ -330,39 +344,56 @@ object IntentUtils {
object App { object App {
private const val UNIQUE_REQUEST_CODE = 1001
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun restart(context: Context, extraActions: (() -> Unit)? = null) { fun restart(context: Context, beforeExit: (() -> Unit)? = null, scriptsAfterRestart: List<String>? = null) {
val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)?.apply { val launchIntent = getLaunchIntent(context)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK) ?: throw RuntimeException("Failed to create launch intent for AutoJs6")
}
when (context) { when (context) {
is AppCompatActivity -> { is AppCompatActivity -> {
context.startActivity(launchIntent) context.startActivity(launchIntent)
} }
else -> { else -> {
val pendingIntent = PendingIntent.getActivity( val delay = TimeUnit.MILLISECONDS.toMillis(300)
/* context = */ context, val triggerAtMillis = SystemClock.elapsedRealtime() + delay
/* requestCode = */ 1001, runCatching tryWithAlarmManager@{
/* intent = */ launchIntent, val pendingIntent = PendingIntent.getActivity(
/* flags = */ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE, /* context = */ context,
) /* requestCode = */ UNIQUE_REQUEST_CODE,
val am = context.getSystemService(ALARM_SERVICE) as AlarmManager /* intent = */ launchIntent,
am.setExactAndAllowWhileIdle( /* flags = */ PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE,
/* type = */ AlarmManager.ELAPSED_REALTIME, )
/* triggerAtMillis = */ SystemClock.elapsedRealtime() + 300L, val am = context.getSystemService(ALARM_SERVICE) as AlarmManager
/* operation = */ pendingIntent, am.cancel(pendingIntent)
) am.setExactAndAllowWhileIdle(
/* type = */ AlarmManager.ELAPSED_REALTIME,
/* triggerAtMillis = */ triggerAtMillis,
/* operation = */ pendingIntent,
)
}.onFailure tryWithWorkManager@{
it.printStackTrace()
val request = OneTimeWorkRequestBuilder<RestartWorker>()
.setInitialDelay(delay, TimeUnit.MILLISECONDS)
.setConstraints(Constraints.NONE)
.build()
WorkManager.getInstance(context).enqueueUniqueWork(
uniqueWorkName = "work-task-restart-autojs6",
existingWorkPolicy = ExistingWorkPolicy.REPLACE,
request = request,
)
}
} }
} }
exit(context, extraActions) exit(context, beforeExit, scriptsAfterRestart)
} }
@JvmStatic @JvmStatic
@JvmOverloads @JvmOverloads
fun exit(context: Context, extraActions: (() -> Unit)? = null) { fun exit(context: Context, beforeExit: (() -> Unit)? = null, scriptsAfterRestart: List<String>? = null) {
FloatyWindowManger.hideCircularMenuAndSaveState() FloatyWindowManger.hideCircularMenuAndSaveState()
FloatyService.stopService() FloatyService.stopService()
@@ -379,11 +410,121 @@ object IntentUtils {
WrappedShizuku.onDestroy() WrappedShizuku.onDestroy()
extraActions?.invoke() beforeExit?.invoke()
Process.killProcess(Process.myPid()) if (!scriptsAfterRestart.isNullOrEmpty()) {
Pref.putStringSync(key(R.string.key_scripts_after_app_restart), scriptsAfterRestart.joinToString("\n") { it.trim() })
}
finishAllAppTasksSafely(context)
exitProcess(0)
}
private fun getLaunchIntent(context: Context): Intent? {
val appCtx = context.applicationContext
val pkgName = appCtx.packageName
return appCtx.packageManager.getLaunchIntentForPackage(pkgName)?.apply {
setAction("$pkgName.action.RESTART_UNIQUE")
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK)
}
}
private fun finishAllAppTasksSafely(context: Context) {
// Use AppTask API to remove all task stacks of the current application (AutoJs6).
// zh-CN: 使用 AppTask API 移除当前应用 (AutoJs6) 的所有任务栈.
runCatching {
val am = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
am.appTasks?.forEach { it.runCatching { finishAndRemoveTask() } }
}
}
@JvmStatic
fun runAfterRestartIfNeeded(activity: AppCompatActivity) {
val prefKey = key(R.string.key_scripts_after_app_restart)
val prefValue = Pref.getStringOrNull(prefKey) ?: return
val scripts = prefValue.split("\n").filter { it.isNotBlank() }
val workingDir = WorkingDirectoryUtils.path
val scriptsFailedToRun = mutableMapOf<String, String>()
try {
activity.runOnUiThread {
scripts.forEach { script ->
try {
val file = script.toScriptFile(workingDir)
when {
file.exists() -> AutoJs.instance.scriptEngineService.execute(
/* source = */ ScriptFile(file.absolutePath).toSource(),
/* config = */ ExecutionConfig(workingDir),
)
else -> throw FileNotFoundException(file.absolutePath)
}
} catch (e: Exception) {
e.printStackTrace()
scriptsFailedToRun[script.toScriptFile(workingDir).absolutePath] = e.stackTraceToString()
}
}
}
} finally {
Pref.remove(prefKey)
}
if (scriptsFailedToRun.isEmpty()) return
val size = scriptsFailedToRun.size
val summary = activity.resources.getQuantityString(R.plurals.text_items_total_sum_with_colon, size, size)
val hint = activity.getString(R.string.text_click_item_to_show_details)
MaterialDialog.Builder(activity)
.title(R.string.error_failed_to_run_script)
.content("$summary\n\n$hint")
.items(scriptsFailedToRun.map { it.key })
.itemsCallback { _, _, _, text ->
val stackTrace = scriptsFailedToRun[text]
val content = "$text\n\n$stackTrace"
MaterialDialog.Builder(activity)
.title(R.string.text_details)
.content(content)
.neutralText(R.string.dialog_button_copy)
.neutralColorRes(R.color.dialog_button_hint)
.onNeutral { d, _ ->
ClipboardUtils.setClip(activity, content)
ViewUtils.showSnack(d.view, R.string.text_already_copied_to_clip, false)
}
.positiveText(R.string.dialog_button_dismiss)
.onPositive { d, _ -> d.dismiss() }
.autoDismiss(false)
.show()
}
.positiveText(R.string.dialog_button_dismiss)
.onPositive { dialog, _ -> dialog.dismiss() }
.cancelable(false)
.autoDismiss(false)
.show()
}
private fun String.toScriptFile(workingDir: String): File {
val file = when (this.endsWith(FileUtils.TYPE.JAVASCRIPT.extensionWithDot)) {
true -> this
else -> this + FileUtils.TYPE.JAVASCRIPT.extensionWithDot
}.let { File(it) }
return when {
file.exists() -> file
file.absolutePath.startsWith(workingDir.removeSuffix("/")) -> file
file.path.startsWith("\$remote/") -> file
else -> File(workingDir, file.path)
}
}
class RestartWorker(context: Context, params: WorkerParameters) : Worker(context, params) {
override fun doWork(): Result = when {
runCatching { applicationContext.startActivity(getLaunchIntent(applicationContext)) }.isSuccess -> {
Result.success()
}
else -> Result.failure()
}
} }
} }
} }

View File

@@ -1072,6 +1072,7 @@
<string name="description_timed_task_backend">يتحكم في الآلية الأساسية لتشغيل السكربتات بشكل مجدول.\n\nAlarmManager: عبر منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن أن تصبح المهام أقرب إلى التنفيذ في الوقت المحدد.\nWorkManager: صديق للنظام؛ مناسب للمهام غير الحرجة التي تتحمل بعض التأخير.\nJobScheduler: تنفيذ قديم محفوظ للتوافق؛ احتمال التأخير أعلى.</string> <string name="description_timed_task_backend">يتحكم في الآلية الأساسية لتشغيل السكربتات بشكل مجدول.\n\nAlarmManager: عبر منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن أن تصبح المهام أقرب إلى التنفيذ في الوقت المحدد.\nWorkManager: صديق للنظام؛ مناسب للمهام غير الحرجة التي تتحمل بعض التأخير.\nJobScheduler: تنفيذ قديم محفوظ للتوافق؛ احتمال التأخير أعلى.</string>
<string name="failed_to_go_to_access_settings">فشل فتح صفحة الإعدادات</string> <string name="failed_to_go_to_access_settings">فشل فتح صفحة الإعدادات</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">يُوصى بمنح إذن \"السماح بتعيين المنبّهات والتذكيرات\" لضمان تنفيذ المهام المجدولة بأكبر قدر ممكن من الدقة حتى عند إيقاف الشاشة أو في وضع السكون</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">يُوصى بمنح إذن \"السماح بتعيين المنبّهات والتذكيرات\" لضمان تنفيذ المهام المجدولة بأكبر قدر ممكن من الدقة حتى عند إيقاف الشاشة أو في وضع السكون</string>
<string name="description_timed_task_backend_more">حالات الاستخدام والفروقات:\n\n1) AlarmManager\nمناسب للمهام الحسّاسة للتوقيت، مثل [التذكيرات/السكربتات الدقيقة التوقيت/...].\nعلى Android 12+ ومع منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن التنفيذ بدقة أكبر حتى مع إيقاف الشاشة أو في وضع السكون.\nبدون الإذن قد يقلل النظام الدقة أو يؤخر التنفيذ.\n\n2) WorkManager\nمناسب للمهام التي لا تتطلب دقة زمنية صارمة مثل [مزامنة غير حرجة/تنظيف/إحصاءات/...].\nيتم الجدولة وفق [حالة البطارية/الشبكة/الشحن/سياسات السكون/...], وقد تتأخر المهام عند إيقاف الشاشة أو في وضع السكون.\nلا يضمن الدقة الزمنية لكنه يوفر مزايا في [إتمام موثوق/إعادة المحاولة عند الفشل/سلاسل المهام/إزالة التكرار].\n\n3) JobScheduler\nتنفيذ تاريخي لأغراض التوافق.\nفي إصدارات أندرويد الحديثة قد تحدث تأخيرات أكبر.\nلا يُنصح به إلا لاعتبارات التوافق.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">حالات الاستخدام والفروقات:\n\n1. AlarmManager\nمناسب للمهام الحسّاسة للتوقيت، مثل [التذكيرات/السكربتات الدقيقة التوقيت/...].\nعلى Android 12+ ومع منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن التنفيذ بدقة أكبر حتى مع إيقاف الشاشة أو في وضع السكون.\nبدون الإذن قد يقلل النظام الدقة أو يؤخر التنفيذ.\n\n2. WorkManager\nمناسب للمهام التي لا تتطلب دقة زمنية صارمة مثل [مزامنة غير حرجة/تنظيف/إحصاءات/...].\nيتم الجدولة وفق [حالة البطارية/الشبكة/الشحن/سياسات السكون/...], وقد تتأخر المهام عند إيقاف الشاشة أو في وضع السكون.\nلا يضمن الدقة الزمنية لكنه يوفر مزايا في [إتمام موثوق/إعادة المحاولة عند الفشل/سلاسل المهام/إزالة التكرار].\n\n3. JobScheduler\nتنفيذ تاريخي لأغراض التوافق.\nفي إصدارات أندرويد الحديثة قد تحدث تأخيرات أكبر.\nلا يُنصح به إلا لاعتبارات التوافق.</string>
<string name="text_click_item_to_show_details">اضغط على العنصر لعرض التفاصيل</string>
</resources> </resources>

View File

@@ -1067,6 +1067,7 @@
<string name="description_timed_task_backend">Controls the underlying mechanism for triggering scripts on a schedule.\n\nAlarmManager: With the “Allow setting alarms and reminders” permission granted, scheduled tasks can fire closer to the exact time.\nWorkManager: System-friendly; suitable for non-critical tasks that can tolerate some delay.\nJobScheduler: Legacy implementation kept for compatibility; higher chance of delays.</string> <string name="description_timed_task_backend">Controls the underlying mechanism for triggering scripts on a schedule.\n\nAlarmManager: With the “Allow setting alarms and reminders” permission granted, scheduled tasks can fire closer to the exact time.\nWorkManager: System-friendly; suitable for non-critical tasks that can tolerate some delay.\nJobScheduler: Legacy implementation kept for compatibility; higher chance of delays.</string>
<string name="failed_to_go_to_access_settings">Failed to open the settings page</string> <string name="failed_to_go_to_access_settings">Failed to open the settings page</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">Granting the “Allow setting alarms and reminders” permission is recommended to help tasks run as punctually as possible even when the screen is off or the device is idle</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">Granting the “Allow setting alarms and reminders” permission is recommended to help tasks run as punctually as possible even when the screen is off or the device is idle</string>
<string name="description_timed_task_backend_more">Use cases and differences:\n\n1) AlarmManager\nBest for time-sensitive tasks, e.g., [reminders/strictly scheduled scripts/...].\nOn Android 12+ with the “Allow setting alarms and reminders” permission, tasks can run more on time even when the screen is off or the device is idle.\nWithout it, the system may degrade exactness or delay execution.\n\n2) WorkManager\nBest for tasks that dont require strict timing, e.g., [non-critical sync/cleanup/statistics/...].\nScheduling depends on [battery/network/charging/idle policies/...], so execution may be postponed when the screen is off or idle.\nWhile it cant guarantee exact timing, it excels at [reliable completion/retries/chaining/unique work de-duplication].\n\n3) JobScheduler\nHistorical implementation for compatibility.\nOn newer Android versions, tasks may be delayed more noticeably.\nGenerally not recommended unless required for compatibility.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">Use cases and differences:\n\n1. AlarmManager\nBest for time-sensitive tasks, e.g., [reminders/strictly scheduled scripts/...].\nOn Android 12+ with the “Allow setting alarms and reminders” permission, tasks can run more on time even when the screen is off or the device is idle.\nWithout it, the system may degrade exactness or delay execution.\n\n2. WorkManager\nBest for tasks that dont require strict timing, e.g., [non-critical sync/cleanup/statistics/...].\nScheduling depends on [battery/network/charging/idle policies/...], so execution may be postponed when the screen is off or idle.\nWhile it cant guarantee exact timing, it excels at [reliable completion/retries/chaining/unique work de-duplication].\n\n3. JobScheduler\nHistorical implementation for compatibility.\nOn newer Android versions, tasks may be delayed more noticeably.\nGenerally not recommended unless required for compatibility.</string>
<string name="text_click_item_to_show_details">Click an item to view details</string>
</resources> </resources>

View File

@@ -1070,6 +1070,7 @@
<string name="description_timed_task_backend">Controla el mecanismo subyacente para activar scripts de forma programada.\n\nAlarmManager: Mediante la concesión del permiso \"Permitir configurar alarmas y recordatorios\", las tareas programadas pueden dispararse con mayor puntualidad.\nWorkManager: Amigable con el sistema; adecuado para tareas no críticas que toleran cierta demora.\nJobScheduler: Implementación antigua, mantenida por compatibilidad; la ejecución puede retrasarse con mayor probabilidad.</string> <string name="description_timed_task_backend">Controla el mecanismo subyacente para activar scripts de forma programada.\n\nAlarmManager: Mediante la concesión del permiso \"Permitir configurar alarmas y recordatorios\", las tareas programadas pueden dispararse con mayor puntualidad.\nWorkManager: Amigable con el sistema; adecuado para tareas no críticas que toleran cierta demora.\nJobScheduler: Implementación antigua, mantenida por compatibilidad; la ejecución puede retrasarse con mayor probabilidad.</string>
<string name="failed_to_go_to_access_settings">No se pudo abrir la página de ajustes</string> <string name="failed_to_go_to_access_settings">No se pudo abrir la página de ajustes</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">Se recomienda conceder el permiso \"Permitir configurar alarmas y recordatorios\" para asegurar que las tareas programadas se ejecuten lo más puntualmente posible incluso con la pantalla apagada o en espera</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">Se recomienda conceder el permiso \"Permitir configurar alarmas y recordatorios\" para asegurar que las tareas programadas se ejecuten lo más puntualmente posible incluso con la pantalla apagada o en espera</string>
<string name="description_timed_task_backend_more">Escenarios de uso y diferencias:\n\n1. AlarmManager\nAdecuado para tareas sensibles a la puntualidad, p. ej., [recordatorios/scripts estrictamente programados/...].\nEn Android 12+ y con el permiso \"Permitir configurar alarmas y recordatorios\", puede ejecutar tareas de forma más puntual con la pantalla apagada o en estado de espera.\nSin dicho permiso, el sistema puede degradar la exactitud o retrasar la ejecución.\n\n2. WorkManager\nAdecuado para tareas que no requieren estricta puntualidad, p. ej., [sincronización no crítica/limpieza/estadísticas/...].\nSe programa según [batería/red/carga/estrategias de reposo/...], por lo que puede posponer la ejecución con la pantalla apagada o en espera.\nAunque no garantiza precisión temporal, tiene ventajas en [finalización fiable/reintentos en caso de fallo/encadenamiento/deduplicación de trabajos].\n\n3. JobScheduler\nImplementación histórica para compatibilidad.\nEn versiones recientes de Android, las tareas pueden experimentar mayores retrasos.\nPor lo general, no se recomienda salvo por motivos de compatibilidad.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">Escenarios de uso y diferencias:\n\n1. AlarmManager\nAdecuado para tareas sensibles a la puntualidad, p. ej., [recordatorios/scripts estrictamente programados/...].\nEn Android 12+ y con el permiso \"Permitir configurar alarmas y recordatorios\", puede ejecutar tareas de forma más puntual con la pantalla apagada o en estado de espera.\nSin dicho permiso, el sistema puede degradar la exactitud o retrasar la ejecución.\n\n2. WorkManager\nAdecuado para tareas que no requieren estricta puntualidad, p. ej., [sincronización no crítica/limpieza/estadísticas/...].\nSe programa según [batería/red/carga/estrategias de reposo/...], por lo que puede posponer la ejecución con la pantalla apagada o en espera.\nAunque no garantiza precisión temporal, tiene ventajas en [finalización fiable/reintentos en caso de fallo/encadenamiento/deduplicación de trabajos].\n\n3. JobScheduler\nImplementación histórica para compatibilidad.\nEn versiones recientes de Android, las tareas pueden experimentar mayores retrasos.\nPor lo general, no se recomienda salvo por motivos de compatibilidad.</string>
<string name="text_click_item_to_show_details">Toca un elemento para ver los detalles</string>
</resources> </resources>

View File

@@ -1070,6 +1070,7 @@
<string name="description_timed_task_backend">Contrôle le mécanisme sous-jacent de déclenchement programmé des scripts.\n\nAlarmManager : En accordant l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\", les tâches peuvent se déclencher avec une meilleure ponctualité.\nWorkManager : Plus conciliant avec le système ; adapté aux tâches non critiques tolérant un certain délai.\nJobScheduler : Ancienne implémentation conservée pour la compatibilité, avec un risque accru de retard.</string> <string name="description_timed_task_backend">Contrôle le mécanisme sous-jacent de déclenchement programmé des scripts.\n\nAlarmManager : En accordant l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\", les tâches peuvent se déclencher avec une meilleure ponctualité.\nWorkManager : Plus conciliant avec le système ; adapté aux tâches non critiques tolérant un certain délai.\nJobScheduler : Ancienne implémentation conservée pour la compatibilité, avec un risque accru de retard.</string>
<string name="failed_to_go_to_access_settings">Échec d\'ouverture de la page des paramètres</string> <string name="failed_to_go_to_access_settings">Échec d\'ouverture de la page des paramètres</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">Il est recommandé d\'accorder l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\" afin d\'assurer un déclenchement aussi ponctuel que possible, même écran éteint ou en veille</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">Il est recommandé d\'accorder l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\" afin d\'assurer un déclenchement aussi ponctuel que possible, même écran éteint ou en veille</string>
<string name="description_timed_task_backend_more">Scénarios d\'usage et différences :\n\n1. AlarmManager\nConvient aux tâches sensibles à la ponctualité, p. ex. [rappels/scripts strictement planifiés/...].\nSous Android 12+ avec l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\", l\'exécution reste plus ponctuelle écran éteint ou en veille.\nSans cette autorisation, le système peut réduire la précision ou retarder l\'exécution.\n\n2. WorkManager\nConvient aux tâches ne nécessitant pas une ponctualité stricte, p. ex. [synchronisation non critique/nettoyage/statistiques/...].\nL\'ordonnancement dépend de [la batterie/le réseau/la charge/les stratégies de veille/...], ce qui peut retarder l\'exécution écran éteint ou en veille.\nBien qu\'il ne garantisse pas la précision temporelle, il offre des atouts en [achèvement fiable/reprise en cas d\'échec/chaînage/déduplication des travaux].\n\n3. JobScheduler\nImplémentation historique conservée pour compatibilité.\nSur les versions récentes d\'Android, les tâches peuvent subir des retards plus importants.\nSauf besoin de compatibilité, il n\'est généralement pas recommandé.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">Scénarios d\'usage et différences :\n\n1. AlarmManager\nConvient aux tâches sensibles à la ponctualité, p. ex. [rappels/scripts strictement planifiés/...].\nSous Android 12+ avec l\'autorisation \"Autoriser la définition d\'alarmes et de rappels\", l\'exécution reste plus ponctuelle écran éteint ou en veille.\nSans cette autorisation, le système peut réduire la précision ou retarder l\'exécution.\n\n2. WorkManager\nConvient aux tâches ne nécessitant pas une ponctualité stricte, p. ex. [synchronisation non critique/nettoyage/statistiques/...].\nL\'ordonnancement dépend de [la batterie/le réseau/la charge/les stratégies de veille/...], ce qui peut retarder l\'exécution écran éteint ou en veille.\nBien qu\'il ne garantisse pas la précision temporelle, il offre des atouts en [achèvement fiable/reprise en cas d\'échec/chaînage/déduplication des travaux].\n\n3. JobScheduler\nImplémentation historique conservée pour compatibilité.\nSur les versions récentes d\'Android, les tâches peuvent subir des retards plus importants.\nSauf besoin de compatibilité, il n\'est généralement pas recommandé.</string>
<string name="text_click_item_to_show_details">Touchez un élément pour afficher les détails</string>
</resources> </resources>

View File

@@ -1071,6 +1071,7 @@
<string name="description_timed_task_backend">スクリプトを定時で起動するための基盤メカニズムを制御します.\n\nAlarmManager: システムの \"アラームとリマインダーの設定を許可\" 権限を付与すると/より正確な時刻での実行に近づきます.\nWorkManager: システムに優しく/一定の遅延を許容できる非重要タスクに適しています.\nJobScheduler: 旧来の実装で互換性のために残されていますが/遅延が発生しやすいです.</string> <string name="description_timed_task_backend">スクリプトを定時で起動するための基盤メカニズムを制御します.\n\nAlarmManager: システムの \"アラームとリマインダーの設定を許可\" 権限を付与すると/より正確な時刻での実行に近づきます.\nWorkManager: システムに優しく/一定の遅延を許容できる非重要タスクに適しています.\nJobScheduler: 旧来の実装で互換性のために残されていますが/遅延が発生しやすいです.</string>
<string name="failed_to_go_to_access_settings">設定画面を開けませんでした</string> <string name="failed_to_go_to_access_settings">設定画面を開けませんでした</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">画面消灯中や待機時でもできるだけ正確に実行できるよう/[アラームとリマインダーの設定を許可] 権限の付与を推奨します</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">画面消灯中や待機時でもできるだけ正確に実行できるよう/[アラームとリマインダーの設定を許可] 権限の付与を推奨します</string>
<string name="description_timed_task_backend_more">利用シーンと違い: \n\n1. AlarmManager\n[リマインダー/厳密な時刻のスクリプト/...] など/時刻精度が重要なタスクに適しています.\nAndroid 12 以降で \"アラームとリマインダーの設定を許可\" 権限がある場合/画面消灯/待機中でも比較的正確に実行されます.\n権限がない場合/システムにより不正確または遅延実行になる可能性があります.\n\n2. WorkManager\n[非重要な同期/クリーンアップ/統計/...] など/厳密な時刻精度を必要としないタスクに適しています.\n[バッテリー/ネットワーク/充電状況/待機ポリシー/...] に応じてスケジューリングされ/消灯/待機中は実行が遅れることがあります.\n時間精度は保証されませんが/[確実な完了/失敗時の再試行/チェーン実行/一意タスクの重複排除] に強みがあります.\n\n3. JobScheduler\n互換性維持のための歴史的実装です.\n新しい Android では遅延が大きくなりやすい傾向があります.\n互換性の必要がない限り/通常は非推奨です.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">利用シーンと違い: \n\n1. AlarmManager\n[リマインダー/厳密な時刻のスクリプト/...] など/時刻精度が重要なタスクに適しています.\nAndroid 12 以降で \"アラームとリマインダーの設定を許可\" 権限がある場合/画面消灯/待機中でも比較的正確に実行されます.\n権限がない場合/システムにより不正確または遅延実行になる可能性があります.\n\n2. WorkManager\n[非重要な同期/クリーンアップ/統計/...] など/厳密な時刻精度を必要としないタスクに適しています.\n[バッテリー/ネットワーク/充電状況/待機ポリシー/...] に応じてスケジューリングされ/消灯/待機中は実行が遅れることがあります.\n時間精度は保証されませんが/[確実な完了/失敗時の再試行/チェーン実行/一意タスクの重複排除] に強みがあります.\n\n3. JobScheduler\n互換性維持のための歴史的実装です.\n新しい Android では遅延が大きくなりやすい傾向があります.\n互換性の必要がない限り/通常は非推奨です.</string>
<string name="text_click_item_to_show_details">項目をタップして詳細を表示します</string>
</resources> </resources>

View File

@@ -1072,6 +1072,7 @@
<string name="description_timed_task_backend">스크립트를 정해진 시간에 실행하는 기본 메커니즘을 제어합니다.\n\nAlarmManager: 시스템의 \"알람 및 알림 설정 허용\" 권한을 부여하면 보다 정확한 시각에 가깝게 실행됩니다.\nWorkManager: 시스템 친화적이며, 일정 지연을 허용할 수 있는 비중요 작업에 적합합니다.\nJobScheduler: 호환성 유지를 위해 남겨둔 구방식으로, 지연 발생 가능성이 큽니다.</string> <string name="description_timed_task_backend">스크립트를 정해진 시간에 실행하는 기본 메커니즘을 제어합니다.\n\nAlarmManager: 시스템의 \"알람 및 알림 설정 허용\" 권한을 부여하면 보다 정확한 시각에 가깝게 실행됩니다.\nWorkManager: 시스템 친화적이며, 일정 지연을 허용할 수 있는 비중요 작업에 적합합니다.\nJobScheduler: 호환성 유지를 위해 남겨둔 구방식으로, 지연 발생 가능성이 큽니다.</string>
<string name="failed_to_go_to_access_settings">설정 페이지를 열지 못했습니다</string> <string name="failed_to_go_to_access_settings">설정 페이지를 열지 못했습니다</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">화면이 꺼져 있거나 대기 상태에서도 최대한 정시에 실행되도록, \"알람 및 알림 설정 허용\" 권한 부여를 권장합니다</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">화면이 꺼져 있거나 대기 상태에서도 최대한 정시에 실행되도록, \"알람 및 알림 설정 허용\" 권한 부여를 권장합니다</string>
<string name="description_timed_task_backend_more">사용 시나리오 및 차이점:\n\n1. AlarmManager\n[리마인더/엄격한 정시 스크립트/...] 등 시간 정확도가 중요한 작업에 적합합니다.\nAndroid 12+ 에서 \"알람 및 알림 설정 허용\" 권한이 있으면, 화면 꺼짐/대기 중에도 비교적 정확하게 실행됩니다.\n 권한이 없으면 시스템이 정확도를 낮추거나 실행을 지연할 수 있습니다.\n\n2. WorkManager\n[비중요 동기화/정리/통계/...] 등 엄격한 정시성이 필요 없는 작업에 적합합니다.\n[배터리/네트워크/충전 상태/대기 정책/...] 에 따라 스케줄링되며, 화면 꺼짐/대기 중에는 지연될 수 있습니다.\n 시간 정확도는 보장되지 않지만, [신뢰성 있는 완료/실패 재시도/체이닝/단일 작업 중복 방지] 에 장점이 있습니다.\n\n3. JobScheduler\n 호환성 유지를 위한 기존 구현입니다.\n 신형 Android 에서는 지연이 더 커질 수 있습니다.\n 특별한 호환성 목적이 아니라면 일반적으로 권장하지 않습니다.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">사용 시나리오 및 차이점:\n\n1. AlarmManager\n[리마인더/엄격한 정시 스크립트/...] 등 시간 정확도가 중요한 작업에 적합합니다.\nAndroid 12+ 에서 \"알람 및 알림 설정 허용\" 권한이 있으면, 화면 꺼짐/대기 중에도 비교적 정확하게 실행됩니다.\n 권한이 없으면 시스템이 정확도를 낮추거나 실행을 지연할 수 있습니다.\n\n2. WorkManager\n[비중요 동기화/정리/통계/...] 등 엄격한 정시성이 필요 없는 작업에 적합합니다.\n[배터리/네트워크/충전 상태/대기 정책/...] 에 따라 스케줄링되며, 화면 꺼짐/대기 중에는 지연될 수 있습니다.\n 시간 정확도는 보장되지 않지만, [신뢰성 있는 완료/실패 재시도/체이닝/단일 작업 중복 방지] 에 장점이 있습니다.\n\n3. JobScheduler\n 호환성 유지를 위한 기존 구현입니다.\n 신형 Android 에서는 지연이 더 커질 수 있습니다.\n 특별한 호환성 목적이 아니라면 일반적으로 권장하지 않습니다.</string>
<string name="text_click_item_to_show_details">항목을 탭하면 자세한 정보를 볼 수 있습니다</string>
</resources> </resources>

View File

@@ -1070,6 +1070,7 @@
<string name="description_timed_task_backend">Управляет базовым механизмом по расписанию запуска скриптов.\n\nAlarmManager: При выдаче разрешения "Разрешить настройку будильников и напоминаний" задачи выполняются более точно по времени.\nWorkManager: Дружелюбен к системе; подходит для некритичных задач, допускающих задержку.\nJobScheduler: Устаревшая реализация, сохранена для совместимости; вероятность задержек выше.</string> <string name="description_timed_task_backend">Управляет базовым механизмом по расписанию запуска скриптов.\n\nAlarmManager: При выдаче разрешения "Разрешить настройку будильников и напоминаний" задачи выполняются более точно по времени.\nWorkManager: Дружелюбен к системе; подходит для некритичных задач, допускающих задержку.\nJobScheduler: Устаревшая реализация, сохранена для совместимости; вероятность задержек выше.</string>
<string name="failed_to_go_to_access_settings">Не удалось открыть страницу настроек</string> <string name="failed_to_go_to_access_settings">Не удалось открыть страницу настроек</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">Рекомендуется выдать разрешение "Разрешить настройку будильников и напоминаний", чтобы обеспечить максимально точный запуск задач даже при выключенном экране или в режиме ожидания</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">Рекомендуется выдать разрешение "Разрешить настройку будильников и напоминаний", чтобы обеспечить максимально точный запуск задач даже при выключенном экране или в режиме ожидания</string>
<string name="description_timed_task_backend_more">Сценарии и отличия:\n\n1. AlarmManager\nПодходит для задач, чувствительных к точности времени, например [напоминания/строго по расписанию/...].\nВ Android 12+ при наличии разрешения "Разрешить настройку будильников и напоминаний" задачи запускаются более точно даже при выключенном экране/в ожидании.\nБез него система может понизить точность или отложить выполнение.\n\n2. WorkManager\nПодходит для задач без строгих требований к времени, например [некритичная синхронизация/очистка/статистика/...].\nПланирование учитывает [батарею/сеть/зарядку/политику сна/...], возможны задержки при выключенном экране или в ожидании.\nХотя точность не гарантируется, он силён в [надёжном завершении/повторных попытках/цепочках/дедупликации работ].\n\n3. JobScheduler\nИсторическая реализация для совместимости.\nНа новых версиях Android возможны более существенные задержки.\nНе рекомендуется, если это не необходимо ради совместимости.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">Сценарии и отличия:\n\n1. AlarmManager\nПодходит для задач, чувствительных к точности времени, например [напоминания/строго по расписанию/...].\nВ Android 12+ при наличии разрешения "Разрешить настройку будильников и напоминаний" задачи запускаются более точно даже при выключенном экране/в ожидании.\nБез него система может понизить точность или отложить выполнение.\n\n2. WorkManager\nПодходит для задач без строгих требований к времени, например [некритичная синхронизация/очистка/статистика/...].\nПланирование учитывает [батарею/сеть/зарядку/политику сна/...], возможны задержки при выключенном экране или в ожидании.\nХотя точность не гарантируется, он силён в [надёжном завершении/повторных попытках/цепочках/дедупликации работ].\n\n3. JobScheduler\nИсторическая реализация для совместимости.\nНа новых версиях Android возможны более существенные задержки.\nНе рекомендуется, если это не необходимо ради совместимости.</string>
<string name="text_click_item_to_show_details">Нажмите на пункт, чтобы просмотреть подробности</string>
</resources> </resources>

View File

@@ -1068,6 +1068,7 @@
<string name="description_timed_task_backend">控制腳本定時觸發的底層機制.\n\nAlarmManager: 通過申請 \"允許設置鬧鐘和提醒\" 權限, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作兼容保留, 定時任務出現延遲的概率較大.</string> <string name="description_timed_task_backend">控制腳本定時觸發的底層機制.\n\nAlarmManager: 通過申請 \"允許設置鬧鐘和提醒\" 權限, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作兼容保留, 定時任務出現延遲的概率較大.</string>
<string name="failed_to_go_to_access_settings">跳轉設置頁面失敗</string> <string name="failed_to_go_to_access_settings">跳轉設置頁面失敗</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">建議授予 \"允許設置鬧鐘和提醒\" 權限以確保定時任務在息屏或待機狀態時儘可能準時執行</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">建議授予 \"允許設置鬧鐘和提醒\" 權限以確保定時任務在息屏或待機狀態時儘可能準時執行</string>
<string name="description_timed_task_backend_more">使用場景與差異説明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時腳本/...].\n在 Android 12+ 獲取 \"允許設置鬧鐘和提醒\" 權限後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設置鬧鐘和提醒\" 權限時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網絡/充電情況/待機策略/... ] 進行調度, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為兼容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於兼容需要, 一般不推薦使用.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">使用場景與差異説明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時腳本/...].\n在 Android 12+ 獲取 \"允許設置鬧鐘和提醒\" 權限後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設置鬧鐘和提醒\" 權限時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網絡/充電情況/待機策略/... ] 進行調度, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為兼容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於兼容需要, 一般不推薦使用.</string>
<string name="text_click_item_to_show_details">點擊條目可查看詳情</string>
</resources> </resources>

View File

@@ -1068,6 +1068,7 @@
<string name="description_timed_task_backend">控制指令碼定時觸發的底層機制.\n\nAlarmManager: 透過申請 \"允許設定鬧鐘和提醒\" 許可權, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作相容保留, 定時任務出現延遲的機率較大.</string> <string name="description_timed_task_backend">控制指令碼定時觸發的底層機制.\n\nAlarmManager: 透過申請 \"允許設定鬧鐘和提醒\" 許可權, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作相容保留, 定時任務出現延遲的機率較大.</string>
<string name="failed_to_go_to_access_settings">跳轉設定頁面失敗</string> <string name="failed_to_go_to_access_settings">跳轉設定頁面失敗</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">建議授予 \"允許設定鬧鐘和提醒\" 許可權以確保定時任務在息屏或待機狀態時儘可能準時執行</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">建議授予 \"允許設定鬧鐘和提醒\" 許可權以確保定時任務在息屏或待機狀態時儘可能準時執行</string>
<string name="description_timed_task_backend_more">使用場景與差異說明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時指令碼/...].\n在 Android 12+ 獲取 \"允許設定鬧鐘和提醒\" 許可權後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設定鬧鐘和提醒\" 許可權時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網路/充電情況/待機策略/... ] 進行排程, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為相容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於相容需要, 一般不推薦使用.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">使用場景與差異說明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時指令碼/...].\n在 Android 12+ 獲取 \"允許設定鬧鐘和提醒\" 許可權後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設定鬧鐘和提醒\" 許可權時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網路/充電情況/待機策略/... ] 進行排程, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為相容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於相容需要, 一般不推薦使用.</string>
<string name="text_click_item_to_show_details">點選條目可檢視詳情</string>
</resources> </resources>

View File

@@ -1068,6 +1068,7 @@
<string name="description_timed_task_backend">控制脚本定时触发的底层机制.\n\nAlarmManager: 通过申请 \"允许设置闹钟和提醒\" 权限, 可使定时任务的触发更接近准时.\nWorkManager: 系统友好, 适合可接受一定延迟的非关键定时任务.\nJobScheduler: 旧实现, 仅用作兼容保留, 定时任务出现延迟的概率较大.</string> <string name="description_timed_task_backend">控制脚本定时触发的底层机制.\n\nAlarmManager: 通过申请 \"允许设置闹钟和提醒\" 权限, 可使定时任务的触发更接近准时.\nWorkManager: 系统友好, 适合可接受一定延迟的非关键定时任务.\nJobScheduler: 旧实现, 仅用作兼容保留, 定时任务出现延迟的概率较大.</string>
<string name="failed_to_go_to_access_settings">跳转设置页面失败</string> <string name="failed_to_go_to_access_settings">跳转设置页面失败</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">建议授予 \"允许设置闹钟和提醒\" 权限以确保定时任务在息屏或待机状态时尽可能准时执行</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">建议授予 \"允许设置闹钟和提醒\" 权限以确保定时任务在息屏或待机状态时尽可能准时执行</string>
<string name="description_timed_task_backend_more">使用场景与差异说明: \n\n1. AlarmManager\n适用于准时性敏感的定时任务, 如 [提醒/严格定时脚本/...].\n在 Android 12+ 获取 \"允许设置闹钟和提醒\" 权限后, 在息屏或待机状态时能够较准时地执行定时任务.\n在未授予 \"允许设置闹钟和提醒\" 权限时, 系统可能降级为不准时或延后执行任务.\n\n2. WorkManager\n适用于不要求严格准时执行的定时任务, 如 [非关键性同步/清理/统计/...].\n根据系统 [ 电量/网络/充电情况/待机策略/... ] 进行调度, 息屏或待机状态时可能推迟任务执行.\n虽无法保证时间精确性, 但在 [ 可靠完成/失败重试/链式执行/唯一任务去重 ] 等方面拥有独特优势.\n\n3. Job\n历史实现, 为兼容保留.\n在高版本安卓系统中定时任务可能存在较大的延迟执行问题.\n除非出于兼容需要, 一般不推荐使用.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">使用场景与差异说明: \n\n1. AlarmManager\n适用于准时性敏感的定时任务, 如 [提醒/严格定时脚本/...].\n在 Android 12+ 获取 \"允许设置闹钟和提醒\" 权限后, 在息屏或待机状态时能够较准时地执行定时任务.\n在未授予 \"允许设置闹钟和提醒\" 权限时, 系统可能降级为不准时或延后执行任务.\n\n2. WorkManager\n适用于不要求严格准时执行的定时任务, 如 [非关键性同步/清理/统计/...].\n根据系统 [ 电量/网络/充电情况/待机策略/... ] 进行调度, 息屏或待机状态时可能推迟任务执行.\n虽无法保证时间精确性, 但在 [ 可靠完成/失败重试/链式执行/唯一任务去重 ] 等方面拥有独特优势.\n\n3. Job\n历史实现, 为兼容保留.\n在高版本安卓系统中定时任务可能存在较大的延迟执行问题.\n除非出于兼容需要, 一般不推荐使用.</string>
<string name="text_click_item_to_show_details">点击条目可查看详情</string>
</resources> </resources>

View File

@@ -142,6 +142,7 @@
<string name="key_root_record_out_file_type" translatable="false">key_$_root_record_out_file_type</string> <string name="key_root_record_out_file_type" translatable="false">key_$_root_record_out_file_type</string>
<string name="key_root_record_out_file_type_binary" translatable="false">key_$_root_record_out_file_type_binary</string> <string name="key_root_record_out_file_type_binary" translatable="false">key_$_root_record_out_file_type_binary</string>
<string name="key_root_record_out_file_type_js" translatable="false">key_$_root_record_out_file_type_js</string> <string name="key_root_record_out_file_type_js" translatable="false">key_$_root_record_out_file_type_js</string>
<string name="key_scripts_after_app_restart" translatable="false">key_$_scripts_after_app_restart</string>
<string name="key_server_address" translatable="false">key_$_server_address</string> <string name="key_server_address" translatable="false">key_$_server_address</string>
<string name="key_server_socket_normally_closed" translatable="false">key_$_server_socket_normally_closed</string> <string name="key_server_socket_normally_closed" translatable="false">key_$_server_socket_normally_closed</string>
<string name="key_stable_mode" translatable="false">key_$_stable_mode</string> <string name="key_stable_mode" translatable="false">key_$_stable_mode</string>
@@ -1311,6 +1312,7 @@
<string name="description_timed_task_backend">Controls the underlying mechanism for triggering scripts on a schedule.\n\nAlarmManager: With the “Allow setting alarms and reminders” permission granted, scheduled tasks can fire closer to the exact time.\nWorkManager: System-friendly; suitable for non-critical tasks that can tolerate some delay.\nJobScheduler: Legacy implementation kept for compatibility; higher chance of delays.</string> <string name="description_timed_task_backend">Controls the underlying mechanism for triggering scripts on a schedule.\n\nAlarmManager: With the “Allow setting alarms and reminders” permission granted, scheduled tasks can fire closer to the exact time.\nWorkManager: System-friendly; suitable for non-critical tasks that can tolerate some delay.\nJobScheduler: Legacy implementation kept for compatibility; higher chance of delays.</string>
<string name="failed_to_go_to_access_settings">Failed to open the settings page</string> <string name="failed_to_go_to_access_settings">Failed to open the settings page</string>
<string name="text_allow_setting_alarms_and_reminders_is_recommended">Granting the “Allow setting alarms and reminders” permission is recommended to help tasks run as punctually as possible even when the screen is off or the device is idle</string> <string name="text_allow_setting_alarms_and_reminders_is_recommended">Granting the “Allow setting alarms and reminders” permission is recommended to help tasks run as punctually as possible even when the screen is off or the device is idle</string>
<string name="description_timed_task_backend_more">Use cases and differences:\n\n1) AlarmManager\nBest for time-sensitive tasks, e.g., [reminders/strictly scheduled scripts/...].\nOn Android 12+ with the “Allow setting alarms and reminders” permission, tasks can run more on time even when the screen is off or the device is idle.\nWithout it, the system may degrade exactness or delay execution.\n\n2) WorkManager\nBest for tasks that dont require strict timing, e.g., [non-critical sync/cleanup/statistics/...].\nScheduling depends on [battery/network/charging/idle policies/...], so execution may be postponed when the screen is off or idle.\nWhile it cant guarantee exact timing, it excels at [reliable completion/retries/chaining/unique work de-duplication].\n\n3) JobScheduler\nHistorical implementation for compatibility.\nOn newer Android versions, tasks may be delayed more noticeably.\nGenerally not recommended unless required for compatibility.</string> <string name="description_timed_task_backend_more" tools:ignore="TypographyEllipsis">Use cases and differences:\n\n1. AlarmManager\nBest for time-sensitive tasks, e.g., [reminders/strictly scheduled scripts/...].\nOn Android 12+ with the “Allow setting alarms and reminders” permission, tasks can run more on time even when the screen is off or the device is idle.\nWithout it, the system may degrade exactness or delay execution.\n\n2. WorkManager\nBest for tasks that dont require strict timing, e.g., [non-critical sync/cleanup/statistics/...].\nScheduling depends on [battery/network/charging/idle policies/...], so execution may be postponed when the screen is off or idle.\nWhile it cant guarantee exact timing, it excels at [reliable completion/retries/chaining/unique work de-duplication].\n\n3. JobScheduler\nHistorical implementation for compatibility.\nOn newer Android versions, tasks may be delayed more noticeably.\nGenerally not recommended unless required for compatibility.</string>
<string name="text_click_item_to_show_details">Click an item to view details</string>
</resources> </resources>

View File

@@ -26,7 +26,9 @@ abstract class DictionaryDatabase internal constructor(context: Context): Closea
SQLiteDatabase.openDatabase(context.getDatabasePath(databaseName).absolutePath, null, SQLiteDatabase.OPEN_READONLY) SQLiteDatabase.openDatabase(context.getDatabasePath(databaseName).absolutePath, null, SQLiteDatabase.OPEN_READONLY)
} }
override fun close() = database.close() override fun close() {
runCatching { database.close() }
}
private fun copyDatabaseWithCompressionAndMd5(context: Context) { private fun copyDatabaseWithCompressionAndMd5(context: Context) {
val dbFile = File(context.getDatabasePath(databaseName).path) val dbFile = File(context.getDatabasePath(databaseName).path)

View File

@@ -1,5 +1,5 @@
#Sun Nov 02 19:59:28 CST 2025 #Mon Nov 03 13:14:49 CST 2025
BUILD_TIME=1762084768045 BUILD_TIME=1762146889031
COMPILE_SDK_VERSION=36 COMPILE_SDK_VERSION=36
IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125 IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=36 TARGET_SDK_VERSION=36
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3465 VERSION_BUILD=3468
VERSION_NAME=6.7.0 Alpha10 VERSION_NAME=6.7.0 Alpha10
VSCODE_EXT_REQUIRED_VERSION=1.0.8 VSCODE_EXT_REQUIRED_VERSION=1.0.8