6.7.0 - Alpha10 - 设置页面增加 "定时任务调度引擎" 设置选项, 支持 AlarmManager/WorkManager/JobScheduler (issue #457, #388, #163, #53, #21)

This commit is contained in:
SuperMonster003
2025-10-29 13:31:06 +08:00
parent 52c1eb56b8
commit c446ffba1f
37 changed files with 619 additions and 178 deletions

View File

@@ -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")

View File

@@ -600,6 +600,20 @@
<!-- </intent-filter>-->
<!--</receiver>-->
<receiver
android:name="org.autojs.autojs.timing.TimedTaskAlarmReceiver"
android:exported="false" />
<receiver
android:name="org.autojs.autojs.timing.BootCompletedReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.LOCKED_BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="org.autojs.autojs.theme.app.ColorSelectActivity"
android:theme="@style/MtAppTheme.FullScreen" />

View File

@@ -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()

View File

@@ -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
}

View File

@@ -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()

View File

@@ -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<M extends BaseModel> {
private final SQLiteDatabase mWritableSQLiteDatabase;
@@ -148,26 +147,22 @@ public abstract class Database<M extends BaseModel> {
return new String[]{String.valueOf(value)};
}
private static class CursorIterator implements Iterator<Cursor> {
private final Cursor mCursor;
private CursorIterator(Cursor cursor) {
mCursor = cursor;
}
private record CursorIterator(Cursor cursor) implements Iterator<Cursor> {
@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;
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}
}
}

View File

@@ -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()
}
}

View File

@@ -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
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)
}

View File

@@ -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<TimedTask>
@@ -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
}

View File

@@ -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
}
}
}

View File

@@ -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<TimedTaskWorker>()
.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<CheckTasksWorker>(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()
}
}
}

View File

@@ -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)
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -474,7 +474,7 @@
<string name="text_clear_pre_execute_script">مسح السيناريو قبل التنفيذ</string>
<string name="text_clear_updates_checked_states">تحديثات مسح الحالات التي تم فحصها</string>
<string name="text_click_item_to_remove">انقر فوق العنصر لإزالته</string>
<string name="text_click_ok_to_go_to_access_settings">انقر فوق \"نعم\" للانتقال إلى الإعدادات</string>
<string name="text_click_ok_to_go_to_settings">انقر فوق \"نعم\" للانتقال إلى الإعدادات</string>
<string name="text_click_too_frequently">التشغيل المتكرر</string>
<string name="text_client_mode">وضع العميل</string>
<string name="text_clone_color_library">استنساخ مكتبة ألوان</string>
@@ -1068,5 +1068,10 @@
<string name="description_rhino_java_primitive_wrap">عند تفعيل المفتاح (الوضع الافتراضي): سيتم تغليف القيم المُعادة من أساليب 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</string>
<string name="summary_rhino_java_primitive_wrap">ستُغلَّف الأنواع البدائية في Java ككائنات Java داخل السكربت</string>
<string name="text_rhino_java_primitive_wrap">تغليف الأنواع البدائية في Java</string>
<string name="title_timed_task_backend">محرك جدولة المهام المؤقتة</string>
<string name="description_timed_task_backend">يتحكم في الآلية الأساسية لتشغيل السكربتات بشكل مجدول.\n\nAlarmManager: عبر منح إذن \"السماح بتعيين المنبّهات والتذكيرات\" يمكن أن تصبح المهام أقرب إلى التنفيذ في الوقت المحدد.\nWorkManager: صديق للنظام؛ مناسب للمهام غير الحرجة التي تتحمل بعض التأخير.\nJobScheduler: تنفيذ قديم محفوظ للتوافق؛ احتمال التأخير أعلى.</string>
<string name="failed_to_go_to_access_settings">فشل فتح صفحة الإعدادات</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>
</resources>

View File

@@ -469,7 +469,7 @@
<string name="text_clear_pre_execute_script">Clear pre-execute script</string>
<string name="text_clear_updates_checked_states">Clear updates checked states</string>
<string name="text_click_item_to_remove">Click the item to remove</string>
<string name="text_click_ok_to_go_to_access_settings">Click \"OK\" to go to settings</string>
<string name="text_click_ok_to_go_to_settings">Click \"OK\" to go to settings</string>
<string name="text_click_too_frequently">Frequent operation</string>
<string name="text_client_mode">Client mode</string>
<string name="text_clone_color_library">Clone a color library</string>
@@ -1063,5 +1063,10 @@
<string name="description_rhino_java_primitive_wrap">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/onecharacter 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</string>
<string name="summary_rhino_java_primitive_wrap">Java primitive types will be wrapped as Java objects in scripts</string>
<string name="text_rhino_java_primitive_wrap">Java primitive wrapping</string>
<string name="title_timed_task_backend">Timed task scheduling engine</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="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>
</resources>

View File

@@ -472,7 +472,7 @@
<string name="text_clear_pre_execute_script">Borrar script de pre-ejecución</string>
<string name="text_clear_updates_checked_states">Borrar los estados de comprobación de las actualizaciones</string>
<string name="text_click_item_to_remove">Haga clic en el elemento a eliminar</string>
<string name="text_click_ok_to_go_to_access_settings">Haga clic en \"Aceptar\" para ir a la configuración</string>
<string name="text_click_ok_to_go_to_settings">Haga clic en \"Aceptar\" para ir a la configuración</string>
<string name="text_click_too_frequently">Funcionamiento frecuente</string>
<string name="text_client_mode">Modo cliente</string>
<string name="text_clone_color_library">Clonar biblioteca de colores</string>
@@ -1066,5 +1066,10 @@
<string name="description_rhino_java_primitive_wrap">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</string>
<string name="summary_rhino_java_primitive_wrap">Los tipos primitivos de Java se envolverán como objetos Java en los scripts</string>
<string name="text_rhino_java_primitive_wrap">Envoltorio de primitivos de Java</string>
<string name="title_timed_task_backend">Motor de programación de tareas temporizadas</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="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>
</resources>

View File

@@ -429,7 +429,7 @@
<string name="text_app_version_code">Code de la version de l\'application</string>
<string name="text_app_version_name">Nom de la version de l\'application</string>
<string name="text_appearance">Appearance</string>
<string name="text_at_least_one_certificate_issuer_field_is_not_empty">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é</string>
<string name="text_at_least_one_certificate_issuer_field_is_not_empty">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é</string>
<string name="text_attribute">Attribut</string>
<string name="text_auto_check_for_updates">Vérification automatique des mises à jour</string>
<string name="text_auto_check_for_updates_and_show_snackbar">Vérification automatique des mises à jour et affichage d\'un snackbar sur la page d\'accueil</string>
@@ -472,7 +472,7 @@
<string name="text_clear_pre_execute_script">Effacer le script de pré-exécution</string>
<string name="text_clear_updates_checked_states">Effacer les états vérifiés des mises à jour</string>
<string name="text_click_item_to_remove">Cliquez sur l\'élément à supprimer</string>
<string name="text_click_ok_to_go_to_access_settings">Cliquez sur \"OK\" pour accéder aux paramètres</string>.
<string name="text_click_ok_to_go_to_settings">Cliquez sur \"OK\" pour accéder aux paramètres</string>.
<string name="text_click_too_frequently">Une opération fréquente</string>
<string name="text_client_mode">Mode client</string>
<string name="text_clone_color_library">Cloner une bibliothèque de couleurs</string>
@@ -1063,8 +1063,13 @@
<string name="text_write_secure_settings">Écrire les paramètres de sécurité</string>.
<string name="text_write_secure_settings_description">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é).</string>
<string name="text_write_system_settings">Écrire les paramètres système</string>
<string name="description_rhino_java_primitive_wrap">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 cidessus 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</string>
<string name="description_rhino_java_primitive_wrap">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 cidessus 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</string>
<string name="summary_rhino_java_primitive_wrap">Les types primitifs Java seront exposés comme objets Java dans les scripts</string>
<string name="text_rhino_java_primitive_wrap">Encapsulation des types primitifs Java</string>
<string name="title_timed_task_backend">Moteur d\'ordonnancement des tâches planifiées</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="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>
</resources>

View File

@@ -82,7 +82,7 @@
<string name="description_launcher_shortcuts">ショートカットは, AutoJs6 で特定のアクションを実行することができます. ユーザーは, サポートされているランチャーにこれらのショートカットを表示し, AutoJs6 アプリケーションのドキュメントを読んだり, AutoJs6 の設定ページを起動したりするなど, いくつかのタスクを素早く開始したり, アクティビティを起動したりすることができます</string>
<string name="description_manage_ignored_updates_preference">クリックすると, リストアイテムを表示または管理できます.\nリストアイテムを削除するには, 長押しします</string>
<string name="description_night_mode_preference">ナイトモード (ダークテーマとも呼ばれる) は, 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] 以上の場合のみです</string>
<string name="description_night_mode_preference_more">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 リソースなどによる) </string>
<string name="description_night_mode_preference_more">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 リソースなどによる)</string>
<string name="description_root_mode_preference">異国の root や root アクセスに異常がある場合, root を強制的に root または non-root に設定することができます</string>
<string name="description_root_record_out_file_type_preference">バイナリタイプ: 編集不可, ファイル拡張子は \"auto\"\nJavaScript タイプ: 直接編集またはコピー可能, ファイル拡張子は \"js\"</string>
<string name="description_stable_mode">安定モードにするとレイアウト境界を取得する際に安定しますが, 一部の結果が無視されることがあります.\nアクセシビリティサービスの再起動が必要です</string>
@@ -473,7 +473,7 @@
<string name="text_clear_pre_execute_script">実行前スクリプトのクリア</string>
<string name="text_clear_updates_checked_states">アップデートのチェック状態をクリアする</string>
<string name="text_click_item_to_remove">削除する項目をクリックします</string>
<string name="text_click_ok_to_go_to_access_settings">\"OK\" をクリックすると設定に進みます</string>
<string name="text_click_ok_to_go_to_settings">\"OK\" をクリックすると設定に進みます</string>
<string name="text_click_too_frequently">頻繁に行う操作</string>
<string name="text_client_mode">クライアントモード</string>
<string name="text_clone_color_library">カラーライブラリを複製</string>
@@ -1067,5 +1067,10 @@
<string name="description_rhino_java_primitive_wrap">スイッチ有効 (デフォルト): 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</string>
<string name="summary_rhino_java_primitive_wrap">Java のプリミティブ型はスクリプト内で Java オブジェクトとしてラップされます</string>
<string name="text_rhino_java_primitive_wrap">Java プリミティブ型のラップ</string>
<string name="title_timed_task_backend">定時タスクのスケジューリングエンジン</string>
<string name="description_timed_task_backend">スクリプトを定時で起動するための基盤メカニズムを制御します.\n\nAlarmManager: システムの \"アラームとリマインダーの設定を許可\" 権限を付与すると/より正確な時刻での実行に近づきます.\nWorkManager: システムに優しく/一定の遅延を許容できる非重要タスクに適しています.\nJobScheduler: 旧来の実装で互換性のために残されていますが/遅延が発生しやすいです.</string>
<string name="failed_to_go_to_access_settings">設定画面を開けませんでした</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>
</resources>

View File

@@ -474,7 +474,7 @@
<string name="text_clear_pre_execute_script">사전 에코 슈트 스크립트를 지우십시오</string>
<string name="text_clear_updates_checked_states">확인 된 상태에서 명확한 업데이트</string>
<string name="text_click_item_to_remove">제거하려면 항목을 클릭하십시오</string>
<string name="text_click_ok_to_go_to_access_settings">\"확인\"을 클릭하여 설정으로 이동하십시오</string>
<string name="text_click_ok_to_go_to_settings">\"확인\"을 클릭하여 설정으로 이동하십시오</string>
<string name="text_click_too_frequently">빈번한 작동</string>
<string name="text_client_mode">클라이언트 모드</string>
<string name="text_clone_color_library">색상 라이브러리 복제</string>
@@ -1068,5 +1068,10 @@
<string name="description_rhino_java_primitive_wrap">스위치 활성화(기본값): 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</string>
<string name="summary_rhino_java_primitive_wrap">Java 원시 타입이 스크립트에서 Java 객체로 래핑됩니다</string>
<string name="text_rhino_java_primitive_wrap">Java 원시 타입 래핑</string>
<string name="title_timed_task_backend">정시 작업 스케줄링 엔진</string>
<string name="description_timed_task_backend">스크립트를 정해진 시간에 실행하는 기본 메커니즘을 제어합니다.\n\nAlarmManager: 시스템의 \"알람 및 알림 설정 허용\" 권한을 부여하면 보다 정확한 시각에 가깝게 실행됩니다.\nWorkManager: 시스템 친화적이며, 일정 지연을 허용할 수 있는 비중요 작업에 적합합니다.\nJobScheduler: 호환성 유지를 위해 남겨둔 구방식으로, 지연 발생 가능성이 큽니다.</string>
<string name="failed_to_go_to_access_settings">설정 페이지를 열지 못했습니다</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>
</resources>

View File

@@ -429,7 +429,7 @@
<string name="text_app_version_code">Код версии приложения</string>
<string name="text_app_version_name">Название версии приложения</string>
<string name="text_appearance">Внешний вид</string>
<string name="text_at_least_one_certificate_issuer_field_is_not_empty">Необходимо заполнить хотя бы одно поле из: «Полное имя, Название организации, Организационная единица, Код страны, Штат или провинция, Город или населенный пункт, Улица»</string>
<string name="text_at_least_one_certificate_issuer_field_is_not_empty">Необходимо заполнить хотя бы одно поле из: "Полное имя, Название организации, Организационная единица, Код страны, Штат или провинция, Город или населенный пункт, Улица"</string>
<string name="text_attribute">Атрибут</string>
<string name="text_auto_check_for_updates">Автоматическая проверка обновлений</string>
<string name="text_auto_check_for_updates_and_show_snackbar">Автоматическая проверка обновлений и отображение закуски на домашней странице</string>
@@ -472,7 +472,7 @@
<string name="text_clear_pre_execute_script">Очистить сценарий предварительного выполнения</string>
<string name="text_clear_updates_checked_states">Очистить состояния проверки обновлений</string>
<string name="text_click_item_to_remove">Нажмите на элемент для удаления</string>
<string name="text_click_ok_to_go_to_access_settings">Нажмите \"OK\" для перехода к настройкам</string>
<string name="text_click_ok_to_go_to_settings">Нажмите \"OK\" для перехода к настройкам</string>
<string name="text_click_too_frequently">Частые операции</string>
<string name="text_client_mode">Режим клиента</string>
<string name="text_clone_color_library">Клонировать цветовую библиотеку</string>
@@ -1066,5 +1066,10 @@
<string name="description_rhino_java_primitive_wrap">Переключатель включён (по умолчанию): значения, возвращаемые методами 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</string>
<string name="summary_rhino_java_primitive_wrap">Примитивы Java в скрипте будут обёрнуты в объекты Java</string>
<string name="text_rhino_java_primitive_wrap">Обёртка примитивов Java</string>
<string name="title_timed_task_backend">Движок планирования таймерных задач</string>
<string name="description_timed_task_backend">Управляет базовым механизмом по расписанию запуска скриптов.\n\nAlarmManager: При выдаче разрешения "Разрешить настройку будильников и напоминаний" задачи выполняются более точно по времени.\nWorkManager: Дружелюбен к системе; подходит для некритичных задач, допускающих задержку.\nJobScheduler: Устаревшая реализация, сохранена для совместимости; вероятность задержек выше.</string>
<string name="failed_to_go_to_access_settings">Не удалось открыть страницу настроек</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>
</resources>

View File

@@ -470,7 +470,7 @@
<string name="text_clear_pre_execute_script">清空預執行腳本</string>
<string name="text_clear_updates_checked_states">清除更新檢查狀態</string>
<string name="text_click_item_to_remove">點擊條目可移除</string>
<string name="text_click_ok_to_go_to_access_settings">點擊 \"確定\" 跳轉到設置頁面</string>
<string name="text_click_ok_to_go_to_settings">點擊 \"確定\" 跳轉到設置頁面</string>
<string name="text_click_too_frequently">操作頻率過快</string>
<string name="text_client_mode">客户端模式</string>
<string name="text_clone_color_library">克隆顏色庫</string>
@@ -1064,5 +1064,10 @@
<string name="description_rhino_java_primitive_wrap">開關啓用 (默認): 將 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</string>
<string name="summary_rhino_java_primitive_wrap">Java 原始類型在腳本中將被包裝為對應的 Java 對象</string>
<string name="text_rhino_java_primitive_wrap">Java 原始類型包裝</string>
<string name="title_timed_task_backend">定時任務調度引擎</string>
<string name="description_timed_task_backend">控制腳本定時觸發的底層機制.\n\nAlarmManager: 通過申請 \"允許設置鬧鐘和提醒\" 權限, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作兼容保留, 定時任務出現延遲的概率較大.</string>
<string name="failed_to_go_to_access_settings">跳轉設置頁面失敗</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>
</resources>

View File

@@ -470,7 +470,7 @@
<string name="text_clear_pre_execute_script">清空預執行指令碼</string>
<string name="text_clear_updates_checked_states">清除更新檢查狀態</string>
<string name="text_click_item_to_remove">點選條目可移除</string>
<string name="text_click_ok_to_go_to_access_settings">點選 \"確定\" 跳轉到設定頁面</string>
<string name="text_click_ok_to_go_to_settings">點選 \"確定\" 跳轉到設定頁面</string>
<string name="text_click_too_frequently">操作頻率過快</string>
<string name="text_client_mode">客戶端模式</string>
<string name="text_clone_color_library">克隆顏色庫</string>
@@ -1064,5 +1064,10 @@
<string name="description_rhino_java_primitive_wrap">開關啟用 (預設): 將 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</string>
<string name="summary_rhino_java_primitive_wrap">Java 原始型別在指令碼中將被包裝為對應的 Java 物件</string>
<string name="text_rhino_java_primitive_wrap">Java 原始型別包裝</string>
<string name="title_timed_task_backend">定時任務排程引擎</string>
<string name="description_timed_task_backend">控制指令碼定時觸發的底層機制.\n\nAlarmManager: 透過申請 \"允許設定鬧鐘和提醒\" 許可權, 可使定時任務的觸發更接近準時.\nWorkManager: 系統友好, 適合可接受一定延遲的非關鍵定時任務.\nJobScheduler: 舊實現, 僅用作相容保留, 定時任務出現延遲的機率較大.</string>
<string name="failed_to_go_to_access_settings">跳轉設定頁面失敗</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>
</resources>

View File

@@ -470,7 +470,7 @@
<string name="text_clear_pre_execute_script">清空预执行脚本</string>
<string name="text_clear_updates_checked_states">清除更新检查状态</string>
<string name="text_click_item_to_remove">点击条目可移除</string>
<string name="text_click_ok_to_go_to_access_settings">点击 \"确定\" 跳转到设置页面</string>
<string name="text_click_ok_to_go_to_settings">点击 \"确定\" 跳转到设置页面</string>
<string name="text_click_too_frequently">操作频率过快</string>
<string name="text_client_mode">客户端模式</string>
<string name="text_clone_color_library">克隆颜色库</string>
@@ -1064,5 +1064,10 @@
<string name="description_rhino_java_primitive_wrap">开关启用 (默认): 将 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</string>
<string name="summary_rhino_java_primitive_wrap">Java 原始类型在脚本中将被包装为对应的 Java 对象</string>
<string name="text_rhino_java_primitive_wrap">Java 原始类型包装</string>
<string name="title_timed_task_backend">定时任务调度引擎</string>
<string name="description_timed_task_backend">控制脚本定时触发的底层机制.\n\nAlarmManager: 通过申请 \"允许设置闹钟和提醒\" 权限, 可使定时任务的触发更接近准时.\nWorkManager: 系统友好, 适合可接受一定延迟的非关键定时任务.\nJobScheduler: 旧实现, 仅用作兼容保留, 定时任务出现延迟的概率较大.</string>
<string name="failed_to_go_to_access_settings">跳转设置页面失败</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>
</resources>

View File

@@ -10,6 +10,18 @@
<item>@string/entry_root_record_out_file_type_js</item>
</string-array>
<string-array name="keys_timed_task_backend">
<item>@string/key_timed_task_backend_alarm</item>
<item>@string/key_timed_task_backend_work</item>
<item>@string/key_timed_task_backend_job</item>
</string-array>
<string-array name="values_timed_task_backend">
<item>@string/entry_timed_task_backend_alarm</item>
<item>@string/entry_timed_task_backend_work</item>
<item>@string/entry_timed_task_backend_job</item>
</string-array>
<string-array name="keys_documentation_source">
<item>@string/key_documentation_source_local</item>
<item>@string/key_documentation_source_online</item>
@@ -143,5 +155,5 @@
<integer-array name="icon_about_app_svg_view_trace_residue_colors">
<item>@color/about_app_svg_view_trace_color</item>
</integer-array>
</resources>

View File

@@ -26,6 +26,7 @@
<string name="default_key_hidden_files" translatable="false">@string/key_hidden_files_not_show</string>
<string name="default_key_keep_screen_on_when_in_foreground" translatable="false">@string/key_keep_screen_on_when_in_foreground_disabled</string>
<string name="default_key_root_record_out_file_type" translatable="false">@string/key_root_record_out_file_type_binary</string>
<string name="default_key_timed_task_backend" translatable="false">@string/key_timed_task_backend_alarm</string>
<string name="default_main_file_name" translatable="false">main.js</string>
<string name="developer_full_name" translatable="false">SuperMonster003</string>
<string name="developer_nickname" translatable="false">SuperMonster003</string>
@@ -148,6 +149,10 @@
<string name="key_theme_color_accent" translatable="false">key_$_theme_color_accent</string>
<string name="key_theme_color_primary" translatable="false">key_$_theme_color_primary</string>
<string name="key_theme_color_primary_dark" translatable="false">key_$_theme_color_primary_dark</string>
<string name="key_timed_task_backend" translatable="false">key_$_timed_task_backend</string>
<string name="key_timed_task_backend_alarm" translatable="false">key_$_timed_task_backend_alarm</string>
<string name="key_timed_task_backend_job" translatable="false">key_$_timed_task_backend_job</string>
<string name="key_timed_task_backend_work" translatable="false">key_$_timed_task_backend_work</string>
<string name="key_updates_checked_states_cleared" translatable="false">key_$_updates_checked_states_cleared</string>
<string name="key_use_volume_control_record" translatable="false">key_$_use_volume_control_record</string>
<string name="key_use_volume_control_running" translatable="false">key_$_use_volume_control_running</string>
@@ -385,6 +390,9 @@
<string name="entry_root_mode_force_root">Force set root mode</string>
<string name="entry_root_record_out_file_type_binary">Binary type (non-editable)</string>
<string name="entry_root_record_out_file_type_js">JavaScript type (editable)</string>
<string name="entry_timed_task_backend_alarm" translatable="false">AlarmManager</string>
<string name="entry_timed_task_backend_work" translatable="false">WorkManager</string>
<string name="entry_timed_task_backend_job" translatable="false">JobScheduler</string>
<string name="error_a_runtime_has_been_set">A runtime has been set</string>
<string name="error_abandoned_method">Method %s has been abandoned and should not be used</string>
<string name="error_action_cannot_be_completed_with_negative_coordinate">The \"%1$s\" operation cannot be completed because the parameter contains negative coordinate values (%2$d, %3$d)</string>
@@ -705,7 +713,7 @@
<string name="text_clear_pre_execute_script">Clear pre-execute script</string>
<string name="text_clear_updates_checked_states">Clear updates checked states</string>
<string name="text_click_item_to_remove">Click the item to remove</string>
<string name="text_click_ok_to_go_to_access_settings">Click \"OK\" to go to settings</string>
<string name="text_click_ok_to_go_to_settings">Click \"OK\" to go to settings</string>
<string name="text_click_too_frequently">Frequent operation</string>
<string name="text_client_mode">Client mode</string>
<string name="text_clone_color_library">Clone a color library</string>
@@ -1299,5 +1307,10 @@
<string name="description_rhino_java_primitive_wrap">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/onecharacter 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</string>
<string name="summary_rhino_java_primitive_wrap">Java primitive types will be wrapped as Java objects in scripts</string>
<string name="text_rhino_java_primitive_wrap">Java primitive wrapping</string>
<string name="title_timed_task_backend">Timed task scheduling engine</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="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>
</resources>

View File

@@ -76,27 +76,18 @@
app:summary="@string/summary_text_launcher_shortcuts"
app:longClickPrompt="@string/description_launcher_shortcuts" />
<org.autojs.autojs.ui.settings.WorkingDirectoryPreference
app:layout="@layout/preference_custom"
app:key="@string/key_change_working_dir"
app:title="@string/text_change_working_dir"
app:longClickPrompt="@string/description_change_working_dir_preference" />
<org.autojs.autojs.ui.settings.RootModePreference
app:layout="@layout/preference_custom"
app:key="@string/key_root_mode"
app:title="@string/text_root_mode_title"
app:itemKeys="@array/keys_root_mode"
app:itemValues="@array/values_root_mode"
app:itemDefaultKey="@string/key_root_mode_auto_detect"
app:longClickPrompt="@string/description_root_mode_preference" />
</org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory>
<org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory
app:layout="@layout/preference_category_custom"
app:title="@string/text_file_explorer">
<org.autojs.autojs.ui.settings.WorkingDirectoryPreference
app:layout="@layout/preference_custom"
app:key="@string/key_change_working_dir"
app:title="@string/text_working_dir_path"
app:longClickPrompt="@string/description_change_working_dir_preference" />
<org.autojs.autojs.ui.settings.HiddenFilesPreference
app:layout="@layout/preference_custom"
app:key="@string/key_hidden_files"
@@ -110,13 +101,29 @@
app:layout="@layout/preference_custom"
app:key="@string/key_file_extensions"
app:title="@string/text_file_extensions_title"
app:itemValues="@array/values_file_extensions"
app:itemKeys="@array/keys_file_extensions"
app:itemValues="@array/values_file_extensions"
app:itemDefaultKey="@string/default_key_file_extensions"
app:longClickPrompt="@string/description_file_extensions_preference" />
</org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory>
<org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory
app:layout="@layout/preference_category_custom"
app:title="@string/text_timed_task">
<org.autojs.autojs.ui.settings.TimedTaskBackendPreference
app:layout="@layout/preference_custom"
app:key="@string/key_timed_task_backend"
app:title="@string/title_timed_task_backend"
app:itemKeys="@array/keys_timed_task_backend"
app:itemValues="@array/values_timed_task_backend"
app:itemDefaultKey="@string/default_key_timed_task_backend"
app:longClickPrompt="@string/description_timed_task_backend"
app:longClickPromptMore="@string/description_timed_task_backend_more"/>
</org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory>
<org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory
app:layout="@layout/preference_category_custom"
app:title="@string/text_a11y_service">
@@ -162,6 +169,15 @@
app:title="@string/text_guard_mode"
app:summary="@string/summary_guard_mode" />
<org.autojs.autojs.ui.settings.RootModePreference
app:layout="@layout/preference_custom"
app:key="@string/key_root_mode"
app:title="@string/text_root_mode_title"
app:itemKeys="@array/keys_root_mode"
app:itemValues="@array/values_root_mode"
app:itemDefaultKey="@string/key_root_mode_auto_detect"
app:longClickPrompt="@string/description_root_mode_preference" />
</org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory>
<org.autojs.autojs.theme.preference.ThemeColorPreferenceCategory