mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 01:17:41 +08:00
parent
0a651b2da2
commit
51149c95cd
@ -19,6 +19,7 @@
|
|||||||
tools:ignore="ProtectedPermissions" />
|
tools:ignore="ProtectedPermissions" />
|
||||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
|
||||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
<uses-permission
|
<uses-permission
|
||||||
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||||
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.idormy.sms.forwarder.entity.task
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
data class SmsSetting(
|
||||||
|
var description: String = "",
|
||||||
|
var simSlot: Int = 1,
|
||||||
|
var phoneNumbers: String = "",
|
||||||
|
var msgContent: String = "",
|
||||||
|
) : Serializable
|
@ -26,6 +26,7 @@ import com.idormy.sms.forwarder.databinding.FragmentTasksEditBinding
|
|||||||
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.*
|
import com.idormy.sms.forwarder.utils.*
|
||||||
|
import com.idormy.sms.forwarder.utils.task.CronUtils
|
||||||
import com.xuexiang.xaop.annotation.SingleClick
|
import com.xuexiang.xaop.annotation.SingleClick
|
||||||
import com.xuexiang.xpage.annotation.Page
|
import com.xuexiang.xpage.annotation.Page
|
||||||
import com.xuexiang.xpage.base.XPageFragment
|
import com.xuexiang.xpage.base.XPageFragment
|
||||||
@ -37,6 +38,7 @@ import com.xuexiang.xui.adapter.recyclerview.RecyclerViewHolder
|
|||||||
import com.xuexiang.xui.utils.DensityUtils
|
import com.xuexiang.xui.utils.DensityUtils
|
||||||
import com.xuexiang.xui.utils.WidgetUtils
|
import com.xuexiang.xui.utils.WidgetUtils
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
|
import gatewayapps.crondroid.CronExpression
|
||||||
import io.reactivex.SingleObserver
|
import io.reactivex.SingleObserver
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@ -214,6 +216,9 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
val taskNew = checkForm()
|
val taskNew = checkForm()
|
||||||
if (isClone) taskNew.id = 0
|
if (isClone) taskNew.id = 0
|
||||||
Log.d(TAG, taskNew.toString())
|
Log.d(TAG, taskNew.toString())
|
||||||
|
//应用任务
|
||||||
|
applyTask(taskNew)
|
||||||
|
//保存任务
|
||||||
viewModel.insertOrUpdate(taskNew)
|
viewModel.insertOrUpdate(taskNew)
|
||||||
XToastUtils.success(R.string.tipSaveSuccess)
|
XToastUtils.success(R.string.tipSaveSuccess)
|
||||||
popToBack()
|
popToBack()
|
||||||
@ -254,6 +259,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "initForm: $itemListConditions")
|
Log.d(TAG, "initForm: $itemListConditions")
|
||||||
conditionsAdapter.notifyDataSetChanged()
|
conditionsAdapter.notifyDataSetChanged()
|
||||||
|
binding!!.layoutAddCondition.visibility = if (itemListConditions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
if (task.actions.isNotEmpty()) {
|
if (task.actions.isNotEmpty()) {
|
||||||
val actionList = Gson().fromJson(task.actions, Array<TaskSetting>::class.java).toMutableList()
|
val actionList = Gson().fromJson(task.actions, Array<TaskSetting>::class.java).toMutableList()
|
||||||
@ -262,6 +268,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
}
|
}
|
||||||
Log.d(TAG, "initForm: $itemListActions")
|
Log.d(TAG, "initForm: $itemListActions")
|
||||||
actionsAdapter.notifyDataSetChanged()
|
actionsAdapter.notifyDataSetChanged()
|
||||||
|
binding!!.layoutAddAction.visibility = if (itemListActions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@ -283,7 +290,23 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
if (itemListActions.size <= 0) {
|
if (itemListActions.size <= 0) {
|
||||||
throw Exception("请添加执行动作")
|
throw Exception("请添加执行动作")
|
||||||
}
|
}
|
||||||
taskType = itemListConditions[0].type
|
|
||||||
|
val lastExecTime = Date()
|
||||||
|
var nextExecTime = Date()
|
||||||
|
val firstCondition = itemListConditions[0]
|
||||||
|
taskType = firstCondition.type
|
||||||
|
|
||||||
|
when (taskType) {
|
||||||
|
TASK_CONDITION_CRON -> {
|
||||||
|
//检查定时任务的时间设置
|
||||||
|
val cronSetting = Gson().fromJson(firstCondition.setting, CronSetting::class.java)
|
||||||
|
if (cronSetting.expression.isEmpty()) {
|
||||||
|
throw Exception("请设置定时任务的时间")
|
||||||
|
}
|
||||||
|
val cronExpression = CronExpression(cronSetting.expression)
|
||||||
|
nextExecTime = cronExpression.getNextValidTimeAfter(lastExecTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//拼接任务描述
|
//拼接任务描述
|
||||||
val description = StringBuilder()
|
val description = StringBuilder()
|
||||||
@ -293,12 +316,36 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
description.append(itemListActions.map { it.description }.toTypedArray().joinToString(","))
|
description.append(itemListActions.map { it.description }.toTypedArray().joinToString(","))
|
||||||
|
|
||||||
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
val status = if (binding!!.sbStatus.isChecked) STATUS_ON else STATUS_OFF
|
||||||
return Task(taskId, taskType, taskName, description.toString(), Gson().toJson(itemListConditions), Gson().toJson(itemListActions), status)
|
return Task(
|
||||||
|
taskId,
|
||||||
|
taskType,
|
||||||
|
taskName,
|
||||||
|
description.toString(),
|
||||||
|
Gson().toJson(itemListConditions),
|
||||||
|
Gson().toJson(itemListActions),
|
||||||
|
status,
|
||||||
|
lastExecTime,
|
||||||
|
nextExecTime
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//测试任务
|
||||||
private fun testTask(task: Task) {
|
private fun testTask(task: Task) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//应用任务
|
||||||
|
private fun applyTask(task: Task) {
|
||||||
|
when (task.type) {
|
||||||
|
//定时任务
|
||||||
|
TASK_CONDITION_CRON -> {
|
||||||
|
//取消旧任务的定时器
|
||||||
|
CronUtils.cancelAlarm(task)
|
||||||
|
//设置新的定时器
|
||||||
|
CronUtils.scheduleAlarm(task)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SingleClick
|
@SingleClick
|
||||||
override fun onItemClick(itemView: View, widgetInfo: PageInfo, pos: Int) {
|
override fun onItemClick(itemView: View, widgetInfo: PageInfo, pos: Int) {
|
||||||
try {
|
try {
|
||||||
@ -394,6 +441,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
itemListConditions[requestCode - 1] = taskSetting
|
itemListConditions[requestCode - 1] = taskSetting
|
||||||
}
|
}
|
||||||
conditionsAdapter.notifyDataSetChanged()
|
conditionsAdapter.notifyDataSetChanged()
|
||||||
|
binding!!.layoutAddCondition.visibility = if (itemListConditions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
} else if (resultCode in KEY_BACK_CODE_ACTION..KEY_BACK_CODE_ACTION + 999) {
|
} else if (resultCode in KEY_BACK_CODE_ACTION..KEY_BACK_CODE_ACTION + 999) {
|
||||||
setting = extras!!.getString(KEY_BACK_DATA_ACTION)
|
setting = extras!!.getString(KEY_BACK_DATA_ACTION)
|
||||||
if (setting == null) return
|
if (setting == null) return
|
||||||
@ -448,6 +496,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
itemListActions[requestCode - 1] = taskSetting
|
itemListActions[requestCode - 1] = taskSetting
|
||||||
}
|
}
|
||||||
actionsAdapter.notifyDataSetChanged()
|
actionsAdapter.notifyDataSetChanged()
|
||||||
|
binding!!.layoutAddAction.visibility = if (itemListActions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
Log.d(TAG, "requestCode:$requestCode resultCode:$resultCode setting:$setting")
|
Log.d(TAG, "requestCode:$requestCode resultCode:$resultCode setting:$setting")
|
||||||
}
|
}
|
||||||
@ -487,6 +536,7 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
private fun removeCondition(position: Int) {
|
private fun removeCondition(position: Int) {
|
||||||
itemListConditions.removeAt(position)
|
itemListConditions.removeAt(position)
|
||||||
conditionsAdapter.notifyItemRemoved(position)
|
conditionsAdapter.notifyItemRemoved(position)
|
||||||
|
binding!!.layoutAddCondition.visibility = if (itemListConditions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun editAction(position: Int) {
|
private fun editAction(position: Int) {
|
||||||
@ -507,5 +557,6 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
|||||||
private fun removeAction(position: Int) {
|
private fun removeAction(position: Int) {
|
||||||
itemListActions.removeAt(position)
|
itemListActions.removeAt(position)
|
||||||
actionsAdapter.notifyItemRemoved(position)
|
actionsAdapter.notifyItemRemoved(position)
|
||||||
|
binding!!.layoutAddAction.visibility = if (itemListActions.size >= MAX_SETTING_NUM) View.GONE else View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import android.view.ViewGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
||||||
@ -26,7 +26,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
|
|
||||||
@Page(name = "Frpc")
|
@Page(name = "Frpc")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class FrpcFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class FrpcFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = FrpcFragment::class.java.simpleName
|
private val TAG: String = FrpcFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -46,12 +46,12 @@ class FrpcFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickList
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_cron)
|
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_frpc)
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import android.view.ViewGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
||||||
@ -26,7 +26,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
|
|
||||||
@Page(name = "HttpServer")
|
@Page(name = "HttpServer")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class HttpServerFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class HttpServerFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = HttpServerFragment::class.java.simpleName
|
private val TAG: String = HttpServerFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -46,12 +46,12 @@ class HttpServerFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnCli
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_cron)
|
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_server)
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ class NotificationFragment : BaseFragment<FragmentRulesEditBinding?>(), View.OnC
|
|||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
titleBar = super.initTitle()!!.setImmersive(false)
|
titleBar = super.initTitle()!!.setImmersive(false)
|
||||||
titleBar!!.setTitle(R.string.menu_rules)
|
titleBar!!.setTitle(R.string.task_notification)
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,19 +1,32 @@
|
|||||||
package com.idormy.sms.forwarder.fragment.action
|
package com.idormy.sms.forwarder.fragment.action
|
||||||
|
|
||||||
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.app.ActivityCompat
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import com.hjq.permissions.OnPermissionCallback
|
||||||
|
import com.hjq.permissions.Permission
|
||||||
|
import com.hjq.permissions.XXPermissions
|
||||||
|
import com.idormy.sms.forwarder.App
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.SmsSetting
|
||||||
|
import com.idormy.sms.forwarder.server.model.ConfigData
|
||||||
|
import com.idormy.sms.forwarder.utils.EVENT_KEY_PHONE_NUMBERS
|
||||||
|
import com.idormy.sms.forwarder.utils.EVENT_KEY_SIM_SLOT
|
||||||
|
import com.idormy.sms.forwarder.utils.HttpServerUtils
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
|
import com.idormy.sms.forwarder.utils.KEY_TEST_ACTION
|
||||||
|
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||||
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
|
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
|
||||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||||
@ -21,12 +34,15 @@ import com.xuexiang.xaop.annotation.SingleClick
|
|||||||
import com.xuexiang.xpage.annotation.Page
|
import com.xuexiang.xpage.annotation.Page
|
||||||
import com.xuexiang.xrouter.annotation.AutoWired
|
import com.xuexiang.xrouter.annotation.AutoWired
|
||||||
import com.xuexiang.xrouter.launcher.XRouter
|
import com.xuexiang.xrouter.launcher.XRouter
|
||||||
|
import com.xuexiang.xrouter.utils.TextUtils
|
||||||
import com.xuexiang.xui.utils.CountDownButtonHelper
|
import com.xuexiang.xui.utils.CountDownButtonHelper
|
||||||
|
import com.xuexiang.xui.utils.ResUtils
|
||||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||||
|
import com.xuexiang.xutil.XUtil
|
||||||
|
|
||||||
@Page(name = "SendSms")
|
@Page(name = "SendSms")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||||
class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class SendSmsFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = SendSmsFragment::class.java.simpleName
|
private val TAG: String = SendSmsFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -36,8 +52,10 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
@AutoWired(name = KEY_EVENT_DATA_ACTION)
|
@AutoWired(name = KEY_EVENT_DATA_ACTION)
|
||||||
var eventData: String? = null
|
var eventData: String? = null
|
||||||
|
|
||||||
private var expression = "* * * * * ? *"
|
private var description = ""
|
||||||
private var description = "测试描述"
|
private var simSlot = 1
|
||||||
|
private var phoneNumbers = ""
|
||||||
|
private var msgContent = ""
|
||||||
|
|
||||||
override fun initArgs() {
|
override fun initArgs() {
|
||||||
XRouter.getInstance().inject(this)
|
XRouter.getInstance().inject(this)
|
||||||
@ -46,18 +64,19 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_cron)
|
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_sendsms)
|
||||||
return titleBar
|
return titleBar
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化控件
|
* 初始化控件
|
||||||
*/
|
*/
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
override fun initViews() {
|
override fun initViews() {
|
||||||
//测试按钮增加倒计时,避免重复点击
|
//测试按钮增加倒计时,避免重复点击
|
||||||
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
||||||
@ -71,11 +90,27 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//卡槽信息
|
||||||
|
val serverConfigStr = HttpServerUtils.serverConfig
|
||||||
|
if (!TextUtils.isEmpty(serverConfigStr)) {
|
||||||
|
val serverConfig: ConfigData = Gson().fromJson(serverConfigStr, object : TypeToken<ConfigData>() {}.type)
|
||||||
|
binding!!.rbSimSlot1.text = "SIM1:" + serverConfig.extraSim1
|
||||||
|
binding!!.rbSimSlot2.text = "SIM2:" + serverConfig.extraSim2
|
||||||
|
}
|
||||||
|
|
||||||
Log.d(TAG, "initViews eventData:$eventData")
|
Log.d(TAG, "initViews eventData:$eventData")
|
||||||
if (eventData != null) {
|
if (eventData != null) {
|
||||||
val settingVo = Gson().fromJson(eventData, CronSetting::class.java)
|
val settingVo = Gson().fromJson(eventData, SmsSetting::class.java)
|
||||||
Log.d(TAG, "initViews settingVo:$settingVo")
|
Log.d(TAG, "initViews settingVo:$settingVo")
|
||||||
|
|
||||||
|
simSlot = settingVo.simSlot
|
||||||
|
phoneNumbers = settingVo.phoneNumbers
|
||||||
|
msgContent = settingVo.msgContent
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding!!.rgSimSlot.check(if (simSlot == 1) R.id.rb_sim_slot_1 else R.id.rb_sim_slot_2)
|
||||||
|
binding!!.etPhoneNumbers.setText(phoneNumbers)
|
||||||
|
binding!!.etMsgContent.setText(msgContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@ -83,6 +118,12 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
binding!!.btnTest.setOnClickListener(this)
|
binding!!.btnTest.setOnClickListener(this)
|
||||||
binding!!.btnDel.setOnClickListener(this)
|
binding!!.btnDel.setOnClickListener(this)
|
||||||
binding!!.btnSave.setOnClickListener(this)
|
binding!!.btnSave.setOnClickListener(this)
|
||||||
|
LiveEventBus.get(EVENT_KEY_SIM_SLOT, Int::class.java).observeSticky(this) { value: Int ->
|
||||||
|
binding!!.rgSimSlot.check(if (value == 1) R.id.rb_sim_slot_2 else R.id.rb_sim_slot_1)
|
||||||
|
}
|
||||||
|
LiveEventBus.get(EVENT_KEY_PHONE_NUMBERS, String::class.java).observeSticky(this) { value: String ->
|
||||||
|
binding!!.etPhoneNumbers.setText(value)
|
||||||
|
}
|
||||||
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
|
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).observe(this) {
|
||||||
mCountDownHelper?.finish()
|
mCountDownHelper?.finish()
|
||||||
|
|
||||||
@ -100,16 +141,45 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.btn_test -> {
|
R.id.btn_test -> {
|
||||||
mCountDownHelper?.start()
|
mCountDownHelper?.start()
|
||||||
Thread {
|
|
||||||
try {
|
//检查发送短信权限是否获取
|
||||||
val settingVo = checkSetting()
|
XXPermissions.with(this)
|
||||||
Log.d(TAG, settingVo.toString())
|
.permission(Permission.SEND_SMS)
|
||||||
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post("success")
|
.request(object : OnPermissionCallback {
|
||||||
} catch (e: Exception) {
|
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||||
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
|
Thread {
|
||||||
e.printStackTrace()
|
try {
|
||||||
}
|
val settingVo = checkSetting()
|
||||||
}.start()
|
Log.d(TAG, settingVo.toString())
|
||||||
|
|
||||||
|
//获取卡槽信息
|
||||||
|
if (App.SimInfoList.isEmpty()) {
|
||||||
|
App.SimInfoList = PhoneUtils.getSimMultiInfo()
|
||||||
|
}
|
||||||
|
Log.d(TAG, App.SimInfoList.toString())
|
||||||
|
|
||||||
|
//发送卡槽: 1=SIM1, 2=SIM2
|
||||||
|
val simSlotIndex = settingVo.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, settingVo.phoneNumbers, settingVo.msgContent) ?: "success"
|
||||||
|
}
|
||||||
|
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(msg)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(e.message.toString())
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDenied(permissions: List<String>, never: Boolean) {
|
||||||
|
LiveEventBus.get(KEY_TEST_ACTION, String::class.java).post(ResUtils.getString(R.string.no_sms_sending_permission))
|
||||||
|
}
|
||||||
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,7 +205,21 @@ class SendSmsFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
|
|
||||||
//检查设置
|
//检查设置
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
private fun checkSetting(): CronSetting {
|
private fun checkSetting(): SmsSetting {
|
||||||
return CronSetting(expression, description)
|
phoneNumbers = binding!!.etPhoneNumbers.text.toString().trim()
|
||||||
|
if (!getString(R.string.phone_numbers_regex).toRegex().matches(phoneNumbers)) {
|
||||||
|
throw Exception(getString(R.string.phone_numbers_error))
|
||||||
|
}
|
||||||
|
|
||||||
|
msgContent = binding!!.etMsgContent.text.toString().trim()
|
||||||
|
if (!getString(R.string.msg_content_regex).toRegex().matches(msgContent)) {
|
||||||
|
throw Exception(getString(R.string.msg_content_error))
|
||||||
|
}
|
||||||
|
|
||||||
|
simSlot = if (binding!!.rgSimSlot.checkedRadioButtonId == R.id.rb_sim_slot_2) 2 else 1
|
||||||
|
|
||||||
|
description = String.format(getString(R.string.send_sms_to), simSlot, phoneNumbers)
|
||||||
|
|
||||||
|
return SmsSetting(description, simSlot, phoneNumbers, msgContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -9,7 +9,7 @@ import android.view.ViewGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
||||||
@ -26,7 +26,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
|
|
||||||
@Page(name = "Battery")
|
@Page(name = "Battery")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class BatteryFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class BatteryFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = BatteryFragment::class.java.simpleName
|
private val TAG: String = BatteryFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -46,8 +46,8 @@ class BatteryFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
|
@ -9,7 +9,7 @@ import android.view.ViewGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
||||||
@ -26,7 +26,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
|
|
||||||
@Page(name = "Charge")
|
@Page(name = "Charge")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class ChargeFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class ChargeFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = ChargeFragment::class.java.simpleName
|
private val TAG: String = ChargeFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -46,8 +46,8 @@ class ChargeFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickLi
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
|
@ -13,7 +13,7 @@ import android.widget.RadioGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksConditionCronBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
||||||
@ -37,7 +37,7 @@ import java.util.Locale
|
|||||||
|
|
||||||
@Page(name = "Cron")
|
@Page(name = "Cron")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class CronFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class CronFragment : BaseFragment<FragmentTasksConditionCronBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = CronFragment::class.java.simpleName
|
private val TAG: String = CronFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -87,8 +87,8 @@ class CronFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickList
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksConditionCronBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksConditionCronBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
|
@ -9,7 +9,7 @@ import android.view.ViewGroup
|
|||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
import com.idormy.sms.forwarder.core.BaseFragment
|
import com.idormy.sms.forwarder.core.BaseFragment
|
||||||
import com.idormy.sms.forwarder.databinding.FragmentTasksCronBinding
|
import com.idormy.sms.forwarder.databinding.FragmentTasksActionSendSmsBinding
|
||||||
import com.idormy.sms.forwarder.entity.task.CronSetting
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_BACK_DATA_CONDITION
|
||||||
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
|
||||||
@ -26,7 +26,7 @@ import com.xuexiang.xui.widget.actionbar.TitleBar
|
|||||||
|
|
||||||
@Page(name = "Network")
|
@Page(name = "Network")
|
||||||
@Suppress("PrivatePropertyName")
|
@Suppress("PrivatePropertyName")
|
||||||
class NetworkFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickListener {
|
class NetworkFragment : BaseFragment<FragmentTasksActionSendSmsBinding?>(), View.OnClickListener {
|
||||||
|
|
||||||
private val TAG: String = NetworkFragment::class.java.simpleName
|
private val TAG: String = NetworkFragment::class.java.simpleName
|
||||||
var titleBar: TitleBar? = null
|
var titleBar: TitleBar? = null
|
||||||
@ -46,8 +46,8 @@ class NetworkFragment : BaseFragment<FragmentTasksCronBinding?>(), View.OnClickL
|
|||||||
override fun viewBindingInflate(
|
override fun viewBindingInflate(
|
||||||
inflater: LayoutInflater,
|
inflater: LayoutInflater,
|
||||||
container: ViewGroup,
|
container: ViewGroup,
|
||||||
): FragmentTasksCronBinding {
|
): FragmentTasksActionSendSmsBinding {
|
||||||
return FragmentTasksCronBinding.inflate(inflater, container, false)
|
return FragmentTasksActionSendSmsBinding.inflate(inflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun initTitle(): TitleBar? {
|
override fun initTitle(): TitleBar? {
|
||||||
|
@ -4,20 +4,70 @@ import android.content.BroadcastReceiver
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.idormy.sms.forwarder.App
|
||||||
|
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.TaskSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.task.CronUtils
|
||||||
|
import gatewayapps.crondroid.CronExpression
|
||||||
|
import java.util.Date
|
||||||
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName", "DEPRECATION")
|
||||||
class AlarmReceiver : BroadcastReceiver() {
|
class AlarmReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
val TAG: String = AlarmReceiver::class.java.simpleName
|
val TAG: String = AlarmReceiver::class.java.simpleName
|
||||||
|
|
||||||
override fun onReceive(context: Context, intent: Intent) {
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
val task = intent.getParcelableExtra<Task>("task")
|
val task = intent.getParcelableExtra<Task>("TASK")
|
||||||
|
if (task == null) {
|
||||||
// 根据任务信息执行相应操作
|
Log.d(TAG, "onReceive task is null")
|
||||||
if (task != null) {
|
return
|
||||||
Log.d(TAG, "onReceive task $task")
|
|
||||||
// 处理任务逻辑,例如执行特定操作或者更新界面
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "onReceive task $task")
|
||||||
|
Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
||||||
|
try {
|
||||||
|
//取消旧任务的定时器
|
||||||
|
CronUtils.cancelAlarm(task)
|
||||||
|
|
||||||
|
// 根据任务信息执行相应操作
|
||||||
|
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
||||||
|
if (conditionList.isEmpty()) {
|
||||||
|
Log.d(TAG, "onReceive conditionList is empty")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val firstCondition = conditionList.firstOrNull()
|
||||||
|
if (firstCondition == null) {
|
||||||
|
Log.d(TAG, "onReceive firstCondition is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val cronSetting = Gson().fromJson(firstCondition.setting, CronSetting::class.java)
|
||||||
|
if (cronSetting == null) {
|
||||||
|
Log.d(TAG, "onReceive cronSetting is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 更新任务的上次执行时间和下次执行时间
|
||||||
|
val cronExpression = CronExpression(cronSetting.expression)
|
||||||
|
task.lastExecTime = Date()
|
||||||
|
task.nextExecTime = cronExpression.getNextValidTimeAfter(task.lastExecTime)
|
||||||
|
Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
|
||||||
|
// 自动禁用任务
|
||||||
|
if (task.nextExecTime <= task.lastExecTime) {
|
||||||
|
task.status = 0
|
||||||
|
}
|
||||||
|
// 更新任务信息
|
||||||
|
AppDatabase.getInstance(App.context).taskDao().update(task)
|
||||||
|
if (task.status == 0) {
|
||||||
|
Log.d(TAG, "onReceive task is disabled")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//设置新的定时器
|
||||||
|
CronUtils.scheduleAlarm(task)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e(TAG, "onReceive error $e")
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ import java.text.SimpleDateFormat
|
|||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@SuppressLint("SimpleDateFormat")
|
@SuppressLint("SimpleDateFormat")
|
||||||
@Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE", "DEPRECATION")
|
@Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE", "DEPRECATION", "LiftReturnOrAssignment")
|
||||||
class ForegroundService : Service() {
|
class ForegroundService : Service() {
|
||||||
|
|
||||||
private val TAG: String = "ForegroundService"
|
private val TAG: String = "ForegroundService"
|
||||||
|
@ -482,6 +482,7 @@ var CLIENT_FRAGMENT_LIST = listOf(
|
|||||||
)
|
)
|
||||||
|
|
||||||
//自动任务
|
//自动任务
|
||||||
|
const val MAX_SETTING_NUM = 5 //最大条件/动作设置条数
|
||||||
const val KEY_TEST_CONDITION = "key_test_condition"
|
const val KEY_TEST_CONDITION = "key_test_condition"
|
||||||
const val KEY_EVENT_DATA_CONDITION = "event_data_condition"
|
const val KEY_EVENT_DATA_CONDITION = "event_data_condition"
|
||||||
const val KEY_BACK_CODE_CONDITION = 1000
|
const val KEY_BACK_CODE_CONDITION = 1000
|
||||||
|
@ -5,10 +5,10 @@ import android.app.AlarmManager
|
|||||||
import android.app.PendingIntent
|
import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
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
|
||||||
|
|
||||||
@Suppress("unused")
|
|
||||||
class CronUtils {
|
class CronUtils {
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
@ -19,48 +19,51 @@ class CronUtils {
|
|||||||
this.context = context.applicationContext
|
this.context = context.applicationContext
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateTaskAndScheduleAlarm(task: Task) {
|
fun cancelAlarm(task: Task?) {
|
||||||
val oldTask = getOldTask(task.id) // 获取旧的任务信息
|
|
||||||
cancelAlarm(oldTask) // 取消旧任务的定时器
|
|
||||||
|
|
||||||
updateTaskInDatabase(task) // 更新任务信息(例如,更新数据库中的任务信息)
|
|
||||||
scheduleAlarm(task) // 设置新的定时器
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun cancelAlarm(task: Task?) {
|
|
||||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
val alarmIntent = Intent(context, AlarmReceiver::class.java)
|
val alarmIntent = Intent(context, AlarmReceiver::class.java)
|
||||||
val requestCode = task?.id?.toInt() ?: -1
|
val requestCode = task?.id?.toInt() ?: -1
|
||||||
|
|
||||||
val pendingIntent = PendingIntent.getBroadcast(context, requestCode, alarmIntent, PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_IMMUTABLE)
|
val pendingIntent = PendingIntent.getBroadcast(
|
||||||
|
context,
|
||||||
|
requestCode,
|
||||||
|
alarmIntent,
|
||||||
|
PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_MUTABLE
|
||||||
|
)
|
||||||
pendingIntent?.let {
|
pendingIntent?.let {
|
||||||
alarmManager.cancel(it)
|
alarmManager.cancel(it)
|
||||||
it.cancel()
|
it.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun scheduleAlarm(task: Task) {
|
@SuppressLint("ScheduleExactAlarm")
|
||||||
|
fun scheduleAlarm(task: Task) {
|
||||||
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
|
||||||
val alarmIntent = Intent(context, AlarmReceiver::class.java)
|
val alarmIntent = Intent(context, AlarmReceiver::class.java)
|
||||||
alarmIntent.putExtra("task", task)
|
|
||||||
val requestCode = task.id.toInt()
|
val requestCode = task.id.toInt()
|
||||||
val pendingIntent = PendingIntent.getBroadcast(context, requestCode, alarmIntent, PendingIntent.FLAG_IMMUTABLE)
|
alarmIntent.putExtra("TASK", task)
|
||||||
//val now = Calendar.getInstance()
|
val pendingIntent = PendingIntent.getBroadcast(
|
||||||
val nextExecutionTime = task.nextExecTime.time
|
context,
|
||||||
|
requestCode,
|
||||||
alarmManager.setExact(
|
alarmIntent,
|
||||||
AlarmManager.RTC_WAKEUP, nextExecutionTime, pendingIntent
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO:设置闹钟,低电量模式下无法设置精确闹钟
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
alarmManager.setExactAndAllowWhileIdle(
|
||||||
|
AlarmManager.RTC_WAKEUP,
|
||||||
|
task.nextExecTime.time,
|
||||||
|
pendingIntent
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
alarmManager.setExact(
|
||||||
|
AlarmManager.RTC_WAKEUP,
|
||||||
|
task.nextExecTime.time,
|
||||||
|
pendingIntent
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOldTask(taskId: Long): Task {
|
|
||||||
// 实现获取旧任务信息的逻辑
|
|
||||||
// 返回旧任务信息(Task对象)
|
|
||||||
return Task()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun updateTaskInDatabase(task: Task) {
|
|
||||||
// 实现更新数据库中任务信息的逻辑
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,8 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="10dp"
|
android:layout_margin="10dp"
|
||||||
android:contentDescription="@string/api_sms_send"
|
android:contentDescription="@string/api_sms_send"
|
||||||
app:srcCompat="@drawable/icon_api_sms_send" />
|
app:srcCompat="@drawable/icon_api_sms_send"
|
||||||
|
tools:ignore="ImageContrastCheck" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/senderBarStyle"
|
style="@style/senderBarStyle"
|
||||||
@ -41,18 +42,21 @@
|
|||||||
<RadioGroup
|
<RadioGroup
|
||||||
android:id="@+id/rg_sim_slot"
|
android:id="@+id/rg_sim_slot"
|
||||||
style="@style/rg_style"
|
style="@style/rg_style"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="@dimen/config_padding_5dp">
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_sim_slot_1"
|
android:id="@+id/rb_sim_slot_1"
|
||||||
style="@style/rg_rb_style_match"
|
style="@style/rg_rb_style_match"
|
||||||
android:checked="true"
|
android:checked="true"
|
||||||
android:text="@string/sim1" />
|
android:text="@string/sim1"
|
||||||
|
tools:ignore="TouchTargetSizeCheck" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_sim_slot_2"
|
android:id="@+id/rb_sim_slot_2"
|
||||||
style="@style/rg_rb_style_match"
|
style="@style/rg_rb_style_match"
|
||||||
android:text="@string/sim2" />
|
android:text="@string/sim2"
|
||||||
|
tools:ignore="TouchTargetSizeCheck" />
|
||||||
|
|
||||||
</RadioGroup>
|
</RadioGroup>
|
||||||
|
|
||||||
@ -78,7 +82,8 @@
|
|||||||
app:met_clearButton="true"
|
app:met_clearButton="true"
|
||||||
app:met_errorMessage="@string/phone_numbers_error"
|
app:met_errorMessage="@string/phone_numbers_error"
|
||||||
app:met_regexp="@string/phone_numbers_regex"
|
app:met_regexp="@string/phone_numbers_regex"
|
||||||
app:met_validateOnFocusLost="true" />
|
app:met_validateOnFocusLost="true"
|
||||||
|
tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -105,7 +110,8 @@
|
|||||||
app:met_maxCharacters="390"
|
app:met_maxCharacters="390"
|
||||||
app:met_regexp="@string/msg_content_regex"
|
app:met_regexp="@string/msg_content_regex"
|
||||||
app:met_validateOnFocusLost="true"
|
app:met_validateOnFocusLost="true"
|
||||||
app:mlet_hintText="@string/msg_content_hint" />
|
app:mlet_hintText="@string/msg_content_hint"
|
||||||
|
tools:ignore="TextContrastCheck" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -126,7 +132,7 @@
|
|||||||
android:drawableStart="@drawable/ic_send_white"
|
android:drawableStart="@drawable/ic_send_white"
|
||||||
android:paddingStart="20dp"
|
android:paddingStart="20dp"
|
||||||
android:text="@string/send"
|
android:text="@string/send"
|
||||||
tools:ignore="RtlSymmetry" />
|
tools:ignore="RtlSymmetry,TouchTargetSizeCheck,TextContrastCheck" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
152
app/src/main/res/layout/fragment_tasks_action_send_sms.xml
Normal file
152
app/src/main/res/layout/fragment_tasks_action_send_sms.xml
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="?attr/xui_config_color_background"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<androidx.core.widget.NestedScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:overScrollMode="never">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="5dp"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/senderBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/sim_slot" />
|
||||||
|
|
||||||
|
<RadioGroup
|
||||||
|
android:id="@+id/rg_sim_slot"
|
||||||
|
style="@style/rg_style"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingBottom="@dimen/config_padding_5dp">
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_sim_slot_1"
|
||||||
|
style="@style/rg_rb_style_match"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/sim1"
|
||||||
|
tools:ignore="TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<RadioButton
|
||||||
|
android:id="@+id/rb_sim_slot_2"
|
||||||
|
style="@style/rg_rb_style_match"
|
||||||
|
android:text="@string/sim2"
|
||||||
|
tools:ignore="TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
</RadioGroup>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/senderBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/phone_numbers" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
android:id="@+id/et_phone_numbers"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/phone_numbers_hint"
|
||||||
|
android:singleLine="true"
|
||||||
|
app:met_clearButton="true"
|
||||||
|
app:met_errorMessage="@string/phone_numbers_error"
|
||||||
|
app:met_regexp="@string/phone_numbers_regex"
|
||||||
|
app:met_validateOnFocusLost="true"
|
||||||
|
tools:ignore="TouchTargetSizeCheck,TextContrastCheck" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
style="@style/senderBarStyle"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/msg_content" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.edittext.materialedittext.MaterialEditText
|
||||||
|
android:id="@+id/et_msg_content"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="start|top"
|
||||||
|
android:hint="@string/msg_content_hint"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
app:met_clearButton="true"
|
||||||
|
app:met_errorMessage="@string/msg_content_error"
|
||||||
|
app:met_maxCharacters="390"
|
||||||
|
app:met_regexp="@string/msg_content_regex"
|
||||||
|
app:met_validateOnFocusLost="true"
|
||||||
|
app:mlet_hintText="@string/msg_content_hint"
|
||||||
|
tools:ignore="TextContrastCheck" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_del"
|
||||||
|
style="@style/SuperButton.Gray.Icon"
|
||||||
|
android:drawableStart="@drawable/icon_delete"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/discard"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_save"
|
||||||
|
style="@style/SuperButton.Blue.Icon"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:drawableStart="@drawable/icon_save"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/submit"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
<com.xuexiang.xui.widget.textview.supertextview.SuperButton
|
||||||
|
android:id="@+id/btn_test"
|
||||||
|
style="@style/SuperButton.Green.Icon"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:drawableStart="@drawable/icon_test"
|
||||||
|
android:paddingStart="15dp"
|
||||||
|
android:text="@string/test"
|
||||||
|
android:textSize="11sp"
|
||||||
|
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
@ -262,6 +262,7 @@
|
|||||||
android:text="@string/test"
|
android:text="@string/test"
|
||||||
android:textColor="#FFFFFF"
|
android:textColor="#FFFFFF"
|
||||||
android:textSize="11sp"
|
android:textSize="11sp"
|
||||||
|
android:visibility="gone"
|
||||||
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
tools:ignore="RtlSymmetry,TextContrastCheck,TouchTargetSizeCheck" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
@ -1108,8 +1108,8 @@
|
|||||||
<string name="task_network">Network</string>
|
<string name="task_network">Network</string>
|
||||||
<string name="task_sendsms">Send Sms</string>
|
<string name="task_sendsms">Send Sms</string>
|
||||||
<string name="task_notification">Notification</string>
|
<string name="task_notification">Notification</string>
|
||||||
<string name="task_frpc">Frpc</string>
|
<string name="task_frpc">Frpc Setting</string>
|
||||||
<string name="task_server">HttpServer</string>
|
<string name="task_server">Server Setting</string>
|
||||||
|
|
||||||
<string name="second">Second</string>
|
<string name="second">Second</string>
|
||||||
<string name="minute">Minute</string>
|
<string name="minute">Minute</string>
|
||||||
@ -1166,4 +1166,6 @@
|
|||||||
<string name="cron_expression_check">Cron Expression Test Result</string>
|
<string name="cron_expression_check">Cron Expression Test Result</string>
|
||||||
<string name="invalid_cron_expression">Cron expression is invalid:\n%s</string>
|
<string name="invalid_cron_expression">Cron expression is invalid:\n%s</string>
|
||||||
<string name="next_execution_times">The next %s execution times:\n%s</string>
|
<string name="next_execution_times">The next %s execution times:\n%s</string>
|
||||||
|
|
||||||
|
<string name="send_sms_to">Use SIM-%s to send sms\n%s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -1109,8 +1109,8 @@
|
|||||||
<string name="task_network">网络状态</string>
|
<string name="task_network">网络状态</string>
|
||||||
<string name="task_sendsms">发送短信</string>
|
<string name="task_sendsms">发送短信</string>
|
||||||
<string name="task_notification">通道推送</string>
|
<string name="task_notification">通道推送</string>
|
||||||
<string name="task_frpc">Frpc</string>
|
<string name="task_frpc">设置 Frpc</string>
|
||||||
<string name="task_server">HttpServer</string>
|
<string name="task_server">设置 HttpServer</string>
|
||||||
|
|
||||||
<string name="second">秒</string>
|
<string name="second">秒</string>
|
||||||
<string name="minute">分</string>
|
<string name="minute">分</string>
|
||||||
@ -1167,4 +1167,6 @@
|
|||||||
<string name="cron_expression_check">Cron表达式测试结果</string>
|
<string name="cron_expression_check">Cron表达式测试结果</string>
|
||||||
<string name="invalid_cron_expression">Cron表达式无效:\n%s</string>
|
<string name="invalid_cron_expression">Cron表达式无效:\n%s</string>
|
||||||
<string name="next_execution_times">最近 %s 次运行时间:\n%s</string>
|
<string name="next_execution_times">最近 %s 次运行时间:\n%s</string>
|
||||||
|
|
||||||
|
<string name="send_sms_to">通过卡槽 SIM-%s 发送短信到:\n%s</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -225,6 +225,7 @@
|
|||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="rg_rb_style_match">
|
<style name="rg_rb_style_match">
|
||||||
|
<item name="android:layout_marginTop">5dp</item>
|
||||||
<item name="android:layout_width">match_parent</item>
|
<item name="android:layout_width">match_parent</item>
|
||||||
<item name="android:layout_height">wrap_content</item>
|
<item name="android:layout_height">wrap_content</item>
|
||||||
<item name="android:singleLine">true</item>
|
<item name="android:singleLine">true</item>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user