新增:自动任务·快捷指令 —— 到达地点&离开地点

pull/408/head
pppscn 10 months ago
parent 0d77eac6ce
commit d4ac2ed38e

@ -88,6 +88,7 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
val LocationClient by lazy { LocationClient(context) } val LocationClient by lazy { LocationClient(context) }
val Geocoder by lazy { Geocoder(context) } val Geocoder by lazy { Geocoder(context) }
val DateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) } val DateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) }
val GeofenceStatusMap = mutableMapOf<Long, Boolean>() //是否已进入/离开围栏
} }
override fun attachBaseContext(base: Context) { override fun attachBaseContext(base: Context) {

@ -72,6 +72,12 @@ class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
holder.binding.ivDelete.setOnClickListener { view: View? -> holder.binding.ivDelete.setOnClickListener { view: View? ->
itemClickListener.onItemClicked(view, item) itemClickListener.onItemClicked(view, item)
} }
holder.binding.sbEnableTask.isChecked = item.status == 1
holder.binding.sbEnableTask.setOnCheckedChangeListener { view: View, isChecked ->
item.status = if (isChecked) 1 else 0
itemClickListener.onItemClicked(view, item)
}
} else { } else {
holder.binding.layoutImage.visibility = View.VISIBLE holder.binding.layoutImage.visibility = View.VISIBLE
holder.binding.layoutIcons.visibility = View.GONE holder.binding.layoutIcons.visibility = View.GONE
@ -83,6 +89,7 @@ class TaskPagingAdapter(private val itemClickListener: OnItemClickListener) : Pa
holder.binding.ivStatus.setImageResource(item.statusImageId) holder.binding.ivStatus.setImageResource(item.statusImageId)
holder.binding.ivEdit.visibility = View.GONE holder.binding.ivEdit.visibility = View.GONE
holder.binding.ivDelete.visibility = View.GONE holder.binding.ivDelete.visibility = View.GONE
holder.binding.sbEnableTask.visibility = View.GONE
} }
holder.binding.tvName.text = item.name holder.binding.tvName.text = item.name
holder.binding.tvDescription.text = item.description holder.binding.tvDescription.text = item.description

@ -59,4 +59,7 @@ interface TaskDao {
@Query("DELETE FROM Task") @Query("DELETE FROM Task")
fun deleteAll() fun deleteAll()
@Query("UPDATE Task SET status = :status WHERE id = :id")
fun updateStatus(id: Long, status: Int)
} }

@ -38,4 +38,8 @@ class TaskViewModel(private val dao: TaskDao) : ViewModel() {
fun delete(id: Long) = ioThread { fun delete(id: Long) = ioThread {
dao.delete(id) dao.delete(id)
} }
fun updateStatus(id: Long, status: Int) = ioThread {
dao.updateStatus(id, status)
}
} }

@ -25,9 +25,7 @@ data class LocationSetting(
} }
} }
fun calculateDistance( fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
lat1: Double, lon1: Double, lat2: Double, lon2: Double
): Double {
val earthRadius = 6371000.0 // 地球平均半径,单位:米 val earthRadius = 6371000.0 // 地球平均半径,单位:米
val latDistance = Math.toRadians(lat2 - lat1) val latDistance = Math.toRadians(lat2 - lat1)
val lonDistance = Math.toRadians(lon2 - lon1) val lonDistance = Math.toRadians(lon2 - lon1)

@ -13,6 +13,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.gson.Gson import com.google.gson.Gson
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.adapter.ItemMoveCallback import com.idormy.sms.forwarder.adapter.ItemMoveCallback
import com.idormy.sms.forwarder.adapter.TaskSettingAdapter import com.idormy.sms.forwarder.adapter.TaskSettingAdapter
@ -25,6 +26,7 @@ import com.idormy.sms.forwarder.database.viewmodel.TaskViewModel
import com.idormy.sms.forwarder.databinding.FragmentTasksEditBinding 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.service.LocationService
import com.idormy.sms.forwarder.utils.* import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.utils.task.CronJobScheduler import com.idormy.sms.forwarder.utils.task.CronJobScheduler
import com.xuexiang.xaop.annotation.SingleClick import com.xuexiang.xaop.annotation.SingleClick
@ -39,6 +41,8 @@ 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 com.xuexiang.xui.widget.alpha.XUIAlphaTextView import com.xuexiang.xui.widget.alpha.XUIAlphaTextView
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
import gatewayapps.crondroid.CronExpression import gatewayapps.crondroid.CronExpression
import io.reactivex.SingleObserver import io.reactivex.SingleObserver
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -363,6 +367,25 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
XToastUtils.error(getString(R.string.condition_already_exists)) XToastUtils.error(getString(R.string.condition_already_exists))
return return
} }
//必须开启定位服务,才能使用进入地点 或 离开地址 类型条件
if ((typeCondition == TASK_CONDITION_TO_ADDRESS || typeCondition == TASK_CONDITION_LEAVE_ADDRESS) && !App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext())
.iconRes(R.drawable.auto_task_icon_location)
.title(R.string.enable_location)
.content(R.string.enable_location_dialog)
.cancelable(false)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
SettingUtils.enableLocation = true
val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = "START"
requireContext().startService(serviceIntent)
}.show()
return
}
//进入地点 或 离开地址 类型条件互斥
if ((typeCondition == TASK_CONDITION_TO_ADDRESS || typeCondition == TASK_CONDITION_LEAVE_ADDRESS) && (item.type == TASK_CONDITION_TO_ADDRESS || item.type == TASK_CONDITION_LEAVE_ADDRESS)) { if ((typeCondition == TASK_CONDITION_TO_ADDRESS || typeCondition == TASK_CONDITION_LEAVE_ADDRESS) && (item.type == TASK_CONDITION_TO_ADDRESS || item.type == TASK_CONDITION_LEAVE_ADDRESS)) {
XToastUtils.error(getString(R.string.only_one_location_condition)) XToastUtils.error(getString(R.string.only_one_location_condition))
return return

@ -104,6 +104,10 @@ class TasksFragment : BaseFragment<FragmentTasksBinding?>(), TaskPagingAdapter.O
override fun onItemClicked(view: View?, item: Task) { override fun onItemClicked(view: View?, item: Task) {
when (view?.id) { when (view?.id) {
R.id.sb_enable_task -> {
viewModel.updateStatus(item.id, item.status)
}
R.id.iv_copy -> { R.id.iv_copy -> {
PageOption.to(TasksEditFragment::class.java) PageOption.to(TasksEditFragment::class.java)
.setNewActivity(true).putLong(KEY_TASK_ID, item.id) .setNewActivity(true).putLong(KEY_TASK_ID, item.id)

@ -7,14 +7,18 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.gson.Gson import com.google.gson.Gson
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.FragmentTasksConditionLeaveAddressBinding import com.idormy.sms.forwarder.databinding.FragmentTasksConditionLeaveAddressBinding
import com.idormy.sms.forwarder.entity.task.LocationSetting import com.idormy.sms.forwarder.entity.task.LocationSetting
import com.idormy.sms.forwarder.service.LocationService
import com.idormy.sms.forwarder.utils.HttpServerUtils
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_BACK_DESCRIPTION_CONDITION import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_CONDITION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS
import com.idormy.sms.forwarder.utils.XToastUtils import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
@ -24,6 +28,8 @@ import com.xuexiang.xrouter.annotation.AutoWired
import com.xuexiang.xrouter.launcher.XRouter import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
@Page(name = "LeaveAddress") @Page(name = "LeaveAddress")
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
@ -98,6 +104,7 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
binding!!.btnTest.setOnClickListener(this) binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this) binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this) binding!!.btnSave.setOnClickListener(this)
binding!!.btnCurrentCoordinates.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) { LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) {
mCountDownHelper?.finish() mCountDownHelper?.finish()
@ -113,6 +120,34 @@ class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBind
override fun onClick(v: View) { override fun onClick(v: View) {
try { try {
when (v.id) { when (v.id) {
R.id.btn_current_coordinates -> {
if (!App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext())
.iconRes(R.drawable.auto_task_icon_location)
.title(R.string.enable_location)
.content(R.string.enable_location_dialog)
.cancelable(false)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
SettingUtils.enableLocation = true
val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = "START"
requireContext().startService(serviceIntent)
}.show()
return
}
val location = HttpServerUtils.apiLocationCache
if (location.latitude == 0.0 || location.longitude == 0.0) {
XToastUtils.error(getString(R.string.location_failed), 30000)
return
}
binding!!.etLatitude.setText(location.latitude.toString())
binding!!.etLongitude.setText(location.longitude.toString())
XToastUtils.success(String.format(getString(R.string.current_address), location.address), 30000)
}
R.id.btn_test -> { R.id.btn_test -> {
mCountDownHelper?.start() mCountDownHelper?.start()
Thread { Thread {

@ -7,14 +7,18 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.gson.Gson import com.google.gson.Gson
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.FragmentTasksConditionToAddressBinding import com.idormy.sms.forwarder.databinding.FragmentTasksConditionToAddressBinding
import com.idormy.sms.forwarder.entity.task.LocationSetting import com.idormy.sms.forwarder.entity.task.LocationSetting
import com.idormy.sms.forwarder.service.LocationService
import com.idormy.sms.forwarder.utils.HttpServerUtils
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_BACK_DESCRIPTION_CONDITION import com.idormy.sms.forwarder.utils.KEY_BACK_DESCRIPTION_CONDITION
import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION import com.idormy.sms.forwarder.utils.KEY_EVENT_DATA_CONDITION
import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS
import com.idormy.sms.forwarder.utils.XToastUtils import com.idormy.sms.forwarder.utils.XToastUtils
import com.jeremyliao.liveeventbus.LiveEventBus import com.jeremyliao.liveeventbus.LiveEventBus
@ -24,6 +28,8 @@ import com.xuexiang.xrouter.annotation.AutoWired
import com.xuexiang.xrouter.launcher.XRouter import com.xuexiang.xrouter.launcher.XRouter
import com.xuexiang.xui.utils.CountDownButtonHelper import com.xuexiang.xui.utils.CountDownButtonHelper
import com.xuexiang.xui.widget.actionbar.TitleBar import com.xuexiang.xui.widget.actionbar.TitleBar
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
@Page(name = "ToAddress") @Page(name = "ToAddress")
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
@ -98,6 +104,7 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
binding!!.btnTest.setOnClickListener(this) binding!!.btnTest.setOnClickListener(this)
binding!!.btnDel.setOnClickListener(this) binding!!.btnDel.setOnClickListener(this)
binding!!.btnSave.setOnClickListener(this) binding!!.btnSave.setOnClickListener(this)
binding!!.btnCurrentCoordinates.setOnClickListener(this)
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) { LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) {
mCountDownHelper?.finish() mCountDownHelper?.finish()
@ -113,6 +120,34 @@ class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(
override fun onClick(v: View) { override fun onClick(v: View) {
try { try {
when (v.id) { when (v.id) {
R.id.btn_current_coordinates -> {
if (!App.LocationClient.isStarted()) {
MaterialDialog.Builder(requireContext())
.iconRes(R.drawable.auto_task_icon_location)
.title(R.string.enable_location)
.content(R.string.enable_location_dialog)
.cancelable(false)
.positiveText(R.string.lab_yes)
.negativeText(R.string.lab_no).onPositive { _: MaterialDialog?, _: DialogAction? ->
SettingUtils.enableLocation = true
val serviceIntent = Intent(requireContext(), LocationService::class.java)
serviceIntent.action = "START"
requireContext().startService(serviceIntent)
}.show()
return
}
val location = HttpServerUtils.apiLocationCache
if (location.latitude == 0.0 || location.longitude == 0.0) {
XToastUtils.error(getString(R.string.location_failed), 30000)
return
}
binding!!.etLatitude.setText(location.latitude.toString())
binding!!.etLongitude.setText(location.longitude.toString())
XToastUtils.success(String.format(getString(R.string.current_address), location.address), 30000)
}
R.id.btn_test -> { R.id.btn_test -> {
mCountDownHelper?.start() mCountDownHelper?.start()
Thread { Thread {

@ -6,10 +6,19 @@ import android.content.Intent
import android.location.Location import android.location.Location
import android.os.IBinder import android.os.IBinder
import android.util.Log import android.util.Log
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.workDataOf
import com.google.gson.Gson
import com.idormy.sms.forwarder.App import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.entity.LocationInfo import com.idormy.sms.forwarder.entity.LocationInfo
import com.idormy.sms.forwarder.utils.HttpServerUtils import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.SettingUtils import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS
import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS
import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.task.TaskUtils
import com.idormy.sms.forwarder.workers.LocationWorker
import com.king.location.LocationErrorCode import com.king.location.LocationErrorCode
import com.king.location.OnExceptionListener import com.king.location.OnExceptionListener
import com.king.location.OnLocationListener import com.king.location.OnLocationListener
@ -97,20 +106,44 @@ class LocationService : Service(), Server.ServerListener {
//位置信息 //位置信息
Log.d(TAG, "onLocationChanged(location = ${location})") Log.d(TAG, "onLocationChanged(location = ${location})")
val locationInfo = LocationInfo( val locationInfoNew = LocationInfo(
location.longitude, location.latitude, "", App.DateFormat.format(Date(location.time)), location.provider.toString() location.longitude, location.latitude, "", App.DateFormat.format(Date(location.time)), location.provider.toString()
) )
//根据坐标经纬度获取位置地址信息WGS-84坐标系 //根据坐标经纬度获取位置地址信息WGS-84坐标系
val list = App.Geocoder.getFromLocation(location.latitude, location.longitude, 1) val list = App.Geocoder.getFromLocation(location.latitude, location.longitude, 1)
if (list?.isNotEmpty() == true) { if (list?.isNotEmpty() == true) {
locationInfo.address = list[0].getAddressLine(0) locationInfoNew.address = list[0].getAddressLine(0)
} }
Log.d(TAG, "locationInfo = $locationInfo") Log.d(TAG, "locationInfoNew = $locationInfoNew")
HttpServerUtils.apiLocationCache = locationInfo HttpServerUtils.apiLocationCache = locationInfoNew
//TODO: 触发自动任务 //TODO: 触发自动任务
val locationInfoOld = TaskUtils.lastLocationInfo
TaskUtils.lastLocationInfo = locationInfoNew
if (locationInfoOld.longitude != locationInfoNew.longitude || locationInfoOld.latitude != locationInfoNew.latitude || locationInfoOld.address != locationInfoNew.address) {
Log.d(TAG, "locationInfoOld = $locationInfoOld")
val locationInfoJsonOld = Gson().toJson(locationInfoOld)
val locationInfoJsonNew = Gson().toJson(locationInfoNew)
val toAddressRequest = OneTimeWorkRequestBuilder<LocationWorker>().setInputData(
workDataOf(
TaskWorker.conditionType to TASK_CONDITION_TO_ADDRESS,
"locationInfoJsonOld" to locationInfoJsonOld,
"locationInfoJsonNew" to locationInfoJsonNew,
)
).build()
WorkManager.getInstance(applicationContext).enqueue(toAddressRequest)
val leaveAddressRequest = OneTimeWorkRequestBuilder<LocationWorker>().setInputData(
workDataOf(
TaskWorker.conditionType to TASK_CONDITION_LEAVE_ADDRESS,
"locationInfoJsonOld" to locationInfoJsonNew,
"locationInfoJsonNew" to locationInfoJsonOld,
)
).build()
WorkManager.getInstance(applicationContext).enqueue(leaveAddressRequest)
}
} }
override fun onProviderEnabled(provider: String) { override fun onProviderEnabled(provider: String) {

@ -2,6 +2,7 @@ package com.idormy.sms.forwarder.utils.task
import android.os.BatteryManager import android.os.BatteryManager
import com.idormy.sms.forwarder.R import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.entity.LocationInfo
import com.idormy.sms.forwarder.utils.SP_BATTERY_INFO import com.idormy.sms.forwarder.utils.SP_BATTERY_INFO
import com.idormy.sms.forwarder.utils.SP_BATTERY_LEVEL import com.idormy.sms.forwarder.utils.SP_BATTERY_LEVEL
import com.idormy.sms.forwarder.utils.SP_BATTERY_PCT import com.idormy.sms.forwarder.utils.SP_BATTERY_PCT
@ -104,5 +105,9 @@ class TaskUtils private constructor() {
//SIM卡状态0-未知状态1-卡被移除5-卡已准备就绪 //SIM卡状态0-未知状态1-卡被移除5-卡已准备就绪
var simState: Int by SharedPreference(SP_SIM_STATE, 0) var simState: Int by SharedPreference(SP_SIM_STATE, 0)
//上次定位信息
var lastLocationInfo: LocationInfo by SharedPreference("lastLocationInfo", LocationInfo())
} }
} }

@ -10,14 +10,13 @@ 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
import com.idormy.sms.forwarder.database.AppDatabase import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.entity.LocationInfo
import com.idormy.sms.forwarder.entity.MsgInfo import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.task.BatterySetting import com.idormy.sms.forwarder.entity.task.LocationSetting
import com.idormy.sms.forwarder.entity.task.ChargeSetting
import com.idormy.sms.forwarder.entity.task.TaskSetting import com.idormy.sms.forwarder.entity.task.TaskSetting
import com.idormy.sms.forwarder.utils.TASK_CONDITION_BATTERY import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CHARGE import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS
import com.idormy.sms.forwarder.utils.TaskWorker import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.task.TaskUtils
import java.util.Date import java.util.Date
@Suppress("PrivatePropertyName", "DEPRECATION") @Suppress("PrivatePropertyName", "DEPRECATION")
@ -27,18 +26,25 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
when (val conditionType = inputData.getInt(TaskWorker.conditionType, -1)) { Log.d(TAG, "doWork")
val locationInfoJsonOld = inputData.getString("locationInfoJsonOld")
val locationInfoJsonNew = inputData.getString("locationInfoJsonNew")
if (locationInfoJsonOld == null || locationInfoJsonNew == null) {
Log.d(TAG, "locationInfoOld or locationInfoNew is null")
return Result.failure()
}
TASK_CONDITION_BATTERY -> { val locationInfoOld = Gson().fromJson(locationInfoJsonOld, LocationInfo::class.java)
val status = inputData.getInt("status", -1) val locationInfoNew = Gson().fromJson(locationInfoJsonNew, LocationInfo::class.java)
val levelNew = inputData.getInt("level_new", -1) if (locationInfoOld == null || locationInfoNew == null) {
val levelOld = inputData.getInt("level_old", -1) Log.d(TAG, "locationInfoOld or locationInfoNew is null")
Log.d(TAG, "levelNew: $levelNew, levelOld: $levelOld") return Result.failure()
if (levelNew == -1 || levelOld == -1) { }
Log.d(TAG, "levelNew or levelOld is -1")
return Result.failure()
}
when (val conditionType = inputData.getInt(TaskWorker.conditionType, -1)) {
//到达地点
TASK_CONDITION_TO_ADDRESS -> {
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
@ -55,27 +61,18 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
continue continue
} }
val batterySetting = Gson().fromJson(firstCondition.setting, BatterySetting::class.java) val locationSetting = Gson().fromJson(firstCondition.setting, LocationSetting::class.java)
if (batterySetting == null) { if (locationSetting == null) {
Log.d(TAG, "任务${task.id}batterySetting is null") Log.d(TAG, "任务${task.id}locationSetting is null")
continue
}
val msg = batterySetting.getMsg(status, levelNew, levelOld, TaskUtils.batteryInfo)
if (msg.isEmpty()) {
Log.d(TAG, "任务${task.id}msg is empty, batterySetting = $batterySetting, status = $status, levelNew = $levelNew, levelOld = $levelOld")
continue continue
} }
//TODO判断其他条件是否满足 //TODO判断条件是否满足
//TODO: 组装消息体 && 执行具体任务 //TODO: 组装消息体 && 执行具体任务
val msg = locationInfoNew.toString()
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.name) val msgInfo = MsgInfo("task", task.name, msg, Date(), task.name)
val actionData = Data.Builder() val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
.putLong(TaskWorker.taskId, task.id)
.putString(TaskWorker.taskActions, task.actions)
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
.build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build() val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest) WorkManager.getInstance().enqueue(actionRequest)
} }
@ -83,17 +80,8 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
return Result.success() return Result.success()
} }
TASK_CONDITION_CHARGE -> { //离开地点
val statusNew = inputData.getInt("status_new", -1) TASK_CONDITION_LEAVE_ADDRESS -> {
val statusOld = inputData.getInt("status_old", -1)
val pluggedNew = inputData.getInt("plugged_new", -1)
val pluggedOld = inputData.getInt("plugged_old", -1)
Log.d(TAG, "statusNew: $statusNew, statusOld: $statusOld, pluggedNew: $pluggedNew, pluggedOld: $pluggedOld")
if (statusNew == -1 || statusOld == -1 || pluggedNew == -1 || pluggedOld == -1) {
Log.d(TAG, "statusNew or statusOld or pluggedNew or pluggedOld is -1")
return Result.failure()
}
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType) val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType)
for (task in taskList) { for (task in taskList) {
Log.d(TAG, "task = $task") Log.d(TAG, "task = $task")
@ -110,27 +98,18 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
continue continue
} }
val chargeSetting = Gson().fromJson(firstCondition.setting, ChargeSetting::class.java) val locationSetting = Gson().fromJson(firstCondition.setting, LocationSetting::class.java)
if (chargeSetting == null) { if (locationSetting == null) {
Log.d(TAG, "任务${task.id}chargeSetting is null") Log.d(TAG, "任务${task.id}locationSetting is null")
continue
}
val msg = chargeSetting.getMsg(statusNew, statusOld, pluggedNew, pluggedOld, TaskUtils.batteryInfo)
if (msg.isEmpty()) {
Log.d(TAG, "任务${task.id}msg is empty, chargeSetting = $chargeSetting, statusNew = $statusNew, statusOld = $statusOld, pluggedNew = $pluggedNew, pluggedOld = $pluggedOld")
continue continue
} }
//TODO判断其他条件是否满足 //TODO判断条件是否满足
//TODO: 组装消息体 && 执行具体任务 //TODO: 组装消息体 && 执行具体任务
val msg = locationInfoNew.toString()
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.description) val msgInfo = MsgInfo("task", task.name, msg, Date(), task.description)
val actionData = Data.Builder() val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
.putLong(TaskWorker.taskId, task.id)
.putString(TaskWorker.taskActions, task.actions)
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
.build()
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build() val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
WorkManager.getInstance().enqueue(actionRequest) WorkManager.getInstance().enqueue(actionRequest)
} }

@ -44,11 +44,13 @@
android:layout_weight="1" android:layout_weight="1"
android:orientation="horizontal" /> android:orientation="horizontal" />
<TextView <com.xuexiang.xui.widget.button.switchbutton.SwitchButton
android:id="@+id/tv_time" android:id="@+id/sb_enable_task"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" /> android:paddingTop="@dimen/config_padding_5dp"
android:paddingBottom="@dimen/config_padding_5dp"
tools:ignore="TouchTargetSizeCheck" />
</LinearLayout> </LinearLayout>
@ -56,7 +58,8 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center_vertical" android:gravity="center_vertical"
android:orientation="horizontal"> android:orientation="horizontal"
tools:ignore="DisableBaselineAlignment">
<LinearLayout <LinearLayout
android:id="@+id/layout_image" android:id="@+id/layout_image"
@ -113,37 +116,59 @@
</LinearLayout> </LinearLayout>
<ImageView <LinearLayout
android:id="@+id/iv_copy" android:layout_width="wrap_content"
android:layout_width="@dimen/card_view_image_size" android:layout_height="wrap_content"
android:layout_height="@dimen/card_view_image_size" android:gravity="center_horizontal"
android:padding="@dimen/card_view_image_padding" android:orientation="vertical">
android:scaleType="fitCenter"
android:src="@drawable/ic_copy"
app:tint="@color/colorStart"
tools:ignore="ContentDescription,ImageContrastCheck" />
<ImageView <LinearLayout
android:id="@+id/iv_edit" android:layout_width="wrap_content"
android:layout_width="@dimen/card_view_image_size" android:layout_height="wrap_content"
android:layout_height="@dimen/card_view_image_size" android:orientation="horizontal">
android:padding="@dimen/card_view_image_padding"
android:scaleType="fitCenter" <ImageView
android:src="@drawable/ic_edit" android:id="@+id/iv_copy"
app:tint="@color/toast_info_color" android:layout_width="28dp"
tools:ignore="ContentDescription,PrivateResource,ImageContrastCheck" /> android:layout_height="28dp"
android:padding="@dimen/card_view_image_padding"
android:scaleType="fitCenter"
android:src="@drawable/ic_copy"
app:tint="@color/colorStart"
tools:ignore="ContentDescription,ImageContrastCheck" />
<ImageView
android:id="@+id/iv_edit"
android:layout_width="28dp"
android:layout_height="28dp"
android:padding="@dimen/card_view_image_padding"
android:scaleType="fitCenter"
android:src="@drawable/ic_edit"
app:tint="@color/toast_info_color"
tools:ignore="ContentDescription,PrivateResource,ImageContrastCheck" />
<ImageView
android:id="@+id/iv_delete"
android:layout_width="28dp"
android:layout_height="28dp"
android:padding="@dimen/card_view_image_padding"
android:scaleType="fitCenter"
android:src="@drawable/ic_delete"
app:tint="@color/toast_error_color"
tools:ignore="ContentDescription,PrivateResource" />
</LinearLayout>
<ImageView <TextView
android:id="@+id/iv_delete" android:id="@+id/tv_time"
android:layout_width="@dimen/card_view_image_size" android:layout_width="wrap_content"
android:layout_height="@dimen/card_view_image_size" android:layout_height="wrap_content"
android:padding="@dimen/card_view_image_padding" android:layout_marginStart="5dp" />
android:scaleType="fitCenter"
android:src="@drawable/ic_delete" </LinearLayout>
app:tint="@color/toast_error_color"
tools:ignore="ContentDescription,PrivateResource" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>
</com.xuexiang.xui.widget.layout.XUIFrameLayout> </com.xuexiang.xui.widget.layout.XUIFrameLayout>

@ -524,7 +524,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="5dp" android:layout_marginStart="5dp"
android:text="@string/seconds" android:text="@string/meter"
android:textSize="12sp" android:textSize="12sp"
android:textStyle="bold" /> android:textStyle="bold" />

@ -1087,6 +1087,7 @@
<string name="ipv6">IPv6</string> <string name="ipv6">IPv6</string>
<string name="enable_location">Enable Location Function</string> <string name="enable_location">Enable Location Function</string>
<string name="enable_location_dialog">Enable location services to use this feature. Yes or No?</string>
<string name="enable_location_tips">Used for locating the phone, {{LOCATION}} tag.</string> <string name="enable_location_tips">Used for locating the phone, {{LOCATION}} tag.</string>
<string name="accuracy">Accuracy</string> <string name="accuracy">Accuracy</string>
<string name="accuracy_fine">Fine</string> <string name="accuracy_fine">Fine</string>
@ -1096,7 +1097,7 @@
<string name="power_requirement_low">Low</string> <string name="power_requirement_low">Low</string>
<string name="power_requirement_medium">Medium</string> <string name="power_requirement_medium">Medium</string>
<string name="power_requirement_high">High</string> <string name="power_requirement_high">High</string>
<string name="min_interval">Min Interval For Update</string> <string name="min_interval">To Update: Min Interval</string>
<string name="min_distance">Min Distance</string> <string name="min_distance">Min Distance</string>
<string name="meter">m</string> <string name="meter">m</string>
<string name="uid">UID</string> <string name="uid">UID</string>
@ -1241,4 +1242,6 @@
<string name="condition_already_exists">This type of condition already exists.</string> <string name="condition_already_exists">This type of condition already exists.</string>
<string name="action_already_exists">This type of action already exists.</string> <string name="action_already_exists">This type of action already exists.</string>
<string name="only_one_location_condition">Only one condition, either "To Address" or "Leave Address" can be added.</string> <string name="only_one_location_condition">Only one condition, either "To Address" or "Leave Address" can be added.</string>
<string name="current_address">Current Address: %s</string>
<string name="location_failed">Location failed. Please try again later.</string>
</resources> </resources>

@ -1088,6 +1088,7 @@
<string name="ipv6">IPv6</string> <string name="ipv6">IPv6</string>
<string name="enable_location">启用GPS定位功能</string> <string name="enable_location">启用GPS定位功能</string>
<string name="enable_location_dialog">必须开启定位服务,才能使用获取!\n是否立即启用</string>
<string name="enable_location_tips">用于支持 查找手机、{{定位信息}}标签 功能</string> <string name="enable_location_tips">用于支持 查找手机、{{定位信息}}标签 功能</string>
<string name="accuracy">位置精度</string> <string name="accuracy">位置精度</string>
<string name="accuracy_fine">精确位置</string> <string name="accuracy_fine">精确位置</string>
@ -1097,7 +1098,7 @@
<string name="power_requirement_low"></string> <string name="power_requirement_low"></string>
<string name="power_requirement_medium"></string> <string name="power_requirement_medium"></string>
<string name="power_requirement_high"></string> <string name="power_requirement_high"></string>
<string name="min_interval">位置更新最小间隔</string> <string name="min_interval">位置更新最小间隔</string>
<string name="min_distance">最小距离</string> <string name="min_distance">最小距离</string>
<string name="meter"></string> <string name="meter"></string>
<string name="uid">UID</string> <string name="uid">UID</string>
@ -1235,11 +1236,13 @@
<string name="keyword_leave_address_2">则表示离开</string> <string name="keyword_leave_address_2">则表示离开</string>
<string name="calc_type_distance_error">经纬度或距离都不能为空</string> <string name="calc_type_distance_error">经纬度或距离都不能为空</string>
<string name="calc_type_address_error">地址关键字不能为空</string> <string name="calc_type_address_error">地址关键字不能为空</string>
<string name="to_address_distance_description">进入以经度%s维度%s 为中心,%s 米半径的区域</string> <string name="to_address_distance_description">进入以经度:%s,维度:%s为中心,%s米半径的区域</string>
<string name="to_address_keyword_description">进入GPS地址包含 %s 关键字区域</string> <string name="to_address_keyword_description">进入GPS地址包含[%s]关键字区域</string>
<string name="leave_address_distance_description">离开以经度%s维度%s 为中心,%s 米半径的区域</string> <string name="leave_address_distance_description">离开以经度:%s,维度:%s为中心,%s米半径的区域</string>
<string name="leave_address_keyword_description">离开GPS地址包含 %s 关键字区域</string> <string name="leave_address_keyword_description">离开GPS地址包含[%s]关键字区域</string>
<string name="condition_already_exists">已经添加过该类型条件</string> <string name="condition_already_exists">已经添加过该类型条件</string>
<string name="action_already_exists">已经添加过该类型动作</string> <string name="action_already_exists">已经添加过该类型动作</string>
<string name="only_one_location_condition">只能添加一个 进入地点 或 离开地址 类型条件</string> <string name="only_one_location_condition">只能添加一个 进入地点 或 离开地址 类型条件</string>
<string name="current_address">当前地址:%s</string>
<string name="location_failed">定位失败,请稍后重试</string>
</resources> </resources>

Loading…
Cancel
Save