mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-03 09:27:41 +08:00
新增:自动任务·快捷指令 (开发中)
This commit is contained in:
parent
1302bf9e20
commit
41c0e1923a
@ -1,8 +1,6 @@
|
|||||||
package com.idormy.sms.forwarder.entity.task
|
package com.idormy.sms.forwarder.entity.task
|
||||||
|
|
||||||
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.task.ConditionUtils.Companion.calculateDistance
|
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
data class LocationSetting(
|
data class LocationSetting(
|
||||||
@ -23,24 +21,4 @@ data class LocationSetting(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//判断是否满足条件
|
|
||||||
fun isMatchCondition(locationOld: LocationInfo, locationNew: LocationInfo): Boolean {
|
|
||||||
if (calcType == "distance") {
|
|
||||||
val distanceOld = calculateDistance(locationOld.latitude, locationOld.longitude, latitude, longitude)
|
|
||||||
val distanceNew = calculateDistance(locationNew.latitude, locationNew.longitude, latitude, longitude)
|
|
||||||
if (type == "to" && distanceOld > distance && distanceNew <= distance) {
|
|
||||||
return true
|
|
||||||
} else if (type == "leave" && distanceOld <= distance && distanceNew > distance) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else if (calcType == "address") {
|
|
||||||
if (type == "to" && !locationOld.address.contains(address) && locationNew.address.contains(address)) {
|
|
||||||
return true
|
|
||||||
} else if (type == "leave" && locationOld.address.contains(address) && !locationNew.address.contains(address)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
switchDirectlyToTask(binding!!.sbDirectlyToTask)
|
switchDirectlyToTask(binding!!.sbDirectlyToTask)
|
||||||
|
|
||||||
//启用 {{定位信息}} 标签
|
//启用 {{定位信息}} 标签
|
||||||
switchEnableLocation(binding!!.sbEnableLocation, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.xsbMinInterval, binding!!.xsbMinDistance)
|
switchEnableLocation(binding!!.sbEnableLocation, binding!!.layoutLocationSetting, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.xsbMinInterval, binding!!.xsbMinDistance)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -888,9 +888,10 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
}
|
}
|
||||||
|
|
||||||
//启用定位功能
|
//启用定位功能
|
||||||
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocation: SwitchButton, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, xsbMinInterval: XSeekBar, xsbMinDistance: XSeekBar) {
|
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocation: SwitchButton, layoutLocationSetting: LinearLayout, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, xsbMinInterval: XSeekBar, xsbMinDistance: XSeekBar) {
|
||||||
//是否启用定位功能
|
//是否启用定位功能
|
||||||
switchEnableLocation.isChecked = SettingUtils.enableLocation
|
switchEnableLocation.isChecked = SettingUtils.enableLocation
|
||||||
|
layoutLocationSetting.visibility = if (SettingUtils.enableLocation) View.VISIBLE else View.GONE
|
||||||
switchEnableLocation.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
switchEnableLocation.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||||
SettingUtils.enableLocation = isChecked
|
SettingUtils.enableLocation = isChecked
|
||||||
if (isChecked) {
|
if (isChecked) {
|
||||||
@ -915,6 +916,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
|||||||
} else {
|
} else {
|
||||||
restartLocationService()
|
restartLocationService()
|
||||||
}
|
}
|
||||||
|
layoutLocationSetting.visibility = if (isChecked) View.VISIBLE else View.GONE
|
||||||
}
|
}
|
||||||
//设置位置精度:高精度(默认)
|
//设置位置精度:高精度(默认)
|
||||||
rgAccuracy.check(
|
rgAccuracy.check(
|
||||||
|
@ -9,6 +9,7 @@ import androidx.work.WorkManager
|
|||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LOCK_SCREEN
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LOCK_SCREEN
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
||||||
import com.idormy.sms.forwarder.workers.LockScreenWorker
|
import com.idormy.sms.forwarder.workers.LockScreenWorker
|
||||||
|
|
||||||
@Suppress("PropertyName")
|
@Suppress("PropertyName")
|
||||||
@ -21,6 +22,7 @@ class LockScreenReceiver : BroadcastReceiver() {
|
|||||||
if (context == null || (intent?.action != Intent.ACTION_SCREEN_OFF && intent?.action != Intent.ACTION_SCREEN_ON)) return
|
if (context == null || (intent?.action != Intent.ACTION_SCREEN_OFF && intent?.action != Intent.ACTION_SCREEN_ON)) return
|
||||||
|
|
||||||
Log.d(TAG, "onReceive: ${intent.action}")
|
Log.d(TAG, "onReceive: ${intent.action}")
|
||||||
|
TaskUtils.lockScreenAction = intent.action.toString()
|
||||||
val request = OneTimeWorkRequestBuilder<LockScreenWorker>().setInputData(
|
val request = OneTimeWorkRequestBuilder<LockScreenWorker>().setInputData(
|
||||||
workDataOf(
|
workDataOf(
|
||||||
TaskWorker.conditionType to TASK_CONDITION_LOCK_SCREEN,
|
TaskWorker.conditionType to TASK_CONDITION_LOCK_SCREEN,
|
||||||
|
@ -9,6 +9,7 @@ import androidx.work.OneTimeWorkRequestBuilder
|
|||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.workDataOf
|
import androidx.work.workDataOf
|
||||||
import com.idormy.sms.forwarder.R
|
import com.idormy.sms.forwarder.R
|
||||||
|
import com.idormy.sms.forwarder.utils.DELAY_TIME_AFTER_SIM_READY
|
||||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_SIM
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_SIM
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
@ -50,7 +51,7 @@ class SimStateReceiver : BroadcastReceiver() {
|
|||||||
TelephonyManager.SIM_STATE_READY -> {
|
TelephonyManager.SIM_STATE_READY -> {
|
||||||
Log.d(TAG, "SIM 卡已准备就绪")
|
Log.d(TAG, "SIM 卡已准备就绪")
|
||||||
TaskUtils.simState = simStateNew
|
TaskUtils.simState = simStateNew
|
||||||
duration = 5000L
|
duration = DELAY_TIME_AFTER_SIM_READY
|
||||||
getString(R.string.sim_state_ready)
|
getString(R.string.sim_state_ready)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ class LocationService : Service(), Server.ServerListener {
|
|||||||
try {
|
try {
|
||||||
//清空缓存
|
//清空缓存
|
||||||
HttpServerUtils.apiLocationCache = LocationInfo()
|
HttpServerUtils.apiLocationCache = LocationInfo()
|
||||||
TaskUtils.lastLocationInfo = LocationInfo()
|
TaskUtils.locationInfoOld = LocationInfo()
|
||||||
|
|
||||||
if (SettingUtils.enableLocation && PermissionUtils.isGranted(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
|
if (SettingUtils.enableLocation && PermissionUtils.isGranted(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||||
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
|
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
|
||||||
@ -121,18 +121,20 @@ class LocationService : Service(), Server.ServerListener {
|
|||||||
|
|
||||||
Log.d(TAG, "locationInfoNew = $locationInfoNew")
|
Log.d(TAG, "locationInfoNew = $locationInfoNew")
|
||||||
HttpServerUtils.apiLocationCache = locationInfoNew
|
HttpServerUtils.apiLocationCache = locationInfoNew
|
||||||
|
TaskUtils.locationInfoNew = locationInfoNew
|
||||||
|
|
||||||
//TODO: 触发自动任务
|
//TODO: 触发自动任务
|
||||||
val locationInfoOld = TaskUtils.lastLocationInfo
|
val locationInfoOld = TaskUtils.locationInfoOld
|
||||||
if (locationInfoOld.longitude != locationInfoNew.longitude || locationInfoOld.latitude != locationInfoNew.latitude || locationInfoOld.address != locationInfoNew.address) {
|
if (locationInfoOld.longitude != locationInfoNew.longitude || locationInfoOld.latitude != locationInfoNew.latitude || locationInfoOld.address != locationInfoNew.address) {
|
||||||
Log.d(TAG, "locationInfoOld = $locationInfoOld")
|
Log.d(TAG, "locationInfoOld = $locationInfoOld")
|
||||||
TaskUtils.lastLocationInfo = locationInfoNew
|
|
||||||
|
|
||||||
val gson = Gson()
|
val gson = Gson()
|
||||||
val locationJsonOld = gson.toJson(locationInfoOld)
|
val locationJsonOld = gson.toJson(locationInfoOld)
|
||||||
val locationJsonNew = gson.toJson(locationInfoNew)
|
val locationJsonNew = gson.toJson(locationInfoNew)
|
||||||
enqueueLocationWorkerRequest(TASK_CONDITION_TO_ADDRESS, locationJsonOld, locationJsonNew)
|
enqueueLocationWorkerRequest(TASK_CONDITION_TO_ADDRESS, locationJsonOld, locationJsonNew)
|
||||||
enqueueLocationWorkerRequest(TASK_CONDITION_LEAVE_ADDRESS, locationJsonOld, locationJsonNew)
|
enqueueLocationWorkerRequest(TASK_CONDITION_LEAVE_ADDRESS, locationJsonOld, locationJsonNew)
|
||||||
|
|
||||||
|
TaskUtils.locationInfoOld = locationInfoNew
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +180,7 @@ class LocationService : Service(), Server.ServerListener {
|
|||||||
private fun stopService() {
|
private fun stopService() {
|
||||||
//清空缓存
|
//清空缓存
|
||||||
HttpServerUtils.apiLocationCache = LocationInfo()
|
HttpServerUtils.apiLocationCache = LocationInfo()
|
||||||
TaskUtils.lastLocationInfo = LocationInfo()
|
TaskUtils.locationInfoOld = LocationInfo()
|
||||||
|
|
||||||
isRunning = try {
|
isRunning = try {
|
||||||
//如果已经开始定位,则先停止定位
|
//如果已经开始定位,则先停止定位
|
||||||
|
@ -617,3 +617,9 @@ const val SP_WIFI_SSID = "wifi_ssid"
|
|||||||
const val SP_IPV4 = "ipv4"
|
const val SP_IPV4 = "ipv4"
|
||||||
const val SP_IPV6 = "ipv6"
|
const val SP_IPV6 = "ipv6"
|
||||||
const val SP_SIM_STATE = "sim_state"
|
const val SP_SIM_STATE = "sim_state"
|
||||||
|
const val SP_LOCATION_INFO_OLD = "location_info_old"
|
||||||
|
const val SP_LOCATION_INFO_NEW = "location_info_new"
|
||||||
|
const val SP_LOCK_SCREEN_ACTION = "lock_screen_action"
|
||||||
|
|
||||||
|
//SIM卡已准备就绪时,延迟5秒(给够搜索信号时间)才执行任务
|
||||||
|
const val DELAY_TIME_AFTER_SIM_READY = 5000L
|
@ -1,5 +1,27 @@
|
|||||||
package com.idormy.sms.forwarder.utils.task
|
package com.idormy.sms.forwarder.utils.task
|
||||||
|
|
||||||
|
import android.os.BatteryManager
|
||||||
|
import android.util.Log
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import com.idormy.sms.forwarder.entity.task.BatterySetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.ChargeSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.CronSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.LocationSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.LockScreenSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.NetworkSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.SimSetting
|
||||||
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
|
import com.idormy.sms.forwarder.utils.DELAY_TIME_AFTER_SIM_READY
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_BATTERY
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CHARGE
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CRON
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LOCK_SCREEN
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_NETWORK
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_SIM
|
||||||
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS
|
||||||
|
import gatewayapps.crondroid.CronExpression
|
||||||
|
import java.util.Date
|
||||||
import kotlin.math.atan2
|
import kotlin.math.atan2
|
||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
@ -12,9 +34,165 @@ class ConditionUtils private constructor() {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
|
private val TAG: String = ConditionUtils::class.java.simpleName
|
||||||
|
|
||||||
|
//遍历条件列表,判断是否满足条件,默认不校验第一个条件(第一个条件是触发条件)
|
||||||
|
fun checkCondition(taskId: Long, conditionList: MutableList<TaskSetting>, startIndex: Int = 1): Boolean {
|
||||||
|
if (startIndex >= conditionList.size) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:no condition need to check")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//注意:触发条件 = SIM卡已准备就绪时,延迟5秒(给够搜索信号时间)才执行任务
|
||||||
|
val firstCondition = conditionList.firstOrNull()
|
||||||
|
val needDelay = firstCondition?.type == TASK_CONDITION_SIM && TaskUtils.simState == 5
|
||||||
|
|
||||||
|
for (i in startIndex until conditionList.size) {
|
||||||
|
val condition = conditionList[i]
|
||||||
|
when (condition.type) {
|
||||||
|
TASK_CONDITION_CRON -> {
|
||||||
|
val cronSetting = Gson().fromJson(condition.setting, CronSetting::class.java)
|
||||||
|
if (cronSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:cronSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentDate = if (needDelay) Date((Date().time / 1000) * 1000 - DELAY_TIME_AFTER_SIM_READY) else Date()
|
||||||
|
currentDate.time = currentDate.time / 1000 * 1000
|
||||||
|
val previousSecond = Date(currentDate.time - 1000)
|
||||||
|
val cronExpression = CronExpression(cronSetting.expression)
|
||||||
|
val nextValidTime = cronExpression.getNextValidTimeAfter(previousSecond)
|
||||||
|
nextValidTime.time = nextValidTime.time / 1000 * 1000
|
||||||
|
if (currentDate.time != nextValidTime.time) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:cron condition is not satisfied")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_TO_ADDRESS, TASK_CONDITION_LEAVE_ADDRESS -> {
|
||||||
|
val locationSetting = Gson().fromJson(condition.setting, LocationSetting::class.java)
|
||||||
|
if (locationSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:locationSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val locationOld = TaskUtils.locationInfoOld
|
||||||
|
val locationNew = TaskUtils.locationInfoNew
|
||||||
|
if (locationSetting.calcType == "distance") {
|
||||||
|
val distanceOld = calculateDistance(locationOld.latitude, locationOld.longitude, locationSetting.latitude, locationSetting.longitude)
|
||||||
|
val distanceNew = calculateDistance(locationNew.latitude, locationNew.longitude, locationSetting.latitude, locationSetting.longitude)
|
||||||
|
if (locationSetting.type == "to" && distanceOld > locationSetting.distance && distanceNew <= locationSetting.distance) {
|
||||||
|
continue
|
||||||
|
} else if (locationSetting.type == "leave" && distanceOld <= locationSetting.distance && distanceNew > locationSetting.distance) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if (locationSetting.calcType == "address") {
|
||||||
|
if (locationSetting.type == "to" && !locationOld.address.contains(locationSetting.address) && locationNew.address.contains(locationSetting.address)) {
|
||||||
|
continue
|
||||||
|
} else if (locationSetting.type == "leave" && locationOld.address.contains(locationSetting.address) && !locationNew.address.contains(locationSetting.address)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_NETWORK -> {
|
||||||
|
val networkSetting = Gson().fromJson(condition.setting, NetworkSetting::class.java)
|
||||||
|
if (networkSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:networkSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TaskUtils.networkState != networkSetting.networkState) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:networkState is not match, networkSetting = $networkSetting")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//移动网络
|
||||||
|
if (networkSetting.networkState == 1 && networkSetting.dataSimSlot != 0 && TaskUtils.dataSimSlot != networkSetting.dataSimSlot) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:dataSimSlot is not match, networkSetting = $networkSetting")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
//WiFi
|
||||||
|
else if (networkSetting.networkState == 2 && networkSetting.wifiSsid.isNotEmpty() && TaskUtils.wifiSsid != networkSetting.wifiSsid) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:wifiSsid is not match, networkSetting = $networkSetting")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_SIM -> {
|
||||||
|
val simSetting = Gson().fromJson(condition.setting, SimSetting::class.java)
|
||||||
|
if (simSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:simSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (TaskUtils.simState != simSetting.simState) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:simState is not match, simSetting = $simSetting")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_BATTERY -> {
|
||||||
|
val batteryLevel = TaskUtils.batteryLevel
|
||||||
|
val batteryStatus = TaskUtils.batteryStatus
|
||||||
|
val batterySetting = Gson().fromJson(condition.setting, BatterySetting::class.java)
|
||||||
|
if (batterySetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:batterySetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
when (batteryStatus) {
|
||||||
|
BatteryManager.BATTERY_STATUS_CHARGING, BatteryManager.BATTERY_STATUS_FULL -> { //充电中
|
||||||
|
if (batterySetting.status != BatteryManager.BATTERY_STATUS_CHARGING) return false
|
||||||
|
if (batterySetting.keepReminding && batteryLevel >= batterySetting.levelMax) {
|
||||||
|
continue
|
||||||
|
} else if (!batterySetting.keepReminding && batteryLevel == batterySetting.levelMax) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BatteryManager.BATTERY_STATUS_DISCHARGING, BatteryManager.BATTERY_STATUS_NOT_CHARGING -> { //放电中
|
||||||
|
if (batterySetting.status != BatteryManager.BATTERY_STATUS_DISCHARGING) return false
|
||||||
|
if (batterySetting.keepReminding && batteryLevel <= batterySetting.levelMin) {
|
||||||
|
continue
|
||||||
|
} else if (!batterySetting.keepReminding && batteryLevel == batterySetting.levelMin) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_CHARGE -> {
|
||||||
|
val chargeSetting = Gson().fromJson(condition.setting, ChargeSetting::class.java)
|
||||||
|
if (chargeSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:chargeSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val batteryStatus = TaskUtils.batteryStatus
|
||||||
|
val batteryPlugged = TaskUtils.batteryPlugged
|
||||||
|
if (batteryStatus != chargeSetting.status || batteryPlugged != chargeSetting.plugged) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TASK_CONDITION_LOCK_SCREEN -> {
|
||||||
|
val lockScreenSetting = Gson().fromJson(condition.setting, LockScreenSetting::class.java)
|
||||||
|
if (lockScreenSetting == null) {
|
||||||
|
Log.d(TAG, "TASK-$taskId:lockScreenSetting is null")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (TaskUtils.lockScreenAction != lockScreenSetting.action) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
//计算两个经纬度之间的距离
|
//计算两个经纬度之间的距离
|
||||||
fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
|
fun calculateDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double {
|
||||||
val earthRadius = 6371000.0 // 地球平均半径,单位:米
|
val earthRadius = 6378137.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)
|
||||||
val a = sin(latDistance / 2) * sin(latDistance / 2) + cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) * sin(lonDistance / 2) * sin(lonDistance / 2)
|
val a = sin(latDistance / 2) * sin(latDistance / 2) + cos(Math.toRadians(lat1)) * cos(Math.toRadians(lat2)) * sin(lonDistance / 2) * sin(lonDistance / 2)
|
||||||
|
@ -15,7 +15,7 @@ class CronJobScheduler {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
private const val TAG: String = "CronJobScheduler"
|
private val TAG: String = CronJobScheduler::class.java.simpleName
|
||||||
|
|
||||||
fun scheduleTask(task: Task) {
|
fun scheduleTask(task: Task) {
|
||||||
val currentTimeMillis = System.currentTimeMillis()
|
val currentTimeMillis = System.currentTimeMillis()
|
||||||
|
@ -11,6 +11,9 @@ import com.idormy.sms.forwarder.utils.SP_BATTERY_STATUS
|
|||||||
import com.idormy.sms.forwarder.utils.SP_DATA_SIM_SLOT
|
import com.idormy.sms.forwarder.utils.SP_DATA_SIM_SLOT
|
||||||
import com.idormy.sms.forwarder.utils.SP_IPV4
|
import com.idormy.sms.forwarder.utils.SP_IPV4
|
||||||
import com.idormy.sms.forwarder.utils.SP_IPV6
|
import com.idormy.sms.forwarder.utils.SP_IPV6
|
||||||
|
import com.idormy.sms.forwarder.utils.SP_LOCATION_INFO_NEW
|
||||||
|
import com.idormy.sms.forwarder.utils.SP_LOCATION_INFO_OLD
|
||||||
|
import com.idormy.sms.forwarder.utils.SP_LOCK_SCREEN_ACTION
|
||||||
import com.idormy.sms.forwarder.utils.SP_NETWORK_STATE
|
import com.idormy.sms.forwarder.utils.SP_NETWORK_STATE
|
||||||
import com.idormy.sms.forwarder.utils.SP_SIM_STATE
|
import com.idormy.sms.forwarder.utils.SP_SIM_STATE
|
||||||
import com.idormy.sms.forwarder.utils.SP_WIFI_SSID
|
import com.idormy.sms.forwarder.utils.SP_WIFI_SSID
|
||||||
@ -107,7 +110,13 @@ class TaskUtils private constructor() {
|
|||||||
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())
|
var locationInfoOld: LocationInfo by SharedPreference(SP_LOCATION_INFO_OLD, LocationInfo())
|
||||||
|
|
||||||
|
//当前定位信息
|
||||||
|
var locationInfoNew: LocationInfo by SharedPreference(SP_LOCATION_INFO_NEW, LocationInfo())
|
||||||
|
|
||||||
|
//上次锁屏广播
|
||||||
|
var lockScreenAction: String by SharedPreference(SP_LOCK_SCREEN_ACTION, "")
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -17,6 +17,7 @@ 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_BATTERY
|
||||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CHARGE
|
import com.idormy.sms.forwarder.utils.TASK_CONDITION_CHARGE
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
@ -123,6 +124,10 @@ class BatteryWorker(context: Context, params: WorkerParameters) : CoroutineWorke
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO:判断其他条件是否满足
|
//TODO:判断其他条件是否满足
|
||||||
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: 组装消息体 && 执行具体任务
|
//TODO: 组装消息体 && 执行具体任务
|
||||||
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.description)
|
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.description)
|
||||||
|
@ -14,6 +14,7 @@ import com.idormy.sms.forwarder.entity.MsgInfo
|
|||||||
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.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
||||||
import gatewayapps.crondroid.CronExpression
|
import gatewayapps.crondroid.CronExpression
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -54,8 +55,8 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 判断其他条件是否满足
|
// TODO: 判断其他条件是否满足
|
||||||
if (false) {
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
Log.d(TAG, "TASK-${task.id}:其他条件不满足")
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
return Result.failure()
|
return Result.failure()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,11 +85,7 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
|
|||||||
|
|
||||||
//TODO: 组装消息体 && 执行具体任务
|
//TODO: 组装消息体 && 执行具体任务
|
||||||
val msgInfo = MsgInfo("task", task.name, task.description, Date(), task.name)
|
val msgInfo = MsgInfo("task", task.name, task.description, 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)
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import com.idormy.sms.forwarder.entity.task.TaskSetting
|
|||||||
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.TASK_CONDITION_TO_ADDRESS
|
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.ConditionUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.ConditionUtils.Companion.calculateDistance
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils.Companion.calculateDistance
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -95,6 +96,12 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:判断其他条件是否满足
|
||||||
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: 组装消息体 && 执行具体任务
|
//TODO: 组装消息体 && 执行具体任务
|
||||||
val msgInfo = MsgInfo("task", task.name, locationNew.toString(), Date(), description)
|
val msgInfo = MsgInfo("task", task.name, locationNew.toString(), Date(), description)
|
||||||
val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
|
val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
|
||||||
@ -152,6 +159,12 @@ class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWork
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO:判断其他条件是否满足
|
||||||
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: 组装消息体 && 执行具体任务
|
//TODO: 组装消息体 && 执行具体任务
|
||||||
val msgInfo = MsgInfo("task", task.name, locationNew.toString(), Date(), description)
|
val msgInfo = MsgInfo("task", task.name, locationNew.toString(), Date(), description)
|
||||||
val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
|
val actionData = Data.Builder().putLong(TaskWorker.taskId, task.id).putString(TaskWorker.taskActions, task.actions).putString(TaskWorker.msgInfo, Gson().toJson(msgInfo)).build()
|
||||||
|
@ -15,6 +15,7 @@ import com.idormy.sms.forwarder.entity.MsgInfo
|
|||||||
import com.idormy.sms.forwarder.entity.task.LockScreenSetting
|
import com.idormy.sms.forwarder.entity.task.LockScreenSetting
|
||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
@ -55,9 +56,11 @@ class LockScreenWorker(context: Context, params: WorkerParameters) : CoroutineWo
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val duration = if (action == Intent.ACTION_SCREEN_ON) lockScreenSetting.timeAfterScreenOn else lockScreenSetting.timeAfterScreenOff
|
|
||||||
|
|
||||||
//TODO:判断其他条件是否满足
|
//TODO:判断其他条件是否满足
|
||||||
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: 组装消息体 && 执行具体任务
|
//TODO: 组装消息体 && 执行具体任务
|
||||||
val msgInfo = MsgInfo("task", task.name, lockScreenSetting.description, Date(), task.description)
|
val msgInfo = MsgInfo("task", task.name, lockScreenSetting.description, Date(), task.description)
|
||||||
@ -66,6 +69,7 @@ class LockScreenWorker(context: Context, params: WorkerParameters) : CoroutineWo
|
|||||||
.putString(TaskWorker.taskActions, task.actions)
|
.putString(TaskWorker.taskActions, task.actions)
|
||||||
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
|
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
|
||||||
.build()
|
.build()
|
||||||
|
val duration = if (action == Intent.ACTION_SCREEN_ON) lockScreenSetting.timeAfterScreenOn else lockScreenSetting.timeAfterScreenOff
|
||||||
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>()
|
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>()
|
||||||
.setInitialDelay(duration.toLong(), TimeUnit.MINUTES)
|
.setInitialDelay(duration.toLong(), TimeUnit.MINUTES)
|
||||||
.setInputData(actionData).build()
|
.setInputData(actionData).build()
|
||||||
|
@ -16,6 +16,7 @@ import com.idormy.sms.forwarder.entity.task.NetworkSetting
|
|||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
import com.idormy.sms.forwarder.utils.PhoneUtils
|
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
||||||
import com.xuexiang.xutil.app.ServiceUtils
|
import com.xuexiang.xutil.app.ServiceUtils
|
||||||
import com.xuexiang.xutil.resource.ResUtils.getString
|
import com.xuexiang.xutil.resource.ResUtils.getString
|
||||||
@ -60,6 +61,10 @@ class NetworkWorker(context: Context, params: WorkerParameters) : CoroutineWorke
|
|||||||
}
|
}
|
||||||
|
|
||||||
//TODO:判断其他条件是否满足
|
//TODO:判断其他条件是否满足
|
||||||
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
var ipv4 = ""
|
var ipv4 = ""
|
||||||
var ipv6 = ""
|
var ipv6 = ""
|
||||||
|
@ -17,6 +17,7 @@ import com.idormy.sms.forwarder.entity.task.SimSetting
|
|||||||
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
import com.idormy.sms.forwarder.entity.task.TaskSetting
|
||||||
import com.idormy.sms.forwarder.utils.PhoneUtils
|
import com.idormy.sms.forwarder.utils.PhoneUtils
|
||||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||||
|
import com.idormy.sms.forwarder.utils.task.ConditionUtils
|
||||||
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
||||||
import com.xuexiang.xutil.resource.ResUtils
|
import com.xuexiang.xutil.resource.ResUtils
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
@ -56,11 +57,11 @@ class SimWorker(context: Context, params: WorkerParameters) : CoroutineWorker(co
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO:判断其他条件是否满足,注意:SIM卡已准备就绪,延迟5秒才进入这里(给够搜索信号时间)
|
//TODO:判断其他条件是否满足,注意:SIM卡已准备就绪时,延迟5秒(给够搜索信号时间)才执行任务
|
||||||
/*if (!TaskUtils.isConditionMatch(task, msg)) {
|
if (!ConditionUtils.checkCondition(task.id, conditionList)) {
|
||||||
Log.d(TAG, "TASK-${task.id}:condition is not match")
|
Log.d(TAG, "TASK-${task.id}:other condition is not satisfied")
|
||||||
continue
|
continue
|
||||||
}*/
|
}
|
||||||
|
|
||||||
val msg = StringBuilder()
|
val msg = StringBuilder()
|
||||||
msg.append(String.format(ResUtils.getString(R.string.sim_state), simStateStr)).append("\n")
|
msg.append(String.format(ResUtils.getString(R.string.sim_state), simStateStr)).append("\n")
|
||||||
|
@ -345,10 +345,15 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/settingBarStyle"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="@color/setting_bar_color"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:paddingEnd="10dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -386,147 +391,156 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layout_location_setting"
|
||||||
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:orientation="vertical"
|
||||||
android:orientation="horizontal">
|
android:visibility="gone">
|
||||||
|
|
||||||
<TextView
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/accuracy"
|
android:gravity="center_vertical"
|
||||||
android:textSize="10sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:ignore="SmallSp" />
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:id="@+id/rg_accuracy"
|
|
||||||
style="@style/rg_style"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RadioButton
|
<TextView
|
||||||
android:id="@+id/rb_accuracy_fine"
|
android:layout_width="wrap_content"
|
||||||
style="@style/rg_rb_style_wrap"
|
android:layout_height="wrap_content"
|
||||||
android:checked="true"
|
android:text="@string/accuracy"
|
||||||
android:text="@string/accuracy_fine" />
|
android:textSize="10sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioGroup
|
||||||
android:id="@+id/rb_accuracy_coarse"
|
android:id="@+id/rg_accuracy"
|
||||||
style="@style/rg_rb_style_wrap"
|
style="@style/rg_style"
|
||||||
android:text="@string/accuracy_coarse" />
|
android:layout_marginStart="5dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_accuracy_no_requirement"
|
android:id="@+id/rb_accuracy_fine"
|
||||||
style="@style/rg_rb_style_wrap"
|
style="@style/rg_rb_style_wrap"
|
||||||
android:text="@string/no_requirement" />
|
android:checked="true"
|
||||||
|
android:text="@string/accuracy_fine" />
|
||||||
|
|
||||||
</RadioGroup>
|
<RadioButton
|
||||||
|
android:id="@+id/rb_accuracy_coarse"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/accuracy_coarse" />
|
||||||
|
|
||||||
</LinearLayout>
|
<RadioButton
|
||||||
|
android:id="@+id/rb_accuracy_no_requirement"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/no_requirement" />
|
||||||
|
|
||||||
<LinearLayout
|
</RadioGroup>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/power_requirement"
|
android:gravity="center_vertical"
|
||||||
android:textSize="10sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
tools:ignore="SmallSp" />
|
|
||||||
|
|
||||||
<RadioGroup
|
|
||||||
android:id="@+id/rg_power_requirement"
|
|
||||||
style="@style/rg_style"
|
|
||||||
android:layout_marginStart="5dp"
|
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RadioButton
|
<TextView
|
||||||
android:id="@+id/rb_power_requirement_low"
|
android:layout_width="wrap_content"
|
||||||
style="@style/rg_rb_style_wrap"
|
android:layout_height="wrap_content"
|
||||||
android:checked="true"
|
android:text="@string/power_requirement"
|
||||||
android:text="@string/power_requirement_low" />
|
android:textSize="10sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioGroup
|
||||||
android:id="@+id/rb_power_requirement_medium"
|
android:id="@+id/rg_power_requirement"
|
||||||
style="@style/rg_rb_style_wrap"
|
style="@style/rg_style"
|
||||||
android:text="@string/power_requirement_medium" />
|
android:layout_marginStart="5dp"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_power_requirement_high"
|
android:id="@+id/rb_power_requirement_low"
|
||||||
style="@style/rg_rb_style_wrap"
|
style="@style/rg_rb_style_wrap"
|
||||||
android:text="@string/power_requirement_high" />
|
android:checked="true"
|
||||||
|
android:text="@string/power_requirement_low" />
|
||||||
|
|
||||||
<RadioButton
|
<RadioButton
|
||||||
android:id="@+id/rb_power_requirement_no_requirement"
|
android:id="@+id/rb_power_requirement_medium"
|
||||||
style="@style/rg_rb_style_wrap"
|
style="@style/rg_rb_style_wrap"
|
||||||
android:text="@string/no_requirement" />
|
android:text="@string/power_requirement_medium" />
|
||||||
|
|
||||||
</RadioGroup>
|
<RadioButton
|
||||||
|
android:id="@+id/rb_power_requirement_high"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/power_requirement_high" />
|
||||||
|
|
||||||
</LinearLayout>
|
<RadioButton
|
||||||
|
android:id="@+id/rb_power_requirement_no_requirement"
|
||||||
|
style="@style/rg_rb_style_wrap"
|
||||||
|
android:text="@string/no_requirement" />
|
||||||
|
|
||||||
<LinearLayout
|
</RadioGroup>
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<TextView
|
</LinearLayout>
|
||||||
android:layout_width="wrap_content"
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/min_interval"
|
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||||
android:textSize="10sp"
|
android:gravity="center_vertical"
|
||||||
android:textStyle="bold"
|
android:orientation="horizontal">
|
||||||
tools:ignore="SmallSp" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.picker.XSeekBar
|
<TextView
|
||||||
android:id="@+id/xsb_min_interval"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:text="@string/min_interval"
|
||||||
android:layout_marginStart="5dp"
|
android:textSize="10sp"
|
||||||
android:layout_weight="1"
|
android:textStyle="bold"
|
||||||
app:xsb_max="120"
|
tools:ignore="SmallSp" />
|
||||||
app:xsb_min="1" />
|
|
||||||
|
|
||||||
<TextView
|
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/xsb_min_interval"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/seconds"
|
android:layout_marginStart="5dp"
|
||||||
android:textSize="12sp"
|
android:layout_weight="1"
|
||||||
android:textStyle="bold" />
|
app:xsb_max="120"
|
||||||
|
app:xsb_min="1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
android:layout_marginStart="5dp"
|
||||||
android:text="@string/min_distance"
|
android:text="@string/seconds"
|
||||||
android:textSize="10sp"
|
android:textSize="12sp"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold" />
|
||||||
tools:ignore="SmallSp" />
|
|
||||||
|
|
||||||
<com.xuexiang.xui.widget.picker.XSeekBar
|
<TextView
|
||||||
android:id="@+id/xsb_min_distance"
|
android:layout_width="wrap_content"
|
||||||
android:layout_width="0dp"
|
android:layout_height="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||||
android:layout_marginStart="5dp"
|
android:text="@string/min_distance"
|
||||||
android:layout_weight="1"
|
android:textSize="10sp"
|
||||||
app:xsb_max="120"
|
android:textStyle="bold"
|
||||||
app:xsb_min="0" />
|
tools:ignore="SmallSp" />
|
||||||
|
|
||||||
<TextView
|
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/xsb_min_distance"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/meter"
|
android:layout_marginStart="5dp"
|
||||||
android:textSize="12sp"
|
android:layout_weight="1"
|
||||||
android:textStyle="bold" />
|
app:xsb_max="120"
|
||||||
|
app:xsb_min="0" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="5dp"
|
||||||
|
android:text="@string/meter"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
@ -1072,11 +1086,14 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
style="@style/settingBarStyle"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:background="@color/setting_bar_color"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:paddingEnd="15dp"
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="10dp"
|
||||||
|
android:paddingTop="10dp"
|
||||||
tools:ignore="RtlSymmetry">
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
@ -1123,7 +1140,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
app:xsb_max="30"
|
app:xsb_max="10"
|
||||||
app:xsb_min="0" />
|
app:xsb_min="0" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -1154,7 +1171,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
app:xsb_max="99"
|
app:xsb_max="60"
|
||||||
app:xsb_min="1" />
|
app:xsb_min="1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
@ -1185,7 +1202,7 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
app:xsb_max="99"
|
app:xsb_max="60"
|
||||||
app:xsb_min="1" />
|
app:xsb_min="1" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
Loading…
x
Reference in New Issue
Block a user