mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
parent
af63302df6
commit
5fb9f1b75c
@ -28,7 +28,7 @@ import com.idormy.sms.forwarder.utils.*
|
|||||||
import com.idormy.sms.forwarder.utils.sdkinit.UMengInit
|
import com.idormy.sms.forwarder.utils.sdkinit.UMengInit
|
||||||
import com.idormy.sms.forwarder.utils.sdkinit.XBasicLibInit
|
import com.idormy.sms.forwarder.utils.sdkinit.XBasicLibInit
|
||||||
import com.idormy.sms.forwarder.utils.sdkinit.XUpdateInit
|
import com.idormy.sms.forwarder.utils.sdkinit.XUpdateInit
|
||||||
import com.idormy.sms.forwarder.utils.task.CronUtils
|
import com.idormy.sms.forwarder.utils.task.AlarmUtils
|
||||||
import com.idormy.sms.forwarder.utils.tinker.TinkerLoadLibrary
|
import com.idormy.sms.forwarder.utils.tinker.TinkerLoadLibrary
|
||||||
import io.reactivex.Observable
|
import io.reactivex.Observable
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
@ -208,7 +208,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
|||||||
// 运营统计数据
|
// 运营统计数据
|
||||||
UMengInit.init(this)
|
UMengInit.init(this)
|
||||||
// 定时任务初始化
|
// 定时任务初始化
|
||||||
CronUtils.initialize(this)
|
AlarmUtils.initialize(this)
|
||||||
// 三方时间库初始化
|
// 三方时间库初始化
|
||||||
//AndroidThreeTen.init(this)
|
//AndroidThreeTen.init(this)
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import com.idormy.sms.forwarder.adapter.TaskPagingAdapter.MyViewHolder
|
|||||||
import com.idormy.sms.forwarder.database.entity.Task
|
import com.idormy.sms.forwarder.database.entity.Task
|
||||||
import com.idormy.sms.forwarder.databinding.AdapterTasksCardViewListItemBinding
|
import com.idormy.sms.forwarder.databinding.AdapterTasksCardViewListItemBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
|
import com.xuexiang.xutil.data.DateUtils
|
||||||
|
|
||||||
class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Task, MyViewHolder>(diffCallback) {
|
class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : PagingDataAdapter<Task, MyViewHolder>(diffCallback) {
|
||||||
|
|
||||||
@ -31,6 +32,8 @@ class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
|
|||||||
if (item.type >= 1000) {
|
if (item.type >= 1000) {
|
||||||
holder.binding.layoutImage.visibility = View.GONE
|
holder.binding.layoutImage.visibility = View.GONE
|
||||||
|
|
||||||
|
holder.binding.tvTime.text = DateUtils.getFriendlyTimeSpanByNow(item.lastExecTime.time)
|
||||||
|
|
||||||
//遍历conditions显示图标
|
//遍历conditions显示图标
|
||||||
holder.binding.layoutConditionsIcons.removeAllViews()
|
holder.binding.layoutConditionsIcons.removeAllViews()
|
||||||
if (item.conditions.isNotEmpty()) {
|
if (item.conditions.isNotEmpty()) {
|
||||||
|
@ -175,6 +175,9 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
//纯客户端模式
|
//纯客户端模式
|
||||||
switchDirectlyToClient(binding!!.sbDirectlyToClient)
|
switchDirectlyToClient(binding!!.sbDirectlyToClient)
|
||||||
|
|
||||||
|
//纯自动任务模式
|
||||||
|
switchDirectlyToTask(binding!!.sbDirectlyToTask)
|
||||||
|
|
||||||
//启用 {{定位信息}} 标签
|
//启用 {{定位信息}} 标签
|
||||||
switchEnableLocationTag(binding!!.sbEnableLocationTag)
|
switchEnableLocationTag(binding!!.sbEnableLocationTag)
|
||||||
}
|
}
|
||||||
@ -996,6 +999,19 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//纯自动任务模式
|
||||||
|
private fun switchDirectlyToTask(@SuppressLint("UseSwitchCompatOrMaterialCode") switchDirectlyToTask: SwitchButton) {
|
||||||
|
switchDirectlyToTask.isChecked = SettingUtils.enablePureTaskMode
|
||||||
|
switchDirectlyToTask.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||||
|
SettingUtils.enablePureTaskMode = isChecked
|
||||||
|
if (isChecked) {
|
||||||
|
MaterialDialog.Builder(requireContext()).content(getString(R.string.enabling_pure_client_mode)).positiveText(R.string.lab_yes).onPositive { _: MaterialDialog?, _: DialogAction? ->
|
||||||
|
XUtil.exitApp()
|
||||||
|
}.negativeText(R.string.lab_no).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//启用 {{定位信息}} 标签
|
//启用 {{定位信息}} 标签
|
||||||
private fun switchEnableLocationTag(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocationTag: SwitchButton) {
|
private fun switchEnableLocationTag(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocationTag: SwitchButton) {
|
||||||
switchEnableLocationTag.isChecked = SettingUtils.enableLocationTag
|
switchEnableLocationTag.isChecked = SettingUtils.enableLocationTag
|
||||||
|
@ -257,7 +257,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
for (condition in conditionList) {
|
for (condition in conditionList) {
|
||||||
itemListConditions.add(condition)
|
itemListConditions.add(condition)
|
||||||
}
|
}
|
||||||
Log.d(TAG, "initForm: $itemListConditions")
|
Log.d(TAG, "itemListConditions: $itemListConditions")
|
||||||
conditionsAdapter.notifyDataSetChanged()
|
conditionsAdapter.notifyDataSetChanged()
|
||||||
binding!!.layoutAddCondition.visibility = if (itemListConditions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
binding!!.layoutAddCondition.visibility = if (itemListConditions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
@ -266,7 +266,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
for (action in actionList) {
|
for (action in actionList) {
|
||||||
itemListActions.add(action)
|
itemListActions.add(action)
|
||||||
}
|
}
|
||||||
Log.d(TAG, "initForm: $itemListActions")
|
Log.d(TAG, "itemListActions: $itemListActions")
|
||||||
actionsAdapter.notifyDataSetChanged()
|
actionsAdapter.notifyDataSetChanged()
|
||||||
binding!!.layoutAddAction.visibility = if (itemListActions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
binding!!.layoutAddAction.visibility = if (itemListActions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
@ -292,7 +292,9 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
|
|
||||||
val lastExecTime = Date()
|
val lastExecTime = Date()
|
||||||
var nextExecTime = Date()
|
// 将毫秒部分设置为 0,避免因为毫秒部分不同导致的任务重复执行
|
||||||
|
lastExecTime.time = lastExecTime.time / 1000 * 1000
|
||||||
|
var nextExecTime = lastExecTime
|
||||||
val firstCondition = itemListConditions[0]
|
val firstCondition = itemListConditions[0]
|
||||||
taskType = firstCondition.type
|
taskType = firstCondition.type
|
||||||
|
|
||||||
@ -317,15 +319,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
|
|
||||||
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
||||||
return Task(
|
return Task(
|
||||||
taskId,
|
taskId, taskType, taskName, description.toString(), Gson().toJson(itemListConditions), Gson().toJson(itemListActions), status, lastExecTime, nextExecTime
|
||||||
taskType,
|
|
||||||
taskName,
|
|
||||||
description.toString(),
|
|
||||||
Gson().toJson(itemListConditions),
|
|
||||||
Gson().toJson(itemListActions),
|
|
||||||
status,
|
|
||||||
lastExecTime,
|
|
||||||
nextExecTime
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,11 +333,9 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
//定时任务
|
//定时任务
|
||||||
TASK_CONDITION_CRON -> {
|
TASK_CONDITION_CRON -> {
|
||||||
//取消旧任务的定时器 & 设置新的定时器
|
//取消旧任务的定时器 & 设置新的定时器
|
||||||
//CronUtils.cancelAlarm(task)
|
//AlarmUtils.cancelAlarm(task)
|
||||||
//CronUtils.scheduleAlarm(task)
|
//AlarmUtils.scheduleAlarm(task)
|
||||||
|
|
||||||
//val uuid = App.TaskIdToWorkerIdMap[task.id]
|
|
||||||
//uuid?.let { CronJobScheduler.cancelTask(it) }
|
|
||||||
CronJobScheduler.cancelTask(task.id)
|
CronJobScheduler.cancelTask(task.id)
|
||||||
CronJobScheduler.scheduleTask(task)
|
CronJobScheduler.scheduleTask(task)
|
||||||
}
|
}
|
||||||
@ -355,6 +347,10 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
try {
|
try {
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
Log.d(TAG, "onItemClick: $widgetInfo")
|
Log.d(TAG, "onItemClick: $widgetInfo")
|
||||||
|
if (pos > 0) {
|
||||||
|
XToastUtils.info("暂不支持,敬请期待……")
|
||||||
|
return
|
||||||
|
}
|
||||||
//判断点击的是条件还是动作
|
//判断点击的是条件还是动作
|
||||||
if (widgetInfo.classPath.contains(".condition.")) {
|
if (widgetInfo.classPath.contains(".condition.")) {
|
||||||
//判断是否已经添加过该类型条件
|
//判断是否已经添加过该类型条件
|
||||||
|
@ -10,7 +10,7 @@ import com.idormy.sms.forwarder.database.AppDatabase
|
|||||||
import com.idormy.sms.forwarder.database.entity.Task
|
import com.idormy.sms.forwarder.database.entity.Task
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
import com.idormy.sms.forwarder.utils.task.CronUtils
|
import com.idormy.sms.forwarder.utils.task.AlarmUtils
|
||||||
import gatewayapps.crondroid.CronExpression
|
import gatewayapps.crondroid.CronExpression
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ class AlarmReceiver : BroadcastReceiver() {
|
|||||||
Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
||||||
try {
|
try {
|
||||||
//取消旧任务的定时器
|
//取消旧任务的定时器
|
||||||
CronUtils.cancelAlarm(task)
|
AlarmUtils.cancelAlarm(task)
|
||||||
|
|
||||||
// 根据任务信息执行相应操作
|
// 根据任务信息执行相应操作
|
||||||
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
||||||
@ -64,7 +64,7 @@ class AlarmReceiver : BroadcastReceiver() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//设置新的定时器
|
//设置新的定时器
|
||||||
CronUtils.scheduleAlarm(task)
|
AlarmUtils.scheduleAlarm(task)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.e(TAG, "onReceive error $e")
|
Log.e(TAG, "onReceive error $e")
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ class SettingUtils private constructor() {
|
|||||||
var enablePureClientMode: Boolean by SharedPreference(SP_PURE_CLIENT_MODE, false)
|
var enablePureClientMode: Boolean by SharedPreference(SP_PURE_CLIENT_MODE, false)
|
||||||
|
|
||||||
//是否纯任务模式
|
//是否纯任务模式
|
||||||
var enablePureTaskMode: Boolean by SharedPreference(SP_PURE_TASK_MODE, true)
|
var enablePureTaskMode: Boolean by SharedPreference(SP_PURE_TASK_MODE, false)
|
||||||
|
|
||||||
//是否启用定位标签
|
//是否启用定位标签
|
||||||
var enableLocationTag: Boolean by SharedPreference(SP_LOCATION_TAG, false)
|
var enableLocationTag: Boolean by SharedPreference(SP_LOCATION_TAG, false)
|
||||||
|
@ -9,7 +9,7 @@ import android.os.Build
|
|||||||
import com.idormy.sms.forwarder.database.entity.Task
|
import com.idormy.sms.forwarder.database.entity.Task
|
||||||
import com.idormy.sms.forwarder.receiver.AlarmReceiver
|
import com.idormy.sms.forwarder.receiver.AlarmReceiver
|
||||||
|
|
||||||
class CronUtils {
|
class AlarmUtils {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@SuppressLint("StaticFieldLeak")
|
@SuppressLint("StaticFieldLeak")
|
@ -6,7 +6,7 @@ import androidx.work.ExistingWorkPolicy
|
|||||||
import androidx.work.OneTimeWorkRequestBuilder
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.idormy.sms.forwarder.database.entity.Task
|
import com.idormy.sms.forwarder.database.entity.Task
|
||||||
import com.idormy.sms.forwarder.workers.TaskWorker
|
import com.idormy.sms.forwarder.workers.CronWorker
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
@ -21,13 +21,13 @@ class CronJobScheduler {
|
|||||||
val delayInMillis = task.nextExecTime.time / 1000 * 1000 - currentTimeMillis
|
val delayInMillis = task.nextExecTime.time / 1000 * 1000 - currentTimeMillis
|
||||||
val inputData = Data.Builder().putLong("taskId", task.id).build()
|
val inputData = Data.Builder().putLong("taskId", task.id).build()
|
||||||
val taskRequest = if (delayInMillis <= 0L) {
|
val taskRequest = if (delayInMillis <= 0L) {
|
||||||
Log.d(TAG, "立即执行任务${task.id},delayInMillis = $delayInMillis")
|
Log.d(TAG, "任务${task.id}:立即执行,delayInMillis = $delayInMillis")
|
||||||
OneTimeWorkRequestBuilder<TaskWorker>()
|
OneTimeWorkRequestBuilder<CronWorker>()
|
||||||
.setInputData(inputData)
|
.setInputData(inputData)
|
||||||
.build()
|
.build()
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "延迟 $delayInMillis 毫秒执行任务${task.id}")
|
Log.d(TAG, "任务${task.id}:延迟 $delayInMillis 毫秒执行")
|
||||||
OneTimeWorkRequestBuilder<TaskWorker>()
|
OneTimeWorkRequestBuilder<CronWorker>()
|
||||||
.setInitialDelay(delayInMillis, TimeUnit.MILLISECONDS)
|
.setInitialDelay(delayInMillis, TimeUnit.MILLISECONDS)
|
||||||
.setInputData(inputData)
|
.setInputData(inputData)
|
||||||
.build()
|
.build()
|
||||||
|
@ -0,0 +1,69 @@
|
|||||||
|
package com.idormy.sms.forwarder.workers
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.util.Log
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.idormy.sms.forwarder.App
|
||||||
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.entity.task.SmsSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
|
||||||
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
|
import com.xuexiang.xutil.XUtil
|
||||||
|
|
||||||
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
|
class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||||
|
|
||||||
|
private val TAG: String = ActionWorker::class.java.simpleName
|
||||||
|
|
||||||
|
override suspend fun doWork(): Result {
|
||||||
|
val taskId = inputData.getLong("taskId", -1L)
|
||||||
|
val actionType = inputData.getInt("actionType", -1)
|
||||||
|
val actionSetting = inputData.getString("actionSetting")
|
||||||
|
Log.d(TAG, "taskId: $taskId, actionSetting: $actionSetting")
|
||||||
|
if (taskId == -1L || actionSetting == null) {
|
||||||
|
Log.d(TAG, "taskId is -1L or actionSetting is null")
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
|
||||||
|
when (actionType) {
|
||||||
|
TASK_ACTION_SENDSMS -> {
|
||||||
|
val smsSetting = Gson().fromJson(actionSetting, SmsSetting::class.java)
|
||||||
|
if (smsSetting == null) {
|
||||||
|
Log.d(TAG, "任务$taskId:smsSetting is null")
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
//获取卡槽信息
|
||||||
|
if (App.SimInfoList.isEmpty()) {
|
||||||
|
App.SimInfoList = PhoneUtils.getSimMultiInfo()
|
||||||
|
}
|
||||||
|
Log.d(TAG, App.SimInfoList.toString())
|
||||||
|
|
||||||
|
//发送卡槽: 1=SIM1, 2=SIM2
|
||||||
|
val simSlotIndex = smsSetting.simSlot - 1
|
||||||
|
//TODO:取不到卡槽信息时,采用默认卡槽发送
|
||||||
|
val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
|
||||||
|
|
||||||
|
val msg = if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
|
||||||
|
ResUtils.getString(R.string.no_sms_sending_permission)
|
||||||
|
} else {
|
||||||
|
PhoneUtils.sendSms(mSubscriptionId, smsSetting.phoneNumbers, smsSetting.msgContent) ?: "success"
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "任务$taskId:send sms result: $msg")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
Log.d(TAG, "任务$taskId:action.type is $actionType")
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,9 @@ package com.idormy.sms.forwarder.workers
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
|
import androidx.work.Data
|
||||||
|
import androidx.work.OneTimeWorkRequestBuilder
|
||||||
|
import androidx.work.WorkManager
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.App
|
import com.idormy.sms.forwarder.App
|
||||||
@ -11,13 +14,12 @@ import com.idormy.sms.forwarder.entity.task.CronSetting
|
|||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
||||||
import gatewayapps.crondroid.CronExpression
|
import gatewayapps.crondroid.CronExpression
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
class TaskWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||||
|
|
||||||
private val TAG: String = TaskWorker::class.java.simpleName
|
private val TAG: String = CronWorker::class.java.simpleName
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
val taskId = inputData.getLong("taskId", -1L)
|
val taskId = inputData.getLong("taskId", -1L)
|
||||||
@ -27,20 +29,31 @@ class TaskWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
}
|
}
|
||||||
|
|
||||||
val task = AppDatabase.getInstance(App.context).taskDao().getOne(taskId)
|
val task = AppDatabase.getInstance(App.context).taskDao().getOne(taskId)
|
||||||
|
if (task.status == 0) {
|
||||||
|
Log.d(TAG, "任务${task.id}:task is disabled")
|
||||||
|
return Result.success()
|
||||||
|
}
|
||||||
|
|
||||||
// 根据任务信息执行相应操作
|
// 根据任务信息执行相应操作
|
||||||
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
||||||
if (conditionList.isEmpty()) {
|
if (conditionList.isEmpty()) {
|
||||||
Log.d(TAG, "onReceive conditionList is empty")
|
Log.d(TAG, "任务${task.id}:conditionList is empty")
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
val firstCondition = conditionList.firstOrNull()
|
val firstCondition = conditionList.firstOrNull()
|
||||||
if (firstCondition == null) {
|
if (firstCondition == null) {
|
||||||
Log.d(TAG, "onReceive firstCondition is null")
|
Log.d(TAG, "任务${task.id}:firstCondition is null")
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
val cronSetting = Gson().fromJson(firstCondition.setting, CronSetting::class.java)
|
val cronSetting = Gson().fromJson(firstCondition.setting, CronSetting::class.java)
|
||||||
if (cronSetting == null) {
|
if (cronSetting == null) {
|
||||||
Log.d(TAG, "onReceive cronSetting is null")
|
Log.d(TAG, "任务${task.id}:cronSetting is null")
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 判断其他条件是否满足
|
||||||
|
if (false) {
|
||||||
|
Log.d(TAG, "任务${task.id}:其他条件不满足")
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,7 +65,7 @@ class TaskWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
// 将 nextExecTime 的毫秒部分设置为 0,避免因为毫秒部分不同导致的任务重复执行
|
// 将 nextExecTime 的毫秒部分设置为 0,避免因为毫秒部分不同导致的任务重复执行
|
||||||
nextExecTime.time = nextExecTime.time / 1000 * 1000
|
nextExecTime.time = nextExecTime.time / 1000 * 1000
|
||||||
task.nextExecTime = nextExecTime
|
task.nextExecTime = nextExecTime
|
||||||
Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
Log.d(TAG, "任务${task.id}:lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
||||||
|
|
||||||
// 自动禁用任务
|
// 自动禁用任务
|
||||||
if (task.nextExecTime.time / 1000 < now.time / 1000) {
|
if (task.nextExecTime.time / 1000 < now.time / 1000) {
|
||||||
@ -63,13 +76,25 @@ class TaskWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
AppDatabase.getInstance(App.context).taskDao().updateExecTime(task.id, task.lastExecTime, task.nextExecTime, task.status)
|
AppDatabase.getInstance(App.context).taskDao().updateExecTime(task.id, task.lastExecTime, task.nextExecTime, task.status)
|
||||||
|
|
||||||
if (task.status == 0) {
|
if (task.status == 0) {
|
||||||
Log.d(TAG, "onReceive task is disabled")
|
Log.d(TAG, "任务${task.id}:task is disabled")
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 执行具体任务
|
// TODO: 执行具体任务
|
||||||
Log.d(TAG, "执行具体任务,耗时 200 毫秒")
|
val actionList = Gson().fromJson(task.actions, Array<TaskSetting>::class.java).toMutableList()
|
||||||
delay(200L)
|
if (actionList.isEmpty()) {
|
||||||
|
Log.d(TAG, "任务${task.id}:actionsList is empty")
|
||||||
|
return Result.failure()
|
||||||
|
}
|
||||||
|
for (action in actionList) {
|
||||||
|
val actionData = Data.Builder()
|
||||||
|
.putLong("taskId", task.id)
|
||||||
|
.putInt("actionType", action.type)
|
||||||
|
.putString("actionSetting", action.setting)
|
||||||
|
.build()
|
||||||
|
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
|
||||||
|
WorkManager.getInstance().enqueue(actionRequest)
|
||||||
|
}
|
||||||
|
|
||||||
// 为新的 nextExecTime 调度下一次任务执行
|
// 为新的 nextExecTime 调度下一次任务执行
|
||||||
CronJobScheduler.cancelTask(task.id)
|
CronJobScheduler.cancelTask(task.id)
|
@ -39,9 +39,16 @@
|
|||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_actions_icons"
|
android:id="@+id/layout_actions_icons"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="horizontal" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tv_time"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal" />
|
android:layout_marginStart="5dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -1748,6 +1748,40 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/settingBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/pure_task_mode"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:ignore="RelativeOverlap" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/pure_task_mode_tips"
|
||||||
|
android:textSize="9sp"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||||
|
android:id="@+id/sb_directly_to_task"
|
||||||
|
style="@style/SwitchButtonStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
@ -989,6 +989,10 @@
|
|||||||
<string name="pure_client_mode_tips">When starting the APP, it will directly enter the active control client</string>
|
<string name="pure_client_mode_tips">When starting the APP, it will directly enter the active control client</string>
|
||||||
<string name="exit_pure_client_mode">Exit pure client mode</string>
|
<string name="exit_pure_client_mode">Exit pure client mode</string>
|
||||||
<string name="enabling_pure_client_mode">Do you want to quit the app immediately and start it manually to take effect in pure client mode?</string>
|
<string name="enabling_pure_client_mode">Do you want to quit the app immediately and start it manually to take effect in pure client mode?</string>
|
||||||
|
<string name="pure_task_mode">Directly To Task</string>
|
||||||
|
<string name="pure_task_mode_tips">When starting the APP, it will directly enter the task center</string>
|
||||||
|
<string name="exit_pure_task_mode">Exit pure task mode</string>
|
||||||
|
<string name="enabling_pure_task_mode">Do you want to quit the app immediately and start it manually to take effect in pure task mode?</string>
|
||||||
<string name="optional_components">Optional:</string>
|
<string name="optional_components">Optional:</string>
|
||||||
<string name="enable_cactus">Enable Cactus Keep Alive</string>
|
<string name="enable_cactus">Enable Cactus Keep Alive</string>
|
||||||
<string name="enabe_cactus_tips">Dual process foreground service/JobScheduler/WorkManager/1px/silent music</string>
|
<string name="enabe_cactus_tips">Dual process foreground service/JobScheduler/WorkManager/1px/silent music</string>
|
||||||
|
@ -990,6 +990,10 @@
|
|||||||
<string name="pure_client_mode_tips">启动APP时直接进入主动控制·客户端</string>
|
<string name="pure_client_mode_tips">启动APP时直接进入主动控制·客户端</string>
|
||||||
<string name="exit_pure_client_mode">退出纯客户端模式</string>
|
<string name="exit_pure_client_mode">退出纯客户端模式</string>
|
||||||
<string name="enabling_pure_client_mode">是否立即退出App,并手动启动以生效纯客户端模式?</string>
|
<string name="enabling_pure_client_mode">是否立即退出App,并手动启动以生效纯客户端模式?</string>
|
||||||
|
<string name="pure_task_mode">纯自动任务模式</string>
|
||||||
|
<string name="pure_task_mode_tips">启动APP时直接进入自动任务</string>
|
||||||
|
<string name="exit_pure_task_mode">退出纯自动任务模式</string>
|
||||||
|
<string name="enabling_pure_task_mode">是否立即退出App,并手动启动以生效纯自动任务模式?</string>
|
||||||
<string name="optional_components">可选组件:</string>
|
<string name="optional_components">可选组件:</string>
|
||||||
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
<string name="enable_cactus">启用 Cactus 增强保活措施(会增加耗电)</string>
|
||||||
<string name="enabe_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
<string name="enabe_cactus_tips">双进程前台服务/JobScheduler/WorkManager/1像素/无声音乐</string>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user