diff --git a/.changelog/lang_zh-Hans.json b/.changelog/lang_zh-Hans.json
index 68f69bae..42071a6f 100644
--- a/.changelog/lang_zh-Hans.json
+++ b/.changelog/lang_zh-Hans.json
@@ -18,8 +18,9 @@
"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)_",
"structuredClone 全局方法, 用于深拷贝 JavaScript 对象 (参阅 [MDN](https://developer.mozilla.org/zh-CN/docs/Web/API/Window/structuredClone))",
- "设置页面支持 \"应用启动器图标\" 设置选项 _[`issue #405`](http://issues.autojs6.com/405)_",
- "设置页面支持 \"Java 原始类型包装\" 设置选项 _[`issue #435`](http://issues.autojs6.com/435)_",
+ "设置页面增加 \"Java 原始类型包装\" 设置选项 _[`issue #435`](http://issues.autojs6.com/435)_",
+ "设置页面增加 \"定时任务调度引擎\" 设置选项, 支持 AlarmManager/WorkManager/JobScheduler _[`issue #457`](http://issues.autojs6.com/457)_ _[`issue #388`](http://issues.autojs6.com/388)_ _[`issue #163`](http://issues.autojs6.com/163)_ _[`issue #53`](http://issues.autojs6.com/53)_ _[`issue #21`](http://issues.autojs6.com/21)_",
+ "设置页面增加 \"应用启动器图标\" 设置选项, 支持自适应图标/透明背景图标 _[`issue #405`](http://issues.autojs6.com/405)_",
"Scrapers 工具 (run-scrapers.mjs) 用于自动更新 Gradle 构建脚本结构化数据/README 通用数据/README 模板数据等"
],
"fix": [
@@ -70,6 +71,7 @@
"本地化 Expandable Layout 版本 1.6.0",
"本地化 Recyclerview Flexible Divider 版本 1.4.0",
"附加 Androidx Core (KTX) 版本 1.15.0",
+ "附加 Androidx Work Runtime 版本 2.11.0",
"升级 Android SDK 版本 35 -> 36",
"升级 Gradle 版本 8.14 -> 8.14.3",
"升级 Desugar JDK Libs 版本 2.0.4 -> 2.1.5",
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index cbc8163a..f17477c8 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -185,6 +185,9 @@ dependencies /* Unclassified */ {
// Android Job
implementation(project(":libs:android-job-simplified-1_4_3"))
+ // Androidx Work Runtime
+ implementation(libs.work.runtime)
+
// APK Parser
// implementation("com.jaredrummler:apk-parser:1.0.2")
// implementation("com.github.AndroidDeveloperLB:apk-parser:6")
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dba1c0fa..cf8aa6db 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -600,6 +600,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/java/org/autojs/autojs/permission/DisplayOverOtherAppsPermission.kt b/app/src/main/java/org/autojs/autojs/permission/DisplayOverOtherAppsPermission.kt
index a72f1616..0a1abcba 100644
--- a/app/src/main/java/org/autojs/autojs/permission/DisplayOverOtherAppsPermission.kt
+++ b/app/src/main/java/org/autojs/autojs/permission/DisplayOverOtherAppsPermission.kt
@@ -62,7 +62,7 @@ class DisplayOverOtherAppsPermission(override val context: Context) : Permission
String.format(
"%s\n\n%s",
context.getString(R.string.text_display_over_other_app_is_recommended),
- context.getString(R.string.text_click_ok_to_go_to_access_settings),
+ context.getString(R.string.text_click_ok_to_go_to_settings),
)
)
.widgetThemeColor()
diff --git a/app/src/main/java/org/autojs/autojs/permission/IgnoreBatteryOptimizationsPermission.kt b/app/src/main/java/org/autojs/autojs/permission/IgnoreBatteryOptimizationsPermission.kt
index 1e93847e..e95e678d 100644
--- a/app/src/main/java/org/autojs/autojs/permission/IgnoreBatteryOptimizationsPermission.kt
+++ b/app/src/main/java/org/autojs/autojs/permission/IgnoreBatteryOptimizationsPermission.kt
@@ -1,12 +1,11 @@
package org.autojs.autojs.permission
import android.annotation.SuppressLint
-import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
-import android.net.Uri
import android.os.PowerManager
import android.provider.Settings
+import androidx.core.net.toUri
import org.autojs.autojs.ui.main.drawer.PermissionItemHelper
import org.autojs.autojs.util.ViewUtils
import org.autojs.autojs6.R
@@ -17,29 +16,27 @@ import org.autojs.autojs6.R
class IgnoreBatteryOptimizationsPermission(override val context: Context) : PermissionItemHelper {
override fun has(): Boolean {
- return (context.getSystemService(Context.POWER_SERVICE) as PowerManager).isIgnoringBatteryOptimizations(context.packageName)
+ val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
+ return powerManager.isIgnoringBatteryOptimizations(context.packageName)
}
@SuppressLint("BatteryLife")
- override fun request() = tryStartActivity(
- Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse("package:" + context.packageName))
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- )
+ override fun request() = Intent()
+ .setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
+ .setData("package:${context.packageName}".toUri())
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .let { tryStartActivity(it) }
- override fun revoke() = tryStartActivity(
- Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
- .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- )
+ override fun revoke() = Intent()
+ .setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS)
+ .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ .let { tryStartActivity(it) }
- private fun tryStartActivity(i: Intent): Boolean {
- return try {
- context.startActivity(i)
- true
- } catch (e: ActivityNotFoundException) {
- e.printStackTrace()
- ViewUtils.showToast(context, R.string.text_failed)
- false
- }
- }
+ private fun tryStartActivity(i: Intent) = runCatching {
+ context.startActivity(i)
+ }.onFailure {
+ it.printStackTrace()
+ ViewUtils.showToast(context, R.string.text_failed)
+ }.isSuccess
}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/permission/ManageAllFilesPermission.kt b/app/src/main/java/org/autojs/autojs/permission/ManageAllFilesPermission.kt
index 61edf505..51afe122 100644
--- a/app/src/main/java/org/autojs/autojs/permission/ManageAllFilesPermission.kt
+++ b/app/src/main/java/org/autojs/autojs/permission/ManageAllFilesPermission.kt
@@ -76,7 +76,7 @@ class ManageAllFilesPermission(override val context: Context) : PermissionItemHe
String.format(
"%s\n\n%s",
context.getString(R.string.text_all_files_access_is_needed),
- context.getString(R.string.text_click_ok_to_go_to_access_settings),
+ context.getString(R.string.text_click_ok_to_go_to_settings),
)
)
.widgetThemeColor()
diff --git a/app/src/main/java/org/autojs/autojs/storage/database/Database.java b/app/src/main/java/org/autojs/autojs/storage/database/Database.java
index 3eb0b6af..71eaf5ac 100644
--- a/app/src/main/java/org/autojs/autojs/storage/database/Database.java
+++ b/app/src/main/java/org/autojs/autojs/storage/database/Database.java
@@ -4,17 +4,16 @@ import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
+import io.reactivex.Flowable;
+import io.reactivex.Observable;
+import io.reactivex.schedulers.Schedulers;
+import io.reactivex.subjects.PublishSubject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
-import io.reactivex.Flowable;
-import io.reactivex.Observable;
-import io.reactivex.schedulers.Schedulers;
-import io.reactivex.subjects.PublishSubject;
-
public abstract class Database {
private final SQLiteDatabase mWritableSQLiteDatabase;
@@ -148,26 +147,22 @@ public abstract class Database {
return new String[]{String.valueOf(value)};
}
- private static class CursorIterator implements Iterator {
-
- private final Cursor mCursor;
-
- private CursorIterator(Cursor cursor) {
- mCursor = cursor;
- }
+ private record CursorIterator(Cursor cursor) implements Iterator {
@Override
public boolean hasNext() {
- boolean next = mCursor.moveToNext();
+ boolean next = cursor.moveToNext();
if (!next) {
- mCursor.close();
+ cursor.close();
}
return next;
}
@Override
public Cursor next() {
- return mCursor;
+ return cursor;
}
+
}
+
}
diff --git a/app/src/main/java/org/autojs/autojs/timing/AlarmTimedTaskScheduler.kt b/app/src/main/java/org/autojs/autojs/timing/AlarmTimedTaskScheduler.kt
new file mode 100644
index 00000000..d366d525
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/AlarmTimedTaskScheduler.kt
@@ -0,0 +1,46 @@
+package org.autojs.autojs.timing
+
+import android.app.AlarmManager
+import android.app.PendingIntent
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import org.autojs.autojs.timing.TaskReceiver.EXTRA_TASK_ID
+
+object AlarmTimedTaskScheduler : TimedTaskBackend {
+
+ private const val LOG_TAG = "AlarmTimedTask"
+
+ const val ACTION_RUN_ALARM_TIMED_TASK = "org.autojs.autojs.timing.ACTION_RUN_ALARM_TIMED_TASK"
+
+ override fun cancel(context: Context, task: TimedTask) {
+ val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ am.cancel(buildPendingIntent(context, task.id))
+ }
+
+ override fun schedule(context: Context, task: TimedTask, triggerAtMillis: Long) {
+ val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ val pi = buildPendingIntent(context, task.id)
+ try {
+ am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, pi)
+ } catch (e: Exception) {
+ // When reaching exceptions like "maximum 500 alarms per UID", fall back to WorkManager to avoid failure.
+ // zh-CN: 达到 "每 UID 最多 500 个闹钟" 等异常时, 退回到 WorkManager, 避免失败.
+ Log.e(LOG_TAG, "Failed to schedule exact alarm, fallback to WorkManager. taskId=${task.id}, cause=${e.message}")
+ WorkTimedTaskScheduler.schedule(context, task, triggerAtMillis)
+ }
+ }
+
+ override fun schedulePeriodicCheck(context: Context, intervalMillis: Long) {
+ WorkTimedTaskScheduler.schedulePeriodicCheck(context, intervalMillis)
+ }
+
+ private fun buildPendingIntent(context: Context, taskId: Long): PendingIntent {
+ val intent = Intent(context, TimedTaskAlarmReceiver::class.java)
+ .setAction(ACTION_RUN_ALARM_TIMED_TASK)
+ .putExtra(EXTRA_TASK_ID, taskId)
+ val flags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
+ return PendingIntent.getBroadcast(context, taskId.toInt(), intent, flags)
+ }
+
+}
diff --git a/app/src/main/java/org/autojs/autojs/timing/BootCompletedReceiver.kt b/app/src/main/java/org/autojs/autojs/timing/BootCompletedReceiver.kt
new file mode 100644
index 00000000..bb77b67a
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/BootCompletedReceiver.kt
@@ -0,0 +1,18 @@
+package org.autojs.autojs.timing
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+
+class BootCompletedReceiver : BroadcastReceiver() {
+
+ override fun onReceive(context: Context, intent: Intent) {
+ val action = intent.action ?: return
+ if (action == Intent.ACTION_BOOT_COMPLETED || action == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
+ Log.d("BootCompletedReceiver", "System boot completed, re-initializing timed tasks")
+ TimedTaskScheduler.init(context.applicationContext)
+ }
+ }
+
+}
diff --git a/app/src/main/java/org/autojs/autojs/timing/ExactAlarmPermissionHelper.kt b/app/src/main/java/org/autojs/autojs/timing/ExactAlarmPermissionHelper.kt
new file mode 100644
index 00000000..2795f7e6
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/ExactAlarmPermissionHelper.kt
@@ -0,0 +1,62 @@
+package org.autojs.autojs.timing
+
+import android.app.AlarmManager
+import android.content.Context
+import android.content.Intent
+import android.os.Build
+import android.provider.Settings
+import androidx.core.net.toUri
+import org.autojs.autojs.extension.MaterialDialogExtensions.widgetThemeColor
+import org.autojs.autojs.ui.common.NotAskAgainDialog
+import org.autojs.autojs.util.StringUtils.key
+import org.autojs.autojs.util.ViewUtils
+import org.autojs.autojs6.R
+
+object ExactAlarmPermissionHelper {
+
+ fun isExactAlarmRuntimeGateRequired() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
+
+ fun canScheduleExactAlarms(context: Context): Boolean {
+ if (!isExactAlarmRuntimeGateRequired()) return true
+ val am = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
+ return am.canScheduleExactAlarms()
+ }
+
+ fun requestExactAlarmPermission(context: Context): Boolean {
+ val intent = Intent()
+ .setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
+ .setData("package:${context.packageName}".toUri())
+ return runCatching { context.startActivity(intent) }.isSuccess
+ }
+
+ // Check canScheduleExactAlarms permission and prompt user if needed.
+ // zh-CN: 在此检查 canScheduleExactAlarms 并按需提示用户打开权限.
+ fun checkExactAlarmPermission(context: Context) {
+ if (canScheduleExactAlarms(context)) return
+ NotAskAgainDialog.Builder(context, key(R.string.key_timed_task_backend_alarm))
+ .title(R.string.text_prompt)
+ .content(
+ String.format(
+ "%s\n\n%s",
+ context.getString(R.string.text_allow_setting_alarms_and_reminders_is_recommended),
+ context.getString(R.string.text_click_ok_to_go_to_settings),
+ )
+ )
+ .widgetThemeColor()
+ .negativeText(R.string.text_cancel)
+ .negativeColorRes(R.color.dialog_button_default)
+ .onNegative { dialog, _ -> dialog.dismiss() }
+ .positiveText(R.string.dialog_button_confirm)
+ .positiveColorRes(R.color.dialog_button_attraction)
+ .onPositive { dialog, _ ->
+ when {
+ requestExactAlarmPermission(context) -> dialog.dismiss()
+ else -> ViewUtils.showSnack(dialog.view, R.string.failed_to_go_to_access_settings, true)
+ }
+ }
+ .cancelable(false)
+ .autoDismiss(false)
+ .show()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/timing/JobTimedTaskScheduler.kt b/app/src/main/java/org/autojs/autojs/timing/JobTimedTaskScheduler.kt
new file mode 100644
index 00000000..fdd0ba32
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/JobTimedTaskScheduler.kt
@@ -0,0 +1,57 @@
+package org.autojs.autojs.timing
+
+import android.content.Context
+import com.evernote.android.job.Job
+import com.evernote.android.job.JobManager
+import com.evernote.android.job.JobRequest
+
+object JobTimedTaskScheduler : TimedTaskBackend {
+
+ private const val LOG_TAG = "JobTimedTaskScheduler"
+
+ private const val JOB_TAG_CHECK_TASKS = "checkTasks"
+
+ override fun cancel(context: Context, task: TimedTask) {
+ JobManager.instance().cancelAllForTag(task.id.toString())
+ }
+
+ override fun schedule(context: Context, task: TimedTask, triggerAtMillis: Long) {
+ val delay = (triggerAtMillis - System.currentTimeMillis()).coerceAtLeast(0)
+ JobRequest.Builder(task.id.toString())
+ .setExact(delay)
+ .build()
+ .schedule()
+ }
+
+ override fun schedulePeriodicCheck(context: Context, intervalMillis: Long) {
+ JobManager.create(context).addJobCreator { tag: String ->
+ when (tag) {
+ JOB_TAG_CHECK_TASKS -> CheckTasksJob(context)
+ else -> TimedTaskJob(context)
+ }
+ }
+ JobRequest.Builder(JOB_TAG_CHECK_TASKS)
+ .setPeriodic(intervalMillis)
+ .build()
+ .scheduleAsync()
+ }
+
+ private class TimedTaskJob(private val context: Context) : Job() {
+ override fun onRunJob(params: Params): Result {
+ val id = params.tag.toLong()
+ val task = TimedTaskManager.getTimedTask(id)
+ println("$LOG_TAG: onRunJob: id = $id, task = $task")
+ task ?: return Result.FAILURE
+ TimedTaskScheduler.runTask(context, task)
+ return Result.SUCCESS
+ }
+ }
+
+ private class CheckTasksJob(private val context: Context) : Job() {
+ override fun onRunJob(params: Params): Result {
+ TimedTaskScheduler.checkTasks(context, false)
+ return Result.SUCCESS
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskAlarmReceiver.kt b/app/src/main/java/org/autojs/autojs/timing/TimedTaskAlarmReceiver.kt
new file mode 100644
index 00000000..b3f0f77d
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskAlarmReceiver.kt
@@ -0,0 +1,25 @@
+package org.autojs.autojs.timing
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import org.autojs.autojs.external.ScriptIntents
+import org.autojs.autojs.timing.AlarmTimedTaskScheduler.ACTION_RUN_ALARM_TIMED_TASK
+import org.autojs.autojs.timing.TaskReceiver.EXTRA_TASK_ID
+
+class TimedTaskAlarmReceiver : BroadcastReceiver() {
+
+ override fun onReceive(context: Context, intent: Intent) {
+ if (intent.action != ACTION_RUN_ALARM_TIMED_TASK) return
+ val id = intent.getLongExtra(EXTRA_TASK_ID, -1L)
+ if (id <= 0) return
+ val task = TimedTaskManager.getTimedTask(id)
+ Log.d("TimedTaskAlarmReceiver", "onReceive: id=$id, task=$task")
+ if (task == null) return
+ val runIntent = task.createIntent()
+ ScriptIntents.handleIntent(context, runIntent)
+ TimedTaskManager.notifyTaskFinished(task.id)
+ }
+
+}
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskBackend.kt b/app/src/main/java/org/autojs/autojs/timing/TimedTaskBackend.kt
new file mode 100644
index 00000000..098d040c
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskBackend.kt
@@ -0,0 +1,17 @@
+package org.autojs.autojs.timing
+
+import android.content.Context
+
+interface TimedTaskBackend {
+
+ fun init(context: Context) {
+ /* Nothing to do by default. */
+ }
+
+ fun cancel(context: Context, task: TimedTask)
+
+ fun schedule(context: Context, task: TimedTask, triggerAtMillis: Long)
+
+ fun schedulePeriodicCheck(context: Context, intervalMillis: Long)
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.kt b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.kt
index 1f2a385d..fff711a9 100644
--- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.kt
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskManager.kt
@@ -20,9 +20,9 @@ import org.autojs.autojs.util.Observers
*/
object TimedTaskManager {
- private val globalAppContext = GlobalAppContext.get()
- private val mTimedTaskDatabase = TimedTaskDatabase(globalAppContext)
- private val mIntentTaskDatabase = IntentTaskDatabase(globalAppContext)
+ private val globalAppContext by lazy { GlobalAppContext.get() }
+ private val mTimedTaskDatabase by lazy { TimedTaskDatabase(globalAppContext) }
+ private val mIntentTaskDatabase by lazy { IntentTaskDatabase(globalAppContext) }
@JvmStatic
val allTasks: Flowable
@@ -96,7 +96,7 @@ object TimedTaskManager {
@JvmStatic
@SuppressLint("CheckResult")
fun removeTask(timedTask: TimedTask) {
- cancel(timedTask)
+ cancel(globalAppContext, timedTask)
mTimedTaskDatabase.delete(timedTask)
.subscribe(Observers.emptyConsumer()) { obj: Throwable -> obj.printStackTrace() }
}
@@ -115,7 +115,7 @@ object TimedTaskManager {
@JvmStatic
fun removeTaskSync(timedTask: TimedTask): Boolean {
- cancel(timedTask)
+ cancel(globalAppContext, timedTask)
return mTimedTaskDatabase.deleteSync(timedTask) > 0
}
@@ -129,7 +129,7 @@ object TimedTaskManager {
fun updateTask(task: TimedTask) {
mTimedTaskDatabase.update(task)
.subscribe(Observers.emptyConsumer()) { obj: Throwable -> obj.printStackTrace() }
- cancel(task)
+ cancel(globalAppContext, task)
scheduleTaskIfNeeded(globalAppContext, task, false)
}
@@ -137,7 +137,7 @@ object TimedTaskManager {
@SuppressLint("CheckResult")
fun updateTaskSync(task: TimedTask): Boolean {
val id = mTimedTaskDatabase.updateSync(task)
- cancel(task)
+ cancel(globalAppContext, task)
scheduleTaskIfNeeded(globalAppContext, task, false)
return id > 0
}
diff --git a/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.kt b/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.kt
index d1232e01..04d7f4d5 100644
--- a/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.kt
+++ b/app/src/main/java/org/autojs/autojs/timing/TimedTaskScheduler.kt
@@ -2,36 +2,80 @@ package org.autojs.autojs.timing
import android.annotation.SuppressLint
import android.content.Context
-import android.util.Log
-import com.evernote.android.job.Job
-import com.evernote.android.job.JobManager
-import com.evernote.android.job.JobRequest
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
+import org.autojs.autojs.core.pref.Pref
import org.autojs.autojs.external.ScriptIntents.handleIntent
+import org.autojs.autojs.util.StringUtils.key
+import org.autojs.autojs6.R
import java.util.concurrent.TimeUnit
/**
* Created by Stardust on Nov 27, 2017.
+ * Modified by SuperMonster003 as of Oct 27, 2025.
*/
object TimedTaskScheduler {
private const val LOG_TAG = "TimedTaskScheduler"
- private const val JOB_TAG_CHECK_TASKS = "checkTasks"
private val SCHEDULE_TASK_MIN_TIME = TimeUnit.DAYS.toMillis(2)
+ private val SCHEDULE_PERIODIC_CHECK_TIME = TimeUnit.MINUTES.toMillis(20)
- @SuppressLint("CheckResult")
- fun checkTasks(context: Context?, force: Boolean) {
- Log.d(LOG_TAG, "check tasks: force = $force")
- TimedTaskManager.allTasks
- .subscribeOn(Schedulers.io())
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe { timedTask: TimedTask -> scheduleTaskIfNeeded(context, timedTask, force) }
+ private lateinit var backend: TimedTaskBackend
+
+ // Alarm quota reserved for the current application (not exceeding 500).
+ // zh-CN: 为当前应用保留的闹钟配额 (不超过 500).
+ private const val MAX_ALARM_SLOTS = 450
+
+ fun init(context: Context) {
+ val backend = run initBackend@{
+ val keyRes = R.string.key_timed_task_backend
+ val defRes = R.string.default_key_timed_task_backend
+ when (val prefValue = Pref.getString(keyRes, defRes)) {
+ key(R.string.key_timed_task_backend_alarm) -> AlarmTimedTaskScheduler
+ key(R.string.key_timed_task_backend_work) -> WorkTimedTaskScheduler
+ key(R.string.key_timed_task_backend_job) -> JobTimedTaskScheduler
+ else -> throw RuntimeException("Unknown backend: $prefValue")
+ }
+ }.also { this.backend = it }
+
+ println("$LOG_TAG: init backend = ${TimedTaskScheduler.backend}")
+ backend.init(context)
+ backend.schedulePeriodicCheck(context, SCHEDULE_PERIODIC_CHECK_TIME)
+
+ checkTasks(context, true)
}
@JvmStatic
- fun scheduleTaskIfNeeded(context: Context?, timedTask: TimedTask, force: Boolean) {
+ fun cancel(context: Context, timedTask: TimedTask) {
+ backend.cancel(context, timedTask)
+ println("$LOG_TAG: cancel task (${backend}): task = $timedTask")
+ }
+
+ fun runTask(context: Context, task: TimedTask) {
+ println("$LOG_TAG: run task: task = $task")
+ val intent = task.createIntent()
+ handleIntent(context, intent)
+ TimedTaskManager.notifyTaskFinished(task.id)
+ }
+
+ @SuppressLint("CheckResult")
+ fun checkTasks(context: Context, force: Boolean) {
+ println("$LOG_TAG: check tasks: force = $force")
+ when (backend) {
+ AlarmTimedTaskScheduler -> TimedTaskManager.allTasksAsList
+ .sortedBy { it.getNextTime(context) }
+ .take(MAX_ALARM_SLOTS)
+ .forEach { timedTask -> scheduleTaskIfNeeded(context, timedTask, force) }
+ else -> TimedTaskManager.allTasks
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { timedTask -> scheduleTaskIfNeeded(context, timedTask, force) }
+ }
+ }
+
+ @JvmStatic
+ fun scheduleTaskIfNeeded(context: Context, timedTask: TimedTask, force: Boolean) {
val millis = timedTask.getNextTime(context)
if (millis <= System.currentTimeMillis()) {
runTask(context, timedTask)
@@ -45,70 +89,21 @@ object TimedTaskScheduler {
}
@Synchronized
- private fun scheduleTask(context: Context?, timedTask: TimedTask, millis: Long, force: Boolean) {
+ private fun scheduleTask(context: Context, timedTask: TimedTask, millis: Long, force: Boolean) {
if (!force && timedTask.isScheduled) {
return
}
- val timeWindow = millis - System.currentTimeMillis()
timedTask.isScheduled = true
+ val timeWindow = millis - System.currentTimeMillis()
TimedTaskManager.updateTaskWithoutReScheduling(timedTask)
if (timeWindow <= 0) {
runTask(context, timedTask)
return
}
- cancel(timedTask)
- Log.d(LOG_TAG, "schedule task: task = $timedTask, millis = $millis, timeWindow = $timeWindow")
- JobRequest.Builder(timedTask.id.toString())
- .setExact(timeWindow)
- .build()
- .schedule()
+ cancel(context, timedTask)
+ println("$LOG_TAG: schedule task: task = $timedTask, millis = $millis, timeWindow = $timeWindow")
+
+ backend.schedule(context, timedTask, millis)
}
- @JvmStatic
- fun cancel(timedTask: TimedTask) {
- val cancelCount = JobManager.instance().cancelAllForTag(timedTask.id.toString())
- Log.d(LOG_TAG, "cancel task: task = $timedTask, cancel = $cancelCount")
- }
-
- fun init(context: Context) {
- JobManager.create(context).addJobCreator { tag: String ->
- if (tag == JOB_TAG_CHECK_TASKS) {
- return@addJobCreator CheckTasksJob(context)
- } else {
- return@addJobCreator TimedTaskJob(context)
- }
- }
- JobRequest.Builder(JOB_TAG_CHECK_TASKS)
- .setPeriodic(TimeUnit.MINUTES.toMillis(20))
- .build()
- .scheduleAsync()
- checkTasks(context, true)
- }
-
- private fun runTask(context: Context?, task: TimedTask) {
- Log.d(LOG_TAG, "run task: task = $task")
- val intent = task.createIntent()
- handleIntent(context, intent)
- TimedTaskManager.notifyTaskFinished(task.id)
- }
-
- private class TimedTaskJob(private val mContext: Context) : Job() {
- override fun onRunJob(params: Params): Result {
- val id = params.tag.toLong()
- val task = TimedTaskManager.getTimedTask(id)
- Log.d(LOG_TAG, "onRunJob: id = $id, task = $task")
- if (task == null) {
- return Result.FAILURE
- }
- runTask(mContext, task)
- return Result.SUCCESS
- }
- }
-
- private class CheckTasksJob(private val mContext: Context) : Job() {
- override fun onRunJob(params: Params): Result {
- checkTasks(mContext, false)
- return Result.SUCCESS
- }
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/timing/WorkTimedTaskScheduler.kt b/app/src/main/java/org/autojs/autojs/timing/WorkTimedTaskScheduler.kt
new file mode 100644
index 00000000..b323d51c
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/timing/WorkTimedTaskScheduler.kt
@@ -0,0 +1,66 @@
+package org.autojs.autojs.timing
+
+import android.content.Context
+import androidx.work.Constraints
+import androidx.work.CoroutineWorker
+import androidx.work.ExistingPeriodicWorkPolicy
+import androidx.work.ExistingWorkPolicy
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.PeriodicWorkRequestBuilder
+import androidx.work.WorkManager
+import androidx.work.WorkerParameters
+import org.autojs.autojs.external.ScriptIntents
+import java.util.concurrent.TimeUnit
+
+object WorkTimedTaskScheduler : TimedTaskBackend {
+
+ private const val UNIQUE_CHECK_NAME = "work-timed-task-periodic-check"
+
+ override fun cancel(context: Context, task: TimedTask) {
+ WorkManager.getInstance(context).cancelAllWorkByTag(task.id.toString())
+ }
+
+ override fun schedule(context: Context, task: TimedTask, triggerAtMillis: Long) {
+ val delay = triggerAtMillis - System.currentTimeMillis()
+ val request = OneTimeWorkRequestBuilder()
+ .setInitialDelay(delay.coerceAtLeast(0), TimeUnit.MILLISECONDS)
+ .addTag(task.id.toString())
+ .setConstraints(Constraints.NONE)
+ .build()
+ WorkManager.getInstance(context).enqueueUniqueWork(
+ "work-timed-task-id-${task.id}",
+ ExistingWorkPolicy.REPLACE,
+ request,
+ )
+ }
+
+ override fun schedulePeriodicCheck(context: Context, intervalMillis: Long) {
+ val request = PeriodicWorkRequestBuilder(intervalMillis, TimeUnit.MILLISECONDS)
+ .build()
+ WorkManager.getInstance(context).enqueueUniquePeriodicWork(
+ UNIQUE_CHECK_NAME,
+ ExistingPeriodicWorkPolicy.UPDATE,
+ request,
+ )
+ }
+
+ internal class TimedTaskWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) {
+ override suspend fun doWork(): Result {
+ val tags = this.tags // contains taskId string. (zh-CN: 包含 taskId 字符串.)
+ val taskId = tags.firstNotNullOfOrNull { it.toLongOrNull() } ?: return Result.failure()
+ val task = TimedTaskManager.getTimedTask(taskId) ?: return Result.failure()
+ val intent = task.createIntent()
+ ScriptIntents.handleIntent(applicationContext, intent)
+ TimedTaskManager.notifyTaskFinished(task.id)
+ return Result.success()
+ }
+ }
+
+ internal class CheckTasksWorker(appContext: Context, params: WorkerParameters) : CoroutineWorker(appContext, params) {
+ override suspend fun doWork(): Result {
+ TimedTaskScheduler.checkTasks(applicationContext, false)
+ return Result.success()
+ }
+ }
+
+}
diff --git a/app/src/main/java/org/autojs/autojs/ui/settings/TimedTaskBackendPreference.kt b/app/src/main/java/org/autojs/autojs/ui/settings/TimedTaskBackendPreference.kt
new file mode 100644
index 00000000..a9c4ecea
--- /dev/null
+++ b/app/src/main/java/org/autojs/autojs/ui/settings/TimedTaskBackendPreference.kt
@@ -0,0 +1,32 @@
+package org.autojs.autojs.ui.settings
+
+import android.content.Context
+import android.util.AttributeSet
+import com.afollestad.materialdialogs.MaterialDialog
+import org.autojs.autojs.theme.preference.MaterialListPreference
+import org.autojs.autojs.timing.ExactAlarmPermissionHelper
+import org.autojs.autojs.timing.TimedTaskScheduler
+import org.autojs.autojs6.R
+
+class TimedTaskBackendPreference : MaterialListPreference {
+
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
+
+ constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
+
+ constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
+
+ constructor(context: Context) : super(context)
+
+ override fun onChangeConfirmed(dialog: MaterialDialog) {
+ super.onChangeConfirmed(dialog)
+
+ when (dialog.items?.get(dialog.selectedIndex)?.toString()) {
+ prefContext.getString(R.string.entry_timed_task_backend_alarm) -> {
+ ExactAlarmPermissionHelper.checkExactAlarmPermission(prefContext)
+ }
+ }
+ TimedTaskScheduler.init(prefContext)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt b/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt
index 4c861f7c..bd209954 100644
--- a/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt
+++ b/app/src/main/java/org/autojs/autojs/ui/settings/WorkingDirectoryPreference.kt
@@ -68,7 +68,7 @@ class WorkingDirectoryPreference : MaterialPreference {
}
override fun build(): MaterialDialog = MaterialDialog.Builder(context)
- .title(R.string.text_change_working_dir)
+ .title(R.string.text_working_dir_path)
.customView(R.layout.pref_working_directory, false)
.neutralText(R.string.dialog_button_history)
.neutralColorRes(R.color.dialog_button_hint)
diff --git a/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.kt b/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.kt
index d678832c..ac5309bd 100644
--- a/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.kt
+++ b/app/src/main/java/org/autojs/autojs/ui/timing/TimedTaskSettingActivity.kt
@@ -5,7 +5,6 @@ import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.ConnectivityManager
import android.os.Bundle
-import android.os.PowerManager
import android.provider.Settings
import android.text.TextUtils
import android.util.Log
@@ -34,7 +33,9 @@ import org.autojs.autojs.execution.ExecutionConfig.CREATOR.default
import org.autojs.autojs.external.ScriptIntents
import org.autojs.autojs.external.receiver.DynamicBroadcastReceivers
import org.autojs.autojs.model.script.ScriptFile
+import org.autojs.autojs.permission.IgnoreBatteryOptimizationsPermission
import org.autojs.autojs.theme.ThemeColorHelper
+import org.autojs.autojs.timing.ExactAlarmPermissionHelper
import org.autojs.autojs.timing.IntentTask
import org.autojs.autojs.timing.TaskReceiver
import org.autojs.autojs.timing.TimedTask
@@ -351,35 +352,49 @@ class TimedTaskSettingActivity : BaseActivity() {
return true
}
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == R.id.action_done) {
- if ((getSystemService(POWER_SERVICE) as PowerManager).isIgnoringBatteryOptimizations(packageName)) {
- createOrUpdateTask()
- return true
+ override fun onOptionsItemSelected(item: MenuItem): Boolean = when (item.itemId) {
+ R.id.action_done -> when {
+ !IgnoreBatteryOptimizationsPermission(this).has() -> {
+ try {
+ @SuppressLint("BatteryLife")
+ val intent = Intent()
+ .setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
+ .setData("package:$packageName".toUri())
+ @Suppress("DEPRECATION")
+ startActivityForResult(intent, REQUEST_CODE_IGNORE_BATTERY)
+ } catch (e: ActivityNotFoundException) {
+ e.printStackTrace()
+ createOrUpdateTask()
+ }
}
- try {
- @SuppressLint("BatteryLife")
- val intent = Intent()
- .setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)
- .setData("package:$packageName".toUri())
- @Suppress("DEPRECATION")
- startActivityForResult(intent, REQUEST_CODE_IGNORE_BATTERY)
- } catch (e: ActivityNotFoundException) {
- e.printStackTrace()
+ !ExactAlarmPermissionHelper.canScheduleExactAlarms(this) -> {
+ try {
+ val intent = Intent()
+ .setAction(Settings.ACTION_REQUEST_SCHEDULE_EXACT_ALARM)
+ .setData("package:$packageName".toUri())
+ @Suppress("DEPRECATION")
+ startActivityForResult(intent, REQUEST_CODE_SCHEDULE_EXACT_ALARM)
+ } catch (e: ActivityNotFoundException) {
+ e.printStackTrace()
+ createOrUpdateTask()
+ }
+ }
+ else -> {
createOrUpdateTask()
}
- return true
- }
- return super.onOptionsItemSelected(item)
+ }.let { true }
+ else -> super.onOptionsItemSelected(item)
}
@Suppress("OVERRIDE_DEPRECATION")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
- if (requestCode == REQUEST_CODE_IGNORE_BATTERY) {
- Log.d(LOG_TAG, "result code = $requestCode")
- createOrUpdateTask()
+ when (requestCode) {
+ REQUEST_CODE_IGNORE_BATTERY, REQUEST_CODE_SCHEDULE_EXACT_ALARM -> {
+ Log.d(LOG_TAG, "result code = $requestCode")
+ createOrUpdateTask()
+ }
+ else -> super.onActivityResult(requestCode, resultCode, data)
}
- super.onActivityResult(requestCode, resultCode, data)
}
private fun createOrUpdateTask() {
@@ -447,6 +462,7 @@ class TimedTaskSettingActivity : BaseActivity() {
private val DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd")
private const val REQUEST_CODE_IGNORE_BATTERY = 27101
+ private const val REQUEST_CODE_SCHEDULE_EXACT_ALARM = 27102
private const val LOG_TAG = "TimedTaskSettings"
@JvmField
diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml
index 7844a1ac..98ca7f48 100644
--- a/app/src/main/res/values-ar/strings.xml
+++ b/app/src/main/res/values-ar/strings.xml
@@ -474,7 +474,7 @@
مسح السيناريو قبل التنفيذ
تحديثات مسح الحالات التي تم فحصها
انقر فوق العنصر لإزالته
- انقر فوق \"نعم\" للانتقال إلى الإعدادات
+ انقر فوق \"نعم\" للانتقال إلى الإعدادات
التشغيل المتكرر
وضع العميل
استنساخ مكتبة ألوان
@@ -1068,5 +1068,10 @@
عند تفعيل المفتاح (الوضع الافتراضي): سيتم تغليف القيم المُعادة من أساليب Java من الأنواع Number/Boolean/Character ككائنات Java وإتاحتها للسكريبت (باستثناء String). ستكون typeof هي \"object\" و species هي \"JavaObject\"، ويمكن استدعاء أساليب Java، مما يساعد على الحفاظ على خصائص الأنواع الدقيقة في Java وحل زيادة التحميل (overload).\n\nعند إيقاف المفتاح: لن تُغلف الأنواع المذكورة، وستُعرض مباشرة كقيم أولية في JavaScript (number/boolean/سلسلة ذات حرف واحد). ستكون typeof هي نوع JavaScript الموافق، وهو أقرب لدلالات ونظام JavaScript البيئي. لا يزال بالإمكان إعلان مغلّف Java صراحةً باستخدام new، مثل new java.lang.Boolean(true).\n\nانظر: http://issues.autojs6.com/435
ستُغلَّف الأنواع البدائية في Java ككائنات Java داخل السكربت
تغليف الأنواع البدائية في Java
+ محرك جدولة المهام المؤقتة
+ يتحكم في الآلية الأساسية لتشغيل السكربتات بشكل مجدول.\n\nAlarmManager: عبر منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن أن تصبح المهام أقرب إلى التنفيذ في الوقت المحدد.\nWorkManager: صديق للنظام؛ مناسب للمهام غير الحرجة التي تتحمل بعض التأخير.\nJobScheduler: تنفيذ قديم محفوظ للتوافق؛ احتمال التأخير أعلى.
+ فشل فتح صفحة الإعدادات
+ يُوصى بمنح إذن \"السماح بتعيين المنبّهات والتذكيرات\" لضمان تنفيذ المهام المجدولة بأكبر قدر ممكن من الدقة حتى عند إيقاف الشاشة أو في وضع السكون
+ حالات الاستخدام والفروقات:\n\n1) AlarmManager\nمناسب للمهام الحسّاسة للتوقيت، مثل [التذكيرات/السكربتات الدقيقة التوقيت/...].\nعلى Android 12+ ومع منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن التنفيذ بدقة أكبر حتى مع إيقاف الشاشة أو في وضع السكون.\nبدون الإذن قد يقلل النظام الدقة أو يؤخر التنفيذ.\n\n2) WorkManager\nمناسب للمهام التي لا تتطلب دقة زمنية صارمة مثل [مزامنة غير حرجة/تنظيف/إحصاءات/...].\nيتم الجدولة وفق [حالة البطارية/الشبكة/الشحن/سياسات السكون/...], وقد تتأخر المهام عند إيقاف الشاشة أو في وضع السكون.\nلا يضمن الدقة الزمنية لكنه يوفر مزايا في [إتمام موثوق/إعادة المحاولة عند الفشل/سلاسل المهام/إزالة التكرار].\n\n3) JobScheduler\nتنفيذ تاريخي لأغراض التوافق.\nفي إصدارات أندرويد الحديثة قد تحدث تأخيرات أكبر.\nلا يُنصح به إلا لاعتبارات التوافق.
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
index 54111f5f..a574e238 100644
--- a/app/src/main/res/values-en/strings.xml
+++ b/app/src/main/res/values-en/strings.xml
@@ -469,7 +469,7 @@
Clear pre-execute script
Clear updates checked states
Click the item to remove
- Click \"OK\" to go to settings
+ Click \"OK\" to go to settings
Frequent operation
Client mode
Clone a color library
@@ -1063,5 +1063,10 @@
Switch ON (default): results of Java methods that are instances of Number/Boolean/Character are wrapped as Java objects and exposed to scripts (String excluded). typeof is \"object\", species is \"JavaObject\"; Java methods remain accessible, which helps retain precise Java type traits and overload resolution.\n\nSwitch OFF: the above types are no longer wrapped and are exposed directly as JavaScript primitives (number/boolean/one‑character string). typeof is the corresponding JavaScript type, aligning better with JavaScript semantics and ecosystem. You can still explicitly create a Java wrapper via new, e.g. new java.lang.Boolean(true).\n\nSee: http://issues.autojs6.com/435
Java primitive types will be wrapped as Java objects in scripts
Java primitive wrapping
+ Timed task scheduling engine
+ 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.
+ Failed to open the settings page
+ 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
+ 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 don’t 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 can’t 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.
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
index f52a3562..0c876177 100644
--- a/app/src/main/res/values-es/strings.xml
+++ b/app/src/main/res/values-es/strings.xml
@@ -472,7 +472,7 @@
Borrar script de pre-ejecución
Borrar los estados de comprobación de las actualizaciones
Haga clic en el elemento a eliminar
- Haga clic en \"Aceptar\" para ir a la configuración
+ Haga clic en \"Aceptar\" para ir a la configuración
Funcionamiento frecuente
Modo cliente
Clonar biblioteca de colores
@@ -1066,5 +1066,10 @@
Con el interruptor activado (predeterminado): los valores devueltos por métodos Java de tipo Number/Boolean/Character se envuelven como objetos Java y se exponen al script (String excluido). typeof es \"object\", species es \"JavaObject\"; se pueden invocar métodos de Java, lo que ayuda a conservar las características de tipo precisas de Java y la resolución de sobrecargas.\n\nCon el interruptor desactivado: no se envuelven los tipos anteriores y se exponen directamente como primitivos de JavaScript (number/boolean/cadena de un solo carácter). typeof corresponde al tipo de JavaScript respectivo, más acorde con la semántica/ecosistema de JavaScript. Aun así, puede declarar explícitamente un envoltorio de Java con new, por ejemplo new java.lang.Boolean(true).\n\nConsulte: http://issues.autojs6.com/435
Los tipos primitivos de Java se envolverán como objetos Java en los scripts
Envoltorio de primitivos de Java
+ Motor de programación de tareas temporizadas
+ 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.
+ No se pudo abrir la página de ajustes
+ 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
+ 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.
diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml
index 7cc98d3f..3cde301b 100644
--- a/app/src/main/res/values-fr/strings.xml
+++ b/app/src/main/res/values-fr/strings.xml
@@ -429,7 +429,7 @@
Code de la version de l\'application
Nom de la version de l\'application
Appearance
- Au moins un champ parmi « Nom complet, Nom de l\'organisation, Unité organisationnelle, Code du pays, État ou province, Ville ou localité, Rue » doit être renseigné
+ Au moins un champ parmi \"Nom complet, Nom de l\'organisation, Unité organisationnelle, Code du pays, État ou province, Ville ou localité, Rue\" doit être renseigné
Attribut
Vérification automatique des mises à jour
Vérification automatique des mises à jour et affichage d\'un snackbar sur la page d\'accueil
@@ -472,7 +472,7 @@
Effacer le script de pré-exécution
Effacer les états vérifiés des mises à jour
Cliquez sur l\'élément à supprimer
- Cliquez sur \"OK\" pour accéder aux paramètres.
+ Cliquez sur \"OK\" pour accéder aux paramètres.
Une opération fréquente
Mode client
Cloner une bibliothèque de couleurs
@@ -1063,8 +1063,13 @@
Écrire les paramètres de sécurité.
Paramètres de sécurité du système, contenant les préférences du système que les applications peuvent lire mais ne sont pas autorisées à écrire.\nIl s\'agit des préférences que l\'utilisateur doit explicitement modifier par le biais de l\'interface utilisateur d\'une application système.\nAvec l\'autorisation de paramètres de sécurité du système, les applications normales peuvent directement modifier les paramètres de sécurité (comme le service d\'accessibilité).
Écrire les paramètres système
- Interrupteur activé (par défaut) : les valeurs retournées par les méthodes Java de type Number/Boolean/Character sont encapsulées comme objets Java et exposées au script (String exclu). typeof vaut \"object\", species vaut \"JavaObject\" ; les méthodes Java restent accessibles, ce qui permet de conserver les caractéristiques de type précises de Java et la résolution de surcharge.\n\nInterrupteur désactivé : les types ci‑dessus ne sont plus encapsulés et sont exposés directement comme primitives JavaScript (number/boolean/chaîne à un seul caractère). typeof correspond au type JavaScript respectif, plus conforme à la sémantique/à l’écosystème JavaScript. Il est toujours possible de déclarer explicitement un wrapper Java avec new, par ex. new java.lang.Boolean(true).\n\nVoir : http://issues.autojs6.com/435
+ Interrupteur activé (par défaut) : les valeurs retournées par les méthodes Java de type Number/Boolean/Character sont encapsulées comme objets Java et exposées au script (String exclu). typeof vaut \"object\", species vaut \"JavaObject\" ; les méthodes Java restent accessibles, ce qui permet de conserver les caractéristiques de type précises de Java et la résolution de surcharge.\n\nInterrupteur désactivé : les types ci‑dessus ne sont plus encapsulés et sont exposés directement comme primitives JavaScript (number/boolean/chaîne à un seul caractère). typeof correspond au type JavaScript respectif, plus conforme à la sémantique/à l\'écosystème JavaScript. Il est toujours possible de déclarer explicitement un wrapper Java avec new, par ex. new java.lang.Boolean(true).\n\nVoir : http://issues.autojs6.com/435
Les types primitifs Java seront exposés comme objets Java dans les scripts
Encapsulation des types primitifs Java
+ Moteur d\'ordonnancement des tâches planifiées
+ 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.
+ Échec d\'ouverture de la page des paramètres
+ 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
+ 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é.
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index c807abb0..a966e6ce 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -82,7 +82,7 @@
ショートカットは, AutoJs6 で特定のアクションを実行することができます. ユーザーは, サポートされているランチャーにこれらのショートカットを表示し, AutoJs6 アプリケーションのドキュメントを読んだり, AutoJs6 の設定ページを起動したりするなど, いくつかのタスクを素早く開始したり, アクティビティを起動したりすることができます
クリックすると, リストアイテムを表示または管理できます.\nリストアイテムを削除するには, 長押しします
ナイトモード (ダークテーマとも呼ばれる) は, Android システムの UI と端末上で動作するアプリケーションの両方に適用され, 弱視のユーザーや明るい光に敏感なユーザーの視認性を向上させ, 誰でも簡単に暗い環境下で端末を使用できるようにします.\n\nフォローシステム AutoJs6 では, Android と同じ Night モードが設定できます.\n常にオン Android のシステム設定に関係なく, 常に Night モードが ON になります.\n常にオフ Android のシステム設定に関係なく, AutoJs6 はナイトモードをオフにします.\n\n注: Follow system オプションは, Android API Level 28 (Android 9) [P] 以上の場合のみです
- Android システムでナイトモードを有効にするには\n- Android API Level 29 (Android 10) [Q] 以上の場合: [設定] -> [ディスプレイ] -> [テーマ].\n- Android API Level 28 (Android 9) [P]: [開発者向けオプション] -> [ナイトモード].\n\nWebView コンポーネント (AutoJs6 のドキュメントページなど) を使って, Web ベースのコンテンツにナイトモード (ダークテーマ) を適用するには, 以下の条件を満たす必要があります.\n1. Android System WebView (または Google Chrome のようなブラウザ) .\n- Android API Level 29 (Android 10) [Q] 以上: バージョン >= 76\n- Android API Level 28 (Android 9) [P]: バージョン >= 105\n2. WebView コンポーネントの Web ベースのコンテンツは, Dark テーマに適合している (CSS や Android XML リソースなどによる)
+ Android システムでナイトモードを有効にするには\n- Android API Level 29 (Android 10) [Q] 以上の場合: [設定] -> [ディスプレイ] -> [テーマ].\n- Android API Level 28 (Android 9) [P]: [開発者向けオプション] -> [ナイトモード].\n\nWebView コンポーネント (AutoJs6 のドキュメントページなど) を使って, Web ベースのコンテンツにナイトモード (ダークテーマ) を適用するには, 以下の条件を満たす必要があります.\n1. Android System WebView (または Google Chrome のようなブラウザ) .\n- Android API Level 29 (Android 10) [Q] 以上: バージョン >= 76\n- Android API Level 28 (Android 9) [P]: バージョン >= 105\n2. WebView コンポーネントの Web ベースのコンテンツは, Dark テーマに適合している (CSS や Android XML リソースなどによる)
異国の root や root アクセスに異常がある場合, root を強制的に root または non-root に設定することができます
バイナリタイプ: 編集不可, ファイル拡張子は \"auto\"\nJavaScript タイプ: 直接編集またはコピー可能, ファイル拡張子は \"js\"
安定モードにするとレイアウト境界を取得する際に安定しますが, 一部の結果が無視されることがあります.\nアクセシビリティサービスの再起動が必要です
@@ -473,7 +473,7 @@
実行前スクリプトのクリア
アップデートのチェック状態をクリアする
削除する項目をクリックします
- \"OK\" をクリックすると設定に進みます
+ \"OK\" をクリックすると設定に進みます
頻繁に行う操作
クライアントモード
カラーライブラリを複製
@@ -1067,5 +1067,10 @@
スイッチ有効 (デフォルト): Java メソッドが返す Number/Boolean/Character は Java オブジェクトとしてラップされ/スクリプトに公開されます (String は除外). typeof は \"object\"/species は \"JavaObject\". Java のメソッドを呼び出せるため/Java の厳密な型特性やオーバーロード解決を保持しやすくなります.\n\n スイッチ無効: 上記の型はラップされず/JavaScript のプリミティブ値 (number/boolean/1 文字の文字列) として直接公開されます. typeof は対応する JavaScript 型となり/JavaScript のセマンティクス/エコシステムにより沿います. 必要なら new によって明示的に Java ラッパーを生成できます (例: new java.lang.Boolean(true)).\n\n 参照: http://issues.autojs6.com/435
Java のプリミティブ型はスクリプト内で Java オブジェクトとしてラップされます
Java プリミティブ型のラップ
+ 定時タスクのスケジューリングエンジン
+ スクリプトを定時で起動するための基盤メカニズムを制御します.\n\nAlarmManager: システムの \"アラームとリマインダーの設定を許可\" 権限を付与すると/より正確な時刻での実行に近づきます.\nWorkManager: システムに優しく/一定の遅延を許容できる非重要タスクに適しています.\nJobScheduler: 旧来の実装で互換性のために残されていますが/遅延が発生しやすいです.
+ 設定画面を開けませんでした
+ 画面消灯中や待機時でもできるだけ正確に実行できるよう/[アラームとリマインダーの設定を許可] 権限の付与を推奨します
+ 利用シーンと違い: \n\n1. AlarmManager\n[リマインダー/厳密な時刻のスクリプト/...] など/時刻精度が重要なタスクに適しています.\nAndroid 12 以降で \"アラームとリマインダーの設定を許可\" 権限がある場合/画面消灯/待機中でも比較的正確に実行されます.\n権限がない場合/システムにより不正確または遅延実行になる可能性があります.\n\n2. WorkManager\n[非重要な同期/クリーンアップ/統計/...] など/厳密な時刻精度を必要としないタスクに適しています.\n[バッテリー/ネットワーク/充電状況/待機ポリシー/...] に応じてスケジューリングされ/消灯/待機中は実行が遅れることがあります.\n時間精度は保証されませんが/[確実な完了/失敗時の再試行/チェーン実行/一意タスクの重複排除] に強みがあります.\n\n3. JobScheduler\n互換性維持のための歴史的実装です.\n新しい Android では遅延が大きくなりやすい傾向があります.\n互換性の必要がない限り/通常は非推奨です.
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index e7273e4c..41ab5a03 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -474,7 +474,7 @@
사전 에코 슈트 스크립트를 지우십시오
확인 된 상태에서 명확한 업데이트
제거하려면 항목을 클릭하십시오
- \"확인\"을 클릭하여 설정으로 이동하십시오
+ \"확인\"을 클릭하여 설정으로 이동하십시오
빈번한 작동
클라이언트 모드
색상 라이브러리 복제
@@ -1068,5 +1068,10 @@
스위치 활성화(기본값): Java 메서드가 반환하는 Number/Boolean/Character 값은 Java 객체로 래핑되어 스크립트에 노출됩니다(String 제외). typeof 는 \"object\", species 는 \"JavaObject\"이며, Java 메서드 호출이 가능해 Java의 정밀한 타입 특성과 오버로드 해석을 보존하는 데 도움이 됩니다.\n\n스위치 비활성화: 위 타입들을 더 이상 래핑하지 않고 JavaScript 원시 값(number/boolean/한 글자 문자열)으로 직접 노출합니다. typeof 는 해당 JavaScript 타입이 되며, JavaScript의 의미론/생태계에 더 가깝습니다. 필요 시 new 키워드로 Java 래퍼를 명시적으로 생성할 수 있습니다(예: new java.lang.Boolean(true)).\n\n참고: http://issues.autojs6.com/435
Java 원시 타입이 스크립트에서 Java 객체로 래핑됩니다
Java 원시 타입 래핑
+ 정시 작업 스케줄링 엔진
+ 스크립트를 정해진 시간에 실행하는 기본 메커니즘을 제어합니다.\n\nAlarmManager: 시스템의 \"알람 및 알림 설정 허용\" 권한을 부여하면 보다 정확한 시각에 가깝게 실행됩니다.\nWorkManager: 시스템 친화적이며, 일정 지연을 허용할 수 있는 비중요 작업에 적합합니다.\nJobScheduler: 호환성 유지를 위해 남겨둔 구방식으로, 지연 발생 가능성이 큽니다.
+ 설정 페이지를 열지 못했습니다
+ 화면이 꺼져 있거나 대기 상태에서도 최대한 정시에 실행되도록, \"알람 및 알림 설정 허용\" 권한 부여를 권장합니다
+ 사용 시나리오 및 차이점:\n\n1. AlarmManager\n[리마인더/엄격한 정시 스크립트/...] 등 시간 정확도가 중요한 작업에 적합합니다.\nAndroid 12+ 에서 \"알람 및 알림 설정 허용\" 권한이 있으면, 화면 꺼짐/대기 중에도 비교적 정확하게 실행됩니다.\n 권한이 없으면 시스템이 정확도를 낮추거나 실행을 지연할 수 있습니다.\n\n2. WorkManager\n[비중요 동기화/정리/통계/...] 등 엄격한 정시성이 필요 없는 작업에 적합합니다.\n[배터리/네트워크/충전 상태/대기 정책/...] 에 따라 스케줄링되며, 화면 꺼짐/대기 중에는 지연될 수 있습니다.\n 시간 정확도는 보장되지 않지만, [신뢰성 있는 완료/실패 재시도/체이닝/단일 작업 중복 방지] 에 장점이 있습니다.\n\n3. JobScheduler\n 호환성 유지를 위한 기존 구현입니다.\n 신형 Android 에서는 지연이 더 커질 수 있습니다.\n 특별한 호환성 목적이 아니라면 일반적으로 권장하지 않습니다.
diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml
index 4ed02c44..7db4b6b1 100644
--- a/app/src/main/res/values-ru/strings.xml
+++ b/app/src/main/res/values-ru/strings.xml
@@ -429,7 +429,7 @@
Код версии приложения
Название версии приложения
Внешний вид
- Необходимо заполнить хотя бы одно поле из: «Полное имя, Название организации, Организационная единица, Код страны, Штат или провинция, Город или населенный пункт, Улица»
+ Необходимо заполнить хотя бы одно поле из: "Полное имя, Название организации, Организационная единица, Код страны, Штат или провинция, Город или населенный пункт, Улица"
Атрибут
Автоматическая проверка обновлений
Автоматическая проверка обновлений и отображение закуски на домашней странице
@@ -472,7 +472,7 @@
Очистить сценарий предварительного выполнения
Очистить состояния проверки обновлений
Нажмите на элемент для удаления
- Нажмите \"OK\" для перехода к настройкам
+ Нажмите \"OK\" для перехода к настройкам
Частые операции
Режим клиента
Клонировать цветовую библиотеку
@@ -1066,5 +1066,10 @@
Переключатель включён (по умолчанию): значения, возвращаемые методами Java типов Number/Boolean/Character, оборачиваются в объекты Java и доступны в скрипте (String исключается). typeof = \"object\", species = \"JavaObject\"; доступны методы Java, что помогает сохранять точные типовые характеристики Java и корректную резолюцию перегрузок.\n\nПереключатель выключен: перечисленные типы больше не оборачиваются и передаются напрямую как примитивы JavaScript (number/boolean/строка из одного символа). typeof соответствует соответствующему типу JavaScript, что ближе к семантике/экосистеме JavaScript. При необходимости можно явно создать Java‑обёртку через new, например new java.lang.Boolean(true).\n\nСм.: http://issues.autojs6.com/435
Примитивы Java в скрипте будут обёрнуты в объекты Java
Обёртка примитивов Java
+ Движок планирования таймерных задач
+ Управляет базовым механизмом по расписанию запуска скриптов.\n\nAlarmManager: При выдаче разрешения "Разрешить настройку будильников и напоминаний" задачи выполняются более точно по времени.\nWorkManager: Дружелюбен к системе; подходит для некритичных задач, допускающих задержку.\nJobScheduler: Устаревшая реализация, сохранена для совместимости; вероятность задержек выше.
+ Не удалось открыть страницу настроек
+ Рекомендуется выдать разрешение "Разрешить настройку будильников и напоминаний", чтобы обеспечить максимально точный запуск задач даже при выключенном экране или в режиме ожидания
+ Сценарии и отличия:\n\n1. AlarmManager\nПодходит для задач, чувствительных к точности времени, например [напоминания/строго по расписанию/...].\nВ Android 12+ при наличии разрешения "Разрешить настройку будильников и напоминаний" задачи запускаются более точно даже при выключенном экране/в ожидании.\nБез него система может понизить точность или отложить выполнение.\n\n2. WorkManager\nПодходит для задач без строгих требований к времени, например [некритичная синхронизация/очистка/статистика/...].\nПланирование учитывает [батарею/сеть/зарядку/политику сна/...], возможны задержки при выключенном экране или в ожидании.\nХотя точность не гарантируется, он силён в [надёжном завершении/повторных попытках/цепочках/дедупликации работ].\n\n3. JobScheduler\nИсторическая реализация для совместимости.\nНа новых версиях Android возможны более существенные задержки.\nНе рекомендуется, если это не необходимо ради совместимости.
diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml
index ed2df1f5..8f37c5a8 100644
--- a/app/src/main/res/values-zh-rHK/strings.xml
+++ b/app/src/main/res/values-zh-rHK/strings.xml
@@ -470,7 +470,7 @@
清空預執行腳本
清除更新檢查狀態
點擊條目可移除
- 點擊 \"確定\" 跳轉到設置頁面
+ 點擊 \"確定\" 跳轉到設置頁面
操作頻率過快
客户端模式
克隆顏色庫
@@ -1064,5 +1064,10 @@
開關啓用 (默認): 將 Java 方法返回的 Number/Boolean/Character 包裝為 Java 對象暴露到腳本 (String 除外). typeof 為 \"object\", species 為 \"JavaObject\", 可訪問這些對象的 Java 方法, 利於保留 Java 精確類型特徵與方法重載行為.\n\n開關禁用: 不再包裝上述類型, 直接作為 JavaScript 基元值 (number/boolean/單字符字符串). typeof 為相應 JavaScript 類型, 更貼近 JavaScript 語義與生態. 但仍可通過 new 關鍵字顯式聲明一個 Java 包裝類型, 如 new java.lang.Boolean(true).\n\n參閲: http://issues.autojs6.com/435
Java 原始類型在腳本中將被包裝為對應的 Java 對象
Java 原始類型包裝
+ 定時任務調度引擎
+ 控制腳本定時觸發的底層機制.\n\nAlarmManager: 通過申請 \"允許設置鬧鐘和提醒\" 權限, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作兼容保留, 定時任務出現延遲的概率較大.
+ 跳轉設置頁面失敗
+ 建議授予 \"允許設置鬧鐘和提醒\" 權限以確保定時任務在息屏或待機狀態時儘可能準時執行
+ 使用場景與差異説明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時腳本/...].\n在 Android 12+ 獲取 \"允許設置鬧鐘和提醒\" 權限後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設置鬧鐘和提醒\" 權限時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網絡/充電情況/待機策略/... ] 進行調度, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為兼容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於兼容需要, 一般不推薦使用.
diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml
index 948fc151..0ef56442 100644
--- a/app/src/main/res/values-zh-rTW/strings.xml
+++ b/app/src/main/res/values-zh-rTW/strings.xml
@@ -470,7 +470,7 @@
清空預執行指令碼
清除更新檢查狀態
點選條目可移除
- 點選 \"確定\" 跳轉到設定頁面
+ 點選 \"確定\" 跳轉到設定頁面
操作頻率過快
客戶端模式
克隆顏色庫
@@ -1064,5 +1064,10 @@
開關啟用 (預設): 將 Java 方法返回的 Number/Boolean/Character 包裝為 Java 物件暴露到指令碼 (String 除外). typeof 為 \"object\", species 為 \"JavaObject\", 可訪問這些物件的 Java 方法, 利於保留 Java 精確型別特徵與方法過載行為.\n\n開關禁用: 不再包裝上述型別, 直接作為 JavaScript 基元值 (number/boolean/單字元字串). typeof 為相應 JavaScript 型別, 更貼近 JavaScript 語義與生態. 但仍可透過 new 關鍵字顯式宣告一個 Java 包裝型別, 如 new java.lang.Boolean(true).\n\n參閱: http://issues.autojs6.com/435
Java 原始型別在指令碼中將被包裝為對應的 Java 物件
Java 原始型別包裝
+ 定時任務排程引擎
+ 控制指令碼定時觸發的底層機制.\n\nAlarmManager: 透過申請 \"允許設定鬧鐘和提醒\" 許可權, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作相容保留, 定時任務出現延遲的機率較大.
+ 跳轉設定頁面失敗
+ 建議授予 \"允許設定鬧鐘和提醒\" 許可權以確保定時任務在息屏或待機狀態時儘可能準時執行
+ 使用場景與差異說明: \n\n1. AlarmManager\n適用於準時性敏感的定時任務, 如 [提醒/嚴格定時指令碼/...].\n在 Android 12+ 獲取 \"允許設定鬧鐘和提醒\" 許可權後, 在息屏或待機狀態時能夠較準時地執行定時任務.\n在未授予 \"允許設定鬧鐘和提醒\" 許可權時, 系統可能降級為不準時或延後執行任務.\n\n2. WorkManager\n適用於不要求嚴格準時執行的定時任務, 如 [非關鍵性同步/清理/統計/...].\n根據系統 [ 電量/網路/充電情況/待機策略/... ] 進行排程, 息屏或待機狀態時可能推遲任務執行.\n雖無法保證時間精確性, 但在 [ 可靠完成/失敗重試/鏈式執行/唯一任務去重 ] 等方面擁有獨特優勢.\n\n3. Job\n歷史實現, 為相容保留.\n在高版本安卓系統中定時任務可能存在較大的延遲執行問題.\n除非出於相容需要, 一般不推薦使用.
diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml
index 61fa7ccc..c83b3a2e 100644
--- a/app/src/main/res/values-zh/strings.xml
+++ b/app/src/main/res/values-zh/strings.xml
@@ -470,7 +470,7 @@
清空预执行脚本
清除更新检查状态
点击条目可移除
- 点击 \"确定\" 跳转到设置页面
+ 点击 \"确定\" 跳转到设置页面
操作频率过快
客户端模式
克隆颜色库
@@ -1064,5 +1064,10 @@
开关启用 (默认): 将 Java 方法返回的 Number/Boolean/Character 包装为 Java 对象暴露到脚本 (String 除外). typeof 为 \"object\", species 为 \"JavaObject\", 可访问这些对象的 Java 方法, 利于保留 Java 精确类型特征与方法重载行为.\n\n开关禁用: 不再包装上述类型, 直接作为 JavaScript 基元值 (number/boolean/单字符字符串). typeof 为相应 JavaScript 类型, 更贴近 JavaScript 语义与生态. 但仍可通过 new 关键字显式声明一个 Java 包装类型, 如 new java.lang.Boolean(true).\n\n参阅: http://issues.autojs6.com/435
Java 原始类型在脚本中将被包装为对应的 Java 对象
Java 原始类型包装
+ 定时任务调度引擎
+ 控制脚本定时触发的底层机制.\n\nAlarmManager: 通过申请 \"允许设置闹钟和提醒\" 权限, 可使定时任务的触发更接近准时.\nWorkManager: 系统友好, 适合可接受一定延迟的非关键定时任务.\nJobScheduler: 旧实现, 仅用作兼容保留, 定时任务出现延迟的概率较大.
+ 跳转设置页面失败
+ 建议授予 \"允许设置闹钟和提醒\" 权限以确保定时任务在息屏或待机状态时尽可能准时执行
+ 使用场景与差异说明: \n\n1. AlarmManager\n适用于准时性敏感的定时任务, 如 [提醒/严格定时脚本/...].\n在 Android 12+ 获取 \"允许设置闹钟和提醒\" 权限后, 在息屏或待机状态时能够较准时地执行定时任务.\n在未授予 \"允许设置闹钟和提醒\" 权限时, 系统可能降级为不准时或延后执行任务.\n\n2. WorkManager\n适用于不要求严格准时执行的定时任务, 如 [非关键性同步/清理/统计/...].\n根据系统 [ 电量/网络/充电情况/待机策略/... ] 进行调度, 息屏或待机状态时可能推迟任务执行.\n虽无法保证时间精确性, 但在 [ 可靠完成/失败重试/链式执行/唯一任务去重 ] 等方面拥有独特优势.\n\n3. Job\n历史实现, 为兼容保留.\n在高版本安卓系统中定时任务可能存在较大的延迟执行问题.\n除非出于兼容需要, 一般不推荐使用.
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index aa6a254a..0b208aad 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -10,6 +10,18 @@
- @string/entry_root_record_out_file_type_js
+
+ - @string/key_timed_task_backend_alarm
+ - @string/key_timed_task_backend_work
+ - @string/key_timed_task_backend_job
+
+
+
+ - @string/entry_timed_task_backend_alarm
+ - @string/entry_timed_task_backend_work
+ - @string/entry_timed_task_backend_job
+
+
- @string/key_documentation_source_local
- @string/key_documentation_source_online
@@ -143,5 +155,5 @@
- @color/about_app_svg_view_trace_color
-
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 08bef4a4..78f3e2d9 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -26,6 +26,7 @@
@string/key_hidden_files_not_show
@string/key_keep_screen_on_when_in_foreground_disabled
@string/key_root_record_out_file_type_binary
+ @string/key_timed_task_backend_alarm
main.js
SuperMonster003
SuperMonster003
@@ -148,6 +149,10 @@
key_$_theme_color_accent
key_$_theme_color_primary
key_$_theme_color_primary_dark
+ key_$_timed_task_backend
+ key_$_timed_task_backend_alarm
+ key_$_timed_task_backend_job
+ key_$_timed_task_backend_work
key_$_updates_checked_states_cleared
key_$_use_volume_control_record
key_$_use_volume_control_running
@@ -385,6 +390,9 @@
Force set root mode
Binary type (non-editable)
JavaScript type (editable)
+ AlarmManager
+ WorkManager
+ JobScheduler
A runtime has been set
Method %s has been abandoned and should not be used
The \"%1$s\" operation cannot be completed because the parameter contains negative coordinate values (%2$d, %3$d)
@@ -705,7 +713,7 @@
Clear pre-execute script
Clear updates checked states
Click the item to remove
- Click \"OK\" to go to settings
+ Click \"OK\" to go to settings
Frequent operation
Client mode
Clone a color library
@@ -1299,5 +1307,10 @@
Switch ON (default): results of Java methods that are instances of Number/Boolean/Character are wrapped as Java objects and exposed to scripts (String excluded). typeof is \"object\", species is \"JavaObject\"; Java methods remain accessible, which helps retain precise Java type traits and overload resolution.\n\nSwitch OFF: the above types are no longer wrapped and are exposed directly as JavaScript primitives (number/boolean/one‑character string). typeof is the corresponding JavaScript type, aligning better with JavaScript semantics and ecosystem. You can still explicitly create a Java wrapper via new, e.g. new java.lang.Boolean(true).\n\nSee: http://issues.autojs6.com/435
Java primitive types will be wrapped as Java objects in scripts
Java primitive wrapping
+ Timed task scheduling engine
+ 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.
+ Failed to open the settings page
+ 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
+ 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 don’t 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 can’t 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.
diff --git a/app/src/main/res/xml/fragment_preferences.xml b/app/src/main/res/xml/fragment_preferences.xml
index 8ad06d9d..8995ba9e 100644
--- a/app/src/main/res/xml/fragment_preferences.xml
+++ b/app/src/main/res/xml/fragment_preferences.xml
@@ -76,27 +76,18 @@
app:summary="@string/summary_text_launcher_shortcuts"
app:longClickPrompt="@string/description_launcher_shortcuts" />
-
-
-
-
+
+
+
+
+
+
+
+
@@ -162,6 +169,15 @@
app:title="@string/text_guard_mode"
app:summary="@string/summary_guard_mode" />
+
+