mirror of
https://github.com/pppscn/SmsForwarder
synced 2025-08-02 17:07:41 +08:00
新增:自动任务·快捷指令 —— 到达地点&离开地点
This commit is contained in:
parent
d8553ef793
commit
0d77eac6ce
@ -222,11 +222,14 @@
|
||||
android:exported="true"
|
||||
android:value="640" />
|
||||
|
||||
<service
|
||||
android:name=".service.ForegroundService"
|
||||
android:enabled="true" />
|
||||
<service
|
||||
android:name=".service.HttpServerService"
|
||||
android:enabled="true" />
|
||||
<service
|
||||
android:name=".service.ForegroundService"
|
||||
android:name=".service.LocationService"
|
||||
android:enabled="true" />
|
||||
<service
|
||||
android:name=".service.NotificationService"
|
||||
|
@ -6,6 +6,7 @@ import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.location.Geocoder
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.Build
|
||||
@ -27,11 +28,13 @@ import com.idormy.sms.forwarder.receiver.LockScreenReceiver
|
||||
import com.idormy.sms.forwarder.receiver.NetworkChangeReceiver
|
||||
import com.idormy.sms.forwarder.service.ForegroundService
|
||||
import com.idormy.sms.forwarder.service.HttpServerService
|
||||
import com.idormy.sms.forwarder.service.LocationService
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.utils.sdkinit.UMengInit
|
||||
import com.idormy.sms.forwarder.utils.sdkinit.XBasicLibInit
|
||||
import com.idormy.sms.forwarder.utils.sdkinit.XUpdateInit
|
||||
import com.idormy.sms.forwarder.utils.tinker.TinkerLoadLibrary
|
||||
import com.king.location.LocationClient
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
@ -74,19 +77,17 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
||||
val isDebug: Boolean
|
||||
get() = BuildConfig.DEBUG
|
||||
|
||||
//Cactus结束时间
|
||||
val mEndDate = MutableLiveData<String>()
|
||||
|
||||
//Cactus上次存活时间
|
||||
val mLastTimer = MutableLiveData<String>()
|
||||
|
||||
//Cactus存活时间
|
||||
val mTimer = MutableLiveData<String>()
|
||||
|
||||
//Cactus运行状态
|
||||
val mStatus = MutableLiveData<Boolean>().apply { value = true }
|
||||
|
||||
//Cactus相关
|
||||
val mEndDate = MutableLiveData<String>() //结束时间
|
||||
val mLastTimer = MutableLiveData<String>() //上次存活时间
|
||||
val mTimer = MutableLiveData<String>() //存活时间
|
||||
val mStatus = MutableLiveData<Boolean>().apply { value = true } //运行状态
|
||||
var mDisposable: Disposable? = null
|
||||
|
||||
//Location相关
|
||||
val LocationClient by lazy { LocationClient(context) }
|
||||
val Geocoder by lazy { Geocoder(context) }
|
||||
val DateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()) }
|
||||
}
|
||||
|
||||
override fun attachBaseContext(base: Context) {
|
||||
@ -116,12 +117,12 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
||||
}
|
||||
|
||||
//启动前台服务
|
||||
val serviceIntent = Intent(this, ForegroundService::class.java)
|
||||
serviceIntent.action = "START"
|
||||
val foregroundServiceIntent = Intent(this, ForegroundService::class.java)
|
||||
foregroundServiceIntent.action = "START"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
startForegroundService(serviceIntent)
|
||||
startForegroundService(foregroundServiceIntent)
|
||||
} else {
|
||||
startService(serviceIntent)
|
||||
startService(foregroundServiceIntent)
|
||||
}
|
||||
|
||||
//启动HttpServer
|
||||
@ -131,6 +132,13 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
|
||||
}
|
||||
}
|
||||
|
||||
//启动LocationService
|
||||
if (SettingUtils.enableLocation) {
|
||||
val locationServiceIntent = Intent(this, LocationService::class.java)
|
||||
locationServiceIntent.action = "START"
|
||||
startService(locationServiceIntent)
|
||||
}
|
||||
|
||||
//监听电量&充电状态变化
|
||||
val batteryReceiver = BatteryReceiver()
|
||||
val batteryFilter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
|
||||
|
@ -0,0 +1,38 @@
|
||||
package com.idormy.sms.forwarder.entity.task
|
||||
|
||||
import com.idormy.sms.forwarder.R
|
||||
import java.io.Serializable
|
||||
import kotlin.math.atan2
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
import kotlin.math.sqrt
|
||||
|
||||
data class LocationSetting(
|
||||
var description: String = "", //描述
|
||||
var type: String = "to", //监控类型:"to":到达地点;"leave":离开地点
|
||||
var calcType: String = "distance", //计算方式:"distance":计算距离;"address":地址匹配
|
||||
var longitude: Double = 0.0, //经度
|
||||
var latitude: Double = 0.0, //纬度
|
||||
var distance: Double = 0.0, //距离
|
||||
var address: String = "", //地址
|
||||
) : Serializable {
|
||||
|
||||
fun getCalcTypeCheckId(): Int {
|
||||
return when (calcType) {
|
||||
"distance" -> R.id.rb_calc_type_distance
|
||||
"address" -> R.id.rb_calc_type_address
|
||||
else -> R.id.rb_calc_type_distance
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateDistance(
|
||||
lat1: Double, lon1: Double, lat2: Double, lon2: Double
|
||||
): Double {
|
||||
val earthRadius = 6371000.0 // 地球平均半径,单位:米
|
||||
val latDistance = Math.toRadians(lat2 - lat1)
|
||||
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 c = 2 * atan2(sqrt(a), sqrt(1 - a))
|
||||
return earthRadius * c
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@ package com.idormy.sms.forwarder.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
@ -21,8 +20,8 @@ import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.core.BaseFragment
|
||||
import com.idormy.sms.forwarder.databinding.FragmentServerBinding
|
||||
import com.idormy.sms.forwarder.service.ForegroundService
|
||||
import com.idormy.sms.forwarder.service.HttpServerService
|
||||
import com.idormy.sms.forwarder.service.LocationService
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
import com.xuexiang.xpage.annotation.Page
|
||||
@ -240,6 +239,12 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
|
||||
|
||||
binding!!.sbApiLocation.isChecked = HttpServerUtils.enableApiLocation
|
||||
binding!!.sbApiLocation.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
if (isChecked && !SettingUtils.enableLocation) {
|
||||
XToastUtils.error(getString(R.string.api_location_permission_tips))
|
||||
binding!!.sbApiLocation.isChecked = false
|
||||
return@setOnCheckedChangeListener
|
||||
}
|
||||
|
||||
HttpServerUtils.enableApiLocation = isChecked
|
||||
if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpServerService")) {
|
||||
Log.d("ServerFragment", "onClick: 重启服务")
|
||||
@ -251,13 +256,9 @@ class ServerFragment : BaseFragment<FragmentServerBinding?>(), View.OnClickListe
|
||||
refreshButtonText()
|
||||
}
|
||||
//重启前台服务,启动/停止定位服务
|
||||
val serviceIntent = Intent(requireContext(), ForegroundService::class.java)
|
||||
val serviceIntent = Intent(requireContext(), LocationService::class.java)
|
||||
serviceIntent.action = "START"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
requireContext().startForegroundService(serviceIntent)
|
||||
} else {
|
||||
requireContext().startService(serviceIntent)
|
||||
}
|
||||
requireContext().startService(serviceIntent)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.location.Criteria
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
@ -34,6 +35,7 @@ import com.idormy.sms.forwarder.databinding.FragmentSettingsBinding
|
||||
import com.idormy.sms.forwarder.entity.SimInfo
|
||||
import com.idormy.sms.forwarder.receiver.BootCompletedReceiver
|
||||
import com.idormy.sms.forwarder.service.ForegroundService
|
||||
import com.idormy.sms.forwarder.service.LocationService
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
@ -162,7 +164,7 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
switchDirectlyToTask(binding!!.sbDirectlyToTask)
|
||||
|
||||
//启用 {{定位信息}} 标签
|
||||
switchEnableLocationTag(binding!!.sbEnableLocationTag)
|
||||
switchEnableLocation(binding!!.sbEnableLocation, binding!!.rgAccuracy, binding!!.rgPowerRequirement, binding!!.xsbMinInterval, binding!!.xsbMinDistance)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
@ -885,15 +887,16 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
}
|
||||
}
|
||||
|
||||
//启用 {{定位信息}} 标签
|
||||
private fun switchEnableLocationTag(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocationTag: SwitchButton) {
|
||||
switchEnableLocationTag.isChecked = SettingUtils.enableLocationTag
|
||||
switchEnableLocationTag.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
SettingUtils.enableLocationTag = isChecked
|
||||
//启用定位功能
|
||||
private fun switchEnableLocation(@SuppressLint("UseSwitchCompatOrMaterialCode") switchEnableLocation: SwitchButton, rgAccuracy: RadioGroup, rgPowerRequirement: RadioGroup, xsbMinInterval: XSeekBar, xsbMinDistance: XSeekBar) {
|
||||
//是否启用定位功能
|
||||
switchEnableLocation.isChecked = SettingUtils.enableLocation
|
||||
switchEnableLocation.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
|
||||
SettingUtils.enableLocation = isChecked
|
||||
if (isChecked) {
|
||||
XXPermissions.with(this).permission(Permission.ACCESS_COARSE_LOCATION).permission(Permission.ACCESS_FINE_LOCATION).permission(Permission.ACCESS_BACKGROUND_LOCATION).request(object : OnPermissionCallback {
|
||||
override fun onGranted(permissions: List<String>, all: Boolean) {
|
||||
restartForegroundService()
|
||||
restartLocationService()
|
||||
}
|
||||
|
||||
override fun onDenied(permissions: List<String>, never: Boolean) {
|
||||
@ -904,26 +907,72 @@ class SettingsFragment : BaseFragment<FragmentSettingsBinding?>(), View.OnClickL
|
||||
} else {
|
||||
XToastUtils.error(R.string.toast_denied)
|
||||
}
|
||||
SettingUtils.enableLocationTag = false
|
||||
switchEnableLocationTag.isChecked = false
|
||||
restartForegroundService()
|
||||
SettingUtils.enableLocation = false
|
||||
switchEnableLocation.isChecked = false
|
||||
restartLocationService()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
restartForegroundService()
|
||||
restartLocationService()
|
||||
}
|
||||
}
|
||||
//设置位置精度:高精度(默认)
|
||||
rgAccuracy.check(
|
||||
when (SettingUtils.locationAccuracy) {
|
||||
Criteria.ACCURACY_FINE -> R.id.rb_accuracy_fine
|
||||
Criteria.ACCURACY_COARSE -> R.id.rb_accuracy_coarse
|
||||
Criteria.NO_REQUIREMENT -> R.id.rb_accuracy_no_requirement
|
||||
else -> R.id.rb_accuracy_fine
|
||||
}
|
||||
)
|
||||
rgAccuracy.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
||||
SettingUtils.locationAccuracy = when (checkedId) {
|
||||
R.id.rb_accuracy_fine -> Criteria.ACCURACY_FINE
|
||||
R.id.rb_accuracy_coarse -> Criteria.ACCURACY_COARSE
|
||||
R.id.rb_accuracy_no_requirement -> Criteria.NO_REQUIREMENT
|
||||
else -> Criteria.ACCURACY_FINE
|
||||
}
|
||||
restartLocationService()
|
||||
}
|
||||
//设置电量消耗:低电耗(默认)
|
||||
rgPowerRequirement.check(
|
||||
when (SettingUtils.locationPowerRequirement) {
|
||||
Criteria.POWER_HIGH -> R.id.rb_power_requirement_high
|
||||
Criteria.POWER_MEDIUM -> R.id.rb_power_requirement_medium
|
||||
Criteria.POWER_LOW -> R.id.rb_power_requirement_low
|
||||
Criteria.NO_REQUIREMENT -> R.id.rb_power_requirement_no_requirement
|
||||
else -> R.id.rb_power_requirement_low
|
||||
}
|
||||
)
|
||||
rgPowerRequirement.setOnCheckedChangeListener { _: RadioGroup?, checkedId: Int ->
|
||||
SettingUtils.locationPowerRequirement = when (checkedId) {
|
||||
R.id.rb_power_requirement_high -> Criteria.POWER_HIGH
|
||||
R.id.rb_power_requirement_medium -> Criteria.POWER_MEDIUM
|
||||
R.id.rb_power_requirement_low -> Criteria.POWER_LOW
|
||||
R.id.rb_power_requirement_no_requirement -> Criteria.NO_REQUIREMENT
|
||||
else -> Criteria.POWER_LOW
|
||||
}
|
||||
restartLocationService()
|
||||
}
|
||||
//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
||||
xsbMinInterval.setDefaultValue((SettingUtils.locationMinInterval / 1000).toInt())
|
||||
xsbMinInterval.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
|
||||
SettingUtils.locationMinInterval = newValue * 1000L
|
||||
restartLocationService()
|
||||
}
|
||||
//设置位置更新最小距离(单位:米);默认距离:0米
|
||||
xsbMinDistance.setDefaultValue(SettingUtils.locationMinDistance)
|
||||
xsbMinDistance.setOnSeekBarListener { _: XSeekBar?, newValue: Int ->
|
||||
SettingUtils.locationMinDistance = newValue
|
||||
restartLocationService()
|
||||
}
|
||||
}
|
||||
|
||||
//重启前台服务
|
||||
private fun restartForegroundService() {
|
||||
val serviceIntent = Intent(requireContext(), ForegroundService::class.java)
|
||||
//重启定位服务
|
||||
private fun restartLocationService() {
|
||||
val serviceIntent = Intent(requireContext(), LocationService::class.java)
|
||||
serviceIntent.action = "START"
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
requireContext().startForegroundService(serviceIntent)
|
||||
} else {
|
||||
requireContext().startService(serviceIntent)
|
||||
}
|
||||
requireContext().startService(serviceIntent)
|
||||
}
|
||||
|
||||
//获取当前手机品牌
|
||||
|
@ -355,20 +355,26 @@ class TasksEditFragment : BaseFragment<FragmentTasksEditBinding?>(), View.OnClic
|
||||
Log.d(TAG, "onItemClick: $widgetInfo")
|
||||
//判断点击的是条件还是动作
|
||||
if (widgetInfo.classPath.contains(".condition.")) {
|
||||
val typeCondition = pos + KEY_BACK_CODE_CONDITION
|
||||
//判断是否已经添加过该类型条件
|
||||
for (item in itemListConditions) {
|
||||
//注意:TASK_CONDITION_XXX 枚举值 等于 TASK_CONDITION_FRAGMENT_LIST 索引加上 KEY_BACK_CODE_CONDITION,不可改变
|
||||
if (item.type == pos + KEY_BACK_CODE_CONDITION) {
|
||||
XToastUtils.error("已经添加过该类型条件")
|
||||
if (item.type == typeCondition) {
|
||||
XToastUtils.error(getString(R.string.condition_already_exists))
|
||||
return
|
||||
}
|
||||
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))
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val typeAction = pos + KEY_BACK_CODE_ACTION
|
||||
//判断是否已经添加过该类型动作
|
||||
for (item in itemListActions) {
|
||||
//注意:TASK_ACTION_XXX 枚举值 等于 TASK_ACTION_FRAGMENT_LIST 索引加上 KEY_BACK_CODE_ACTION,不可改变
|
||||
if (item.type == pos + KEY_BACK_CODE_ACTION) {
|
||||
XToastUtils.error("已经添加过该类型动作")
|
||||
if (item.type == typeAction) {
|
||||
XToastUtils.error(getString(R.string.action_already_exists))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,175 @@
|
||||
package com.idormy.sms.forwarder.fragment.condition
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.core.BaseFragment
|
||||
import com.idormy.sms.forwarder.databinding.FragmentTasksConditionLeaveAddressBinding
|
||||
import com.idormy.sms.forwarder.entity.task.LocationSetting
|
||||
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_EVENT_DATA_CONDITION
|
||||
import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION
|
||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_LEAVE_ADDRESS
|
||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
import com.xuexiang.xpage.annotation.Page
|
||||
import com.xuexiang.xrouter.annotation.AutoWired
|
||||
import com.xuexiang.xrouter.launcher.XRouter
|
||||
import com.xuexiang.xui.utils.CountDownButtonHelper
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||
|
||||
@Page(name = "LeaveAddress")
|
||||
@Suppress("PrivatePropertyName")
|
||||
class LeaveAddressFragment : BaseFragment<FragmentTasksConditionLeaveAddressBinding?>(), View.OnClickListener {
|
||||
|
||||
private val TAG: String = LeaveAddressFragment::class.java.simpleName
|
||||
var titleBar: TitleBar? = null
|
||||
private var mCountDownHelper: CountDownButtonHelper? = null
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_EVENT_DATA_CONDITION)
|
||||
var eventData: String? = null
|
||||
|
||||
private var description = ""
|
||||
|
||||
override fun initArgs() {
|
||||
XRouter.getInstance().inject(this)
|
||||
}
|
||||
|
||||
override fun viewBindingInflate(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
): FragmentTasksConditionLeaveAddressBinding {
|
||||
return FragmentTasksConditionLeaveAddressBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun initTitle(): TitleBar? {
|
||||
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_leave_address)
|
||||
return titleBar
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
override fun initViews() {
|
||||
//测试按钮增加倒计时,避免重复点击
|
||||
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
||||
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
|
||||
override fun onCountDown(time: Int) {
|
||||
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
|
||||
}
|
||||
|
||||
override fun onFinished() {
|
||||
binding!!.btnTest.text = getString(R.string.test)
|
||||
}
|
||||
})
|
||||
|
||||
binding!!.rgCalcType.setOnCheckedChangeListener { _, checkedId ->
|
||||
if (checkedId == R.id.rb_calc_type_distance) {
|
||||
binding!!.layoutCalcTypeDistance.visibility = View.VISIBLE
|
||||
binding!!.layoutCalcTypeAddress.visibility = View.GONE
|
||||
} else {
|
||||
binding!!.layoutCalcTypeDistance.visibility = View.GONE
|
||||
binding!!.layoutCalcTypeAddress.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "initViews eventData:$eventData")
|
||||
if (eventData != null) {
|
||||
val settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
|
||||
Log.d(TAG, "initViews settingVo:$settingVo")
|
||||
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
|
||||
binding!!.etLongitude.setText(settingVo.longitude.toString())
|
||||
binding!!.etLatitude.setText(settingVo.latitude.toString())
|
||||
binding!!.etDistance.setText(settingVo.distance.toString())
|
||||
binding!!.etAddress.setText(settingVo.address)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun initListeners() {
|
||||
binding!!.btnTest.setOnClickListener(this)
|
||||
binding!!.btnDel.setOnClickListener(this)
|
||||
binding!!.btnSave.setOnClickListener(this)
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) {
|
||||
mCountDownHelper?.finish()
|
||||
|
||||
if (it == "success") {
|
||||
XToastUtils.success("测试通过", 30000)
|
||||
} else {
|
||||
XToastUtils.error(it, 30000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(v: View) {
|
||||
try {
|
||||
when (v.id) {
|
||||
R.id.btn_test -> {
|
||||
mCountDownHelper?.start()
|
||||
Thread {
|
||||
try {
|
||||
val settingVo = checkSetting()
|
||||
Log.d(TAG, settingVo.toString())
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post("success")
|
||||
} catch (e: Exception) {
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post(e.message.toString())
|
||||
e.printStackTrace()
|
||||
}
|
||||
}.start()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_del -> {
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_save -> {
|
||||
val settingVo = checkSetting()
|
||||
val intent = Intent()
|
||||
intent.putExtra(KEY_BACK_DESCRIPTION_CONDITION, description)
|
||||
intent.putExtra(KEY_BACK_DATA_CONDITION, Gson().toJson(settingVo))
|
||||
setFragmentResult(TASK_CONDITION_LEAVE_ADDRESS, intent)
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString(), 30000)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
//检查设置
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun checkSetting(): LocationSetting {
|
||||
val longitude = binding!!.etLongitude.text.toString().toDouble()
|
||||
val latitude = binding!!.etLatitude.text.toString().toDouble()
|
||||
val distance = binding!!.etDistance.text.toString().toDouble()
|
||||
val address = binding!!.etAddress.text.toString()
|
||||
var calcType = "distance"
|
||||
if (binding!!.rbCalcTypeDistance.isChecked) {
|
||||
if (latitude.isNaN() || longitude.isNaN() || distance.isNaN()) {
|
||||
throw Exception(getString(R.string.calc_type_address_error))
|
||||
}
|
||||
description = String.format(getString(R.string.leave_address_distance_description), longitude, latitude, distance)
|
||||
} else if (binding!!.rbCalcTypeAddress.isChecked) {
|
||||
if (address.isEmpty()) {
|
||||
throw Exception(getString(R.string.calc_type_address_error))
|
||||
}
|
||||
description = String.format(getString(R.string.leave_address_keyword_description), address)
|
||||
calcType = "address"
|
||||
}
|
||||
|
||||
return LocationSetting(description, "leave", calcType, longitude, latitude, distance, address)
|
||||
}
|
||||
}
|
@ -0,0 +1,175 @@
|
||||
package com.idormy.sms.forwarder.fragment.condition
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.core.BaseFragment
|
||||
import com.idormy.sms.forwarder.databinding.FragmentTasksConditionToAddressBinding
|
||||
import com.idormy.sms.forwarder.entity.task.LocationSetting
|
||||
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_EVENT_DATA_CONDITION
|
||||
import com.idormy.sms.forwarder.utils.KEY_TEST_CONDITION
|
||||
import com.idormy.sms.forwarder.utils.TASK_CONDITION_TO_ADDRESS
|
||||
import com.idormy.sms.forwarder.utils.XToastUtils
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.xuexiang.xaop.annotation.SingleClick
|
||||
import com.xuexiang.xpage.annotation.Page
|
||||
import com.xuexiang.xrouter.annotation.AutoWired
|
||||
import com.xuexiang.xrouter.launcher.XRouter
|
||||
import com.xuexiang.xui.utils.CountDownButtonHelper
|
||||
import com.xuexiang.xui.widget.actionbar.TitleBar
|
||||
|
||||
@Page(name = "ToAddress")
|
||||
@Suppress("PrivatePropertyName")
|
||||
class ToAddressFragment : BaseFragment<FragmentTasksConditionToAddressBinding?>(), View.OnClickListener {
|
||||
|
||||
private val TAG: String = ToAddressFragment::class.java.simpleName
|
||||
var titleBar: TitleBar? = null
|
||||
private var mCountDownHelper: CountDownButtonHelper? = null
|
||||
|
||||
@JvmField
|
||||
@AutoWired(name = KEY_EVENT_DATA_CONDITION)
|
||||
var eventData: String? = null
|
||||
|
||||
private var description = ""
|
||||
|
||||
override fun initArgs() {
|
||||
XRouter.getInstance().inject(this)
|
||||
}
|
||||
|
||||
override fun viewBindingInflate(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup,
|
||||
): FragmentTasksConditionToAddressBinding {
|
||||
return FragmentTasksConditionToAddressBinding.inflate(inflater, container, false)
|
||||
}
|
||||
|
||||
override fun initTitle(): TitleBar? {
|
||||
titleBar = super.initTitle()!!.setImmersive(false).setTitle(R.string.task_to_address)
|
||||
return titleBar
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
override fun initViews() {
|
||||
//测试按钮增加倒计时,避免重复点击
|
||||
mCountDownHelper = CountDownButtonHelper(binding!!.btnTest, 3)
|
||||
mCountDownHelper!!.setOnCountDownListener(object : CountDownButtonHelper.OnCountDownListener {
|
||||
override fun onCountDown(time: Int) {
|
||||
binding!!.btnTest.text = String.format(getString(R.string.seconds_n), time)
|
||||
}
|
||||
|
||||
override fun onFinished() {
|
||||
binding!!.btnTest.text = getString(R.string.test)
|
||||
}
|
||||
})
|
||||
|
||||
binding!!.rgCalcType.setOnCheckedChangeListener { _, checkedId ->
|
||||
if (checkedId == R.id.rb_calc_type_distance) {
|
||||
binding!!.layoutCalcTypeDistance.visibility = View.VISIBLE
|
||||
binding!!.layoutCalcTypeAddress.visibility = View.GONE
|
||||
} else {
|
||||
binding!!.layoutCalcTypeDistance.visibility = View.GONE
|
||||
binding!!.layoutCalcTypeAddress.visibility = View.VISIBLE
|
||||
}
|
||||
}
|
||||
|
||||
Log.d(TAG, "initViews eventData:$eventData")
|
||||
if (eventData != null) {
|
||||
val settingVo = Gson().fromJson(eventData, LocationSetting::class.java)
|
||||
Log.d(TAG, "initViews settingVo:$settingVo")
|
||||
binding!!.rgCalcType.check(settingVo.getCalcTypeCheckId())
|
||||
binding!!.etLongitude.setText(settingVo.longitude.toString())
|
||||
binding!!.etLatitude.setText(settingVo.latitude.toString())
|
||||
binding!!.etDistance.setText(settingVo.distance.toString())
|
||||
binding!!.etAddress.setText(settingVo.address)
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun initListeners() {
|
||||
binding!!.btnTest.setOnClickListener(this)
|
||||
binding!!.btnDel.setOnClickListener(this)
|
||||
binding!!.btnSave.setOnClickListener(this)
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).observe(this) {
|
||||
mCountDownHelper?.finish()
|
||||
|
||||
if (it == "success") {
|
||||
XToastUtils.success("测试通过", 30000)
|
||||
} else {
|
||||
XToastUtils.error(it, 30000)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SingleClick
|
||||
override fun onClick(v: View) {
|
||||
try {
|
||||
when (v.id) {
|
||||
R.id.btn_test -> {
|
||||
mCountDownHelper?.start()
|
||||
Thread {
|
||||
try {
|
||||
val settingVo = checkSetting()
|
||||
Log.d(TAG, settingVo.toString())
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post("success")
|
||||
} catch (e: Exception) {
|
||||
LiveEventBus.get(KEY_TEST_CONDITION, String::class.java).post(e.message.toString())
|
||||
e.printStackTrace()
|
||||
}
|
||||
}.start()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_del -> {
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
|
||||
R.id.btn_save -> {
|
||||
val settingVo = checkSetting()
|
||||
val intent = Intent()
|
||||
intent.putExtra(KEY_BACK_DESCRIPTION_CONDITION, description)
|
||||
intent.putExtra(KEY_BACK_DATA_CONDITION, Gson().toJson(settingVo))
|
||||
setFragmentResult(TASK_CONDITION_TO_ADDRESS, intent)
|
||||
popToBack()
|
||||
return
|
||||
}
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
XToastUtils.error(e.message.toString(), 30000)
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
//检查设置
|
||||
@SuppressLint("SetTextI18n")
|
||||
private fun checkSetting(): LocationSetting {
|
||||
val longitude = binding!!.etLongitude.text.toString().toDouble()
|
||||
val latitude = binding!!.etLatitude.text.toString().toDouble()
|
||||
val distance = binding!!.etDistance.text.toString().toDouble()
|
||||
val address = binding!!.etAddress.text.toString()
|
||||
var calcType = "distance"
|
||||
if (binding!!.rbCalcTypeDistance.isChecked) {
|
||||
if (latitude.isNaN() || longitude.isNaN() || distance.isNaN()) {
|
||||
throw Exception(getString(R.string.calc_type_address_error))
|
||||
}
|
||||
description = String.format(getString(R.string.to_address_distance_description), longitude, latitude, distance)
|
||||
} else if (binding!!.rbCalcTypeAddress.isChecked) {
|
||||
if (address.isEmpty()) {
|
||||
throw Exception(getString(R.string.calc_type_address_error))
|
||||
}
|
||||
description = String.format(getString(R.string.to_address_keyword_description), address)
|
||||
calcType = "address"
|
||||
}
|
||||
|
||||
return LocationSetting(description, "to", calcType, longitude, latitude, distance, address)
|
||||
}
|
||||
}
|
@ -5,9 +5,6 @@ import android.app.*
|
||||
import android.content.Intent
|
||||
import android.graphics.BitmapFactory
|
||||
import android.graphics.Color
|
||||
import android.location.Criteria
|
||||
import android.location.Geocoder
|
||||
import android.location.Location
|
||||
import android.os.Build
|
||||
import android.os.IBinder
|
||||
import android.text.TextUtils
|
||||
@ -20,16 +17,10 @@ import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.idormy.sms.forwarder.activity.MainActivity
|
||||
import com.idormy.sms.forwarder.database.AppDatabase
|
||||
import com.idormy.sms.forwarder.entity.LocationInfo
|
||||
import com.idormy.sms.forwarder.utils.*
|
||||
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
|
||||
import com.idormy.sms.forwarder.workers.LoadAppListWorker
|
||||
import com.jeremyliao.liveeventbus.LiveEventBus
|
||||
import com.king.location.LocationClient
|
||||
import com.king.location.LocationErrorCode
|
||||
import com.king.location.OnExceptionListener
|
||||
import com.king.location.OnLocationListener
|
||||
import com.xuexiang.xaop.util.PermissionUtils
|
||||
import com.xuexiang.xutil.XUtil
|
||||
import com.xuexiang.xutil.file.FileUtils
|
||||
import frpclib.Frpclib
|
||||
@ -42,8 +33,6 @@ import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.async
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
@Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE", "DEPRECATION", "LiftReturnOrAssignment")
|
||||
@ -81,10 +70,6 @@ class ForegroundService : Service() {
|
||||
})
|
||||
}
|
||||
|
||||
private val locationClient by lazy { LocationClient(App.context) }
|
||||
private val geocoder by lazy { Geocoder(App.context) }
|
||||
private val simpleDateFormat by lazy { SimpleDateFormat("yyyy-MM-dd HH:mm:ss") }
|
||||
|
||||
companion object {
|
||||
var isRunning = false
|
||||
}
|
||||
@ -181,70 +166,6 @@ class ForegroundService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
//远程找手机 TODO: 判断权限 ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION
|
||||
if ((SettingUtils.enableLocationTag || HttpServerUtils.enableApiLocation)
|
||||
&& PermissionUtils.isGranted(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION)
|
||||
) {
|
||||
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
|
||||
val locationOption = locationClient.getLocationOption().setAccuracy(Criteria.ACCURACY_FINE)//设置位置精度:高精度
|
||||
.setPowerRequirement(Criteria.POWER_LOW) //设置电量消耗:低电耗
|
||||
.setMinTime(10000)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
||||
.setMinDistance(0)//设置位置更新最小距离(单位:米);默认距离:0米
|
||||
.setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位
|
||||
.setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true
|
||||
//设置定位配置参数
|
||||
locationClient.setLocationOption(locationOption)
|
||||
locationClient.startLocation()
|
||||
|
||||
//设置定位监听
|
||||
locationClient.setOnLocationListener(object : OnLocationListener() {
|
||||
override fun onLocationChanged(location: Location) {
|
||||
//位置信息
|
||||
Log.d(TAG, "onLocationChanged(location = ${location})")
|
||||
|
||||
val locationInfo = LocationInfo(
|
||||
location.longitude, location.latitude, "", simpleDateFormat.format(Date(location.time)), location.provider.toString()
|
||||
)
|
||||
|
||||
//根据坐标经纬度获取位置地址信息(WGS-84坐标系)
|
||||
val list = geocoder.getFromLocation(location.latitude, location.longitude, 1)
|
||||
if (list?.isNotEmpty() == true) {
|
||||
locationInfo.address = list[0].getAddressLine(0)
|
||||
}
|
||||
|
||||
Log.d(TAG, "locationInfo = $locationInfo")
|
||||
HttpServerUtils.apiLocationCache = locationInfo
|
||||
}
|
||||
|
||||
override fun onProviderEnabled(provider: String) {
|
||||
super.onProviderEnabled(provider)
|
||||
Log.d(TAG, "onProviderEnabled(provider = ${provider})")
|
||||
}
|
||||
|
||||
override fun onProviderDisabled(provider: String) {
|
||||
super.onProviderDisabled(provider)
|
||||
Log.d(TAG, "onProviderDisabled(provider = ${provider})")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
//设置异常监听
|
||||
locationClient.setOnExceptionListener(object : OnExceptionListener {
|
||||
override fun onException(@LocationErrorCode errorCode: Int, e: Exception) {
|
||||
//定位出现异常
|
||||
Log.w(TAG, "onException(errorCode = ${errorCode}, e = ${e})")
|
||||
}
|
||||
})
|
||||
|
||||
if (locationClient.isStarted()) {//如果已经开始定位,则先停止定位
|
||||
locationClient.stopLocation()
|
||||
}
|
||||
locationClient.startLocation()
|
||||
} else if ((!SettingUtils.enableLocationTag && !HttpServerUtils.enableApiLocation) && locationClient.isStarted()) {
|
||||
Log.d(TAG, "stopLocation")
|
||||
locationClient.stopLocation()
|
||||
}
|
||||
|
||||
isRunning = true
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
@ -255,11 +176,6 @@ class ForegroundService : Service() {
|
||||
|
||||
private fun stopForegroundService() {
|
||||
try {
|
||||
//如果已经开始定位,则先停止定位
|
||||
if ((SettingUtils.enableLocationTag || HttpServerUtils.enableApiLocation) && locationClient.isStarted()) {
|
||||
locationClient.stopLocation()
|
||||
}
|
||||
|
||||
stopForeground(true)
|
||||
stopSelf()
|
||||
compositeDisposable.dispose()
|
||||
|
@ -0,0 +1,170 @@
|
||||
package com.idormy.sms.forwarder.service
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import android.location.Location
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.entity.LocationInfo
|
||||
import com.idormy.sms.forwarder.utils.HttpServerUtils
|
||||
import com.idormy.sms.forwarder.utils.SettingUtils
|
||||
import com.king.location.LocationErrorCode
|
||||
import com.king.location.OnExceptionListener
|
||||
import com.king.location.OnLocationListener
|
||||
import com.xuexiang.xaop.util.PermissionUtils
|
||||
import com.yanzhenjie.andserver.Server
|
||||
import java.util.Date
|
||||
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||
class LocationService : Service(), Server.ServerListener {
|
||||
|
||||
private val TAG: String = LocationService::class.java.simpleName
|
||||
|
||||
companion object {
|
||||
var isRunning = false
|
||||
}
|
||||
|
||||
override fun onBind(p0: Intent?): IBinder? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
Log.i(TAG, "onCreate: ")
|
||||
super.onCreate()
|
||||
|
||||
if (!SettingUtils.enableLocation) return
|
||||
startForegroundService()
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.i(TAG, "onStartCommand: ")
|
||||
if (intent != null) {
|
||||
when (intent.action) {
|
||||
"START" -> {
|
||||
startForegroundService()
|
||||
}
|
||||
|
||||
"STOP" -> {
|
||||
stopForegroundService()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
Log.i(TAG, "onDestroy: ")
|
||||
super.onDestroy()
|
||||
|
||||
if (!SettingUtils.enableLocation) return
|
||||
stopForegroundService()
|
||||
}
|
||||
|
||||
override fun onException(e: Exception?) {
|
||||
Log.i(TAG, "onException: ")
|
||||
}
|
||||
|
||||
override fun onStarted() {
|
||||
Log.i(TAG, "onStarted: ")
|
||||
}
|
||||
|
||||
override fun onStopped() {
|
||||
Log.i(TAG, "onStopped: ")
|
||||
}
|
||||
|
||||
private fun startForegroundService() {
|
||||
try {
|
||||
//远程找手机 TODO: 判断权限 ACCESS_COARSE_LOCATION ACCESS_FINE_LOCATION
|
||||
if (SettingUtils.enableLocation && PermissionUtils.isGranted(android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
|
||||
//可根据具体需求设置定位配置参数(这里只列出一些主要的参数)
|
||||
val locationOption = App.LocationClient.getLocationOption().setAccuracy(SettingUtils.locationAccuracy)//设置位置精度:高精度
|
||||
.setPowerRequirement(SettingUtils.locationPowerRequirement) //设置电量消耗:低电耗
|
||||
.setMinTime(SettingUtils.locationMinInterval)//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
||||
.setMinDistance(SettingUtils.locationMinDistance)//设置位置更新最小距离(单位:米);默认距离:0米
|
||||
.setOnceLocation(false)//设置是否只定位一次,默认为 false,当设置为 true 时,则只定位一次后,会自动停止定位
|
||||
.setLastKnownLocation(false)//设置是否获取最后一次缓存的已知位置,默认为 true
|
||||
//设置定位配置参数
|
||||
App.LocationClient.setLocationOption(locationOption)
|
||||
App.LocationClient.startLocation()
|
||||
|
||||
//设置定位监听
|
||||
App.LocationClient.setOnLocationListener(object : OnLocationListener() {
|
||||
override fun onLocationChanged(location: Location) {
|
||||
//位置信息
|
||||
Log.d(TAG, "onLocationChanged(location = ${location})")
|
||||
|
||||
val locationInfo = LocationInfo(
|
||||
location.longitude, location.latitude, "", App.DateFormat.format(Date(location.time)), location.provider.toString()
|
||||
)
|
||||
|
||||
//根据坐标经纬度获取位置地址信息(WGS-84坐标系)
|
||||
val list = App.Geocoder.getFromLocation(location.latitude, location.longitude, 1)
|
||||
if (list?.isNotEmpty() == true) {
|
||||
locationInfo.address = list[0].getAddressLine(0)
|
||||
}
|
||||
|
||||
Log.d(TAG, "locationInfo = $locationInfo")
|
||||
HttpServerUtils.apiLocationCache = locationInfo
|
||||
|
||||
//TODO: 触发自动任务
|
||||
}
|
||||
|
||||
override fun onProviderEnabled(provider: String) {
|
||||
super.onProviderEnabled(provider)
|
||||
Log.d(TAG, "onProviderEnabled(provider = ${provider})")
|
||||
}
|
||||
|
||||
override fun onProviderDisabled(provider: String) {
|
||||
super.onProviderDisabled(provider)
|
||||
Log.d(TAG, "onProviderDisabled(provider = ${provider})")
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
//设置异常监听
|
||||
App.LocationClient.setOnExceptionListener(object : OnExceptionListener {
|
||||
override fun onException(@LocationErrorCode errorCode: Int, e: Exception) {
|
||||
//定位出现异常
|
||||
Log.w(TAG, "onException(errorCode = ${errorCode}, e = ${e})")
|
||||
|
||||
//TODO: 重启定位
|
||||
App.LocationClient.startLocation()
|
||||
}
|
||||
})
|
||||
|
||||
if (App.LocationClient.isStarted()) {//如果已经开始定位,则先停止定位
|
||||
App.LocationClient.stopLocation()
|
||||
}
|
||||
App.LocationClient.startLocation()
|
||||
isRunning = true
|
||||
} else if (!SettingUtils.enableLocation && App.LocationClient.isStarted()) {
|
||||
Log.d(TAG, "stopLocation")
|
||||
App.LocationClient.stopLocation()
|
||||
isRunning = false
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
isRunning = false
|
||||
}
|
||||
}
|
||||
|
||||
private fun stopForegroundService() {
|
||||
isRunning = try {
|
||||
//如果已经开始定位,则先停止定位
|
||||
if (SettingUtils.enableLocation && App.LocationClient.isStarted()) {
|
||||
App.LocationClient.stopLocation()
|
||||
}
|
||||
stopForeground(true)
|
||||
stopSelf()
|
||||
false
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -85,7 +85,11 @@ const val SP_SMS_TEMPLATE = "sms_template"
|
||||
const val SP_ENABLE_HELP_TIP = "enable_help_tip"
|
||||
const val SP_PURE_CLIENT_MODE = "enable_pure_client_mode"
|
||||
const val SP_PURE_TASK_MODE = "enable_pure_task_mode"
|
||||
const val SP_LOCATION_TAG = "enable_location_tag"
|
||||
const val SP_LOCATION = "enable_location"
|
||||
const val SP_LOCATION_ACCURACY = "location_accuracy"
|
||||
const val SP_LOCATION_POWER_REQUIREMENT = "location_power_requirement"
|
||||
const val SP_LOCATION_MIN_INTERVAL = "location_min_interval_time"
|
||||
const val SP_LOCATION_MIN_DISTANCE = "location_min_distance"
|
||||
|
||||
const val SP_ENABLE_CACTUS = "enable_cactus"
|
||||
const val CACTUS_TIMER = "cactus_timer"
|
||||
@ -515,14 +519,14 @@ var TASK_CONDITION_FRAGMENT_LIST = listOf(
|
||||
R.drawable.auto_task_icon_custom_time,
|
||||
),
|
||||
PageInfo(
|
||||
getString(R.string.to_address),
|
||||
getString(R.string.task_to_address),
|
||||
"com.idormy.sms.forwarder.fragment.condition.ToAddressFragment",
|
||||
"{\"\":\"\"}",
|
||||
CoreAnim.slide,
|
||||
R.drawable.auto_task_icon_to_address,
|
||||
),
|
||||
PageInfo(
|
||||
getString(R.string.leave_address),
|
||||
getString(R.string.task_leave_address),
|
||||
"com.idormy.sms.forwarder.fragment.condition.LeaveAddressFragment",
|
||||
"{\"\":\"\"}",
|
||||
CoreAnim.slide,
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.idormy.sms.forwarder.utils
|
||||
|
||||
import android.location.Criteria
|
||||
import com.idormy.sms.forwarder.R
|
||||
import com.xuexiang.xui.utils.ResUtils.getString
|
||||
|
||||
@ -128,8 +129,20 @@ class SettingUtils private constructor() {
|
||||
//是否纯任务模式
|
||||
var enablePureTaskMode: Boolean by SharedPreference(SP_PURE_TASK_MODE, false)
|
||||
|
||||
//是否启用定位标签
|
||||
var enableLocationTag: Boolean by SharedPreference(SP_LOCATION_TAG, false)
|
||||
//是否启用定位功能
|
||||
var enableLocation: Boolean by SharedPreference(SP_LOCATION, false)
|
||||
|
||||
//设置位置精度:高精度
|
||||
var locationAccuracy: Int by SharedPreference(SP_LOCATION_ACCURACY, Criteria.ACCURACY_FINE)
|
||||
|
||||
//设置电量消耗:低电耗
|
||||
var locationPowerRequirement: Int by SharedPreference(SP_LOCATION_POWER_REQUIREMENT, Criteria.POWER_LOW)
|
||||
|
||||
//设置位置更新最小时间间隔(单位:毫秒); 默认间隔:10000毫秒,最小间隔:1000毫秒
|
||||
var locationMinInterval: Long by SharedPreference(SP_LOCATION_MIN_INTERVAL, 10000L)
|
||||
|
||||
//设置位置更新最小距离(单位:米);默认距离:0米
|
||||
var locationMinDistance: Int by SharedPreference(SP_LOCATION_MIN_DISTANCE, 0)
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,149 @@
|
||||
package com.idormy.sms.forwarder.workers
|
||||
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.Data
|
||||
import androidx.work.OneTimeWorkRequestBuilder
|
||||
import androidx.work.WorkManager
|
||||
import androidx.work.WorkerParameters
|
||||
import com.google.gson.Gson
|
||||
import com.idormy.sms.forwarder.App
|
||||
import com.idormy.sms.forwarder.database.AppDatabase
|
||||
import com.idormy.sms.forwarder.entity.MsgInfo
|
||||
import com.idormy.sms.forwarder.entity.task.BatterySetting
|
||||
import com.idormy.sms.forwarder.entity.task.ChargeSetting
|
||||
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_CHARGE
|
||||
import com.idormy.sms.forwarder.utils.TaskWorker
|
||||
import com.idormy.sms.forwarder.utils.task.TaskUtils
|
||||
import java.util.Date
|
||||
|
||||
@Suppress("PrivatePropertyName", "DEPRECATION")
|
||||
class LocationWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
|
||||
|
||||
private val TAG: String = LocationWorker::class.java.simpleName
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
|
||||
when (val conditionType = inputData.getInt(TaskWorker.conditionType, -1)) {
|
||||
|
||||
TASK_CONDITION_BATTERY -> {
|
||||
val status = inputData.getInt("status", -1)
|
||||
val levelNew = inputData.getInt("level_new", -1)
|
||||
val levelOld = inputData.getInt("level_old", -1)
|
||||
Log.d(TAG, "levelNew: $levelNew, levelOld: $levelOld")
|
||||
if (levelNew == -1 || levelOld == -1) {
|
||||
Log.d(TAG, "levelNew or levelOld is -1")
|
||||
return Result.failure()
|
||||
}
|
||||
|
||||
val taskList = AppDatabase.getInstance(App.context).taskDao().getByType(conditionType)
|
||||
for (task in taskList) {
|
||||
Log.d(TAG, "task = $task")
|
||||
|
||||
// 根据任务信息执行相应操作
|
||||
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
||||
if (conditionList.isEmpty()) {
|
||||
Log.d(TAG, "任务${task.id}:conditionList is empty")
|
||||
continue
|
||||
}
|
||||
val firstCondition = conditionList.firstOrNull()
|
||||
if (firstCondition == null) {
|
||||
Log.d(TAG, "任务${task.id}:firstCondition is null")
|
||||
continue
|
||||
}
|
||||
|
||||
val batterySetting = Gson().fromJson(firstCondition.setting, BatterySetting::class.java)
|
||||
if (batterySetting == null) {
|
||||
Log.d(TAG, "任务${task.id}:batterySetting 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
|
||||
}
|
||||
|
||||
//TODO:判断其他条件是否满足
|
||||
|
||||
//TODO: 组装消息体 && 执行具体任务
|
||||
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.name)
|
||||
val actionData = Data.Builder()
|
||||
.putLong(TaskWorker.taskId, task.id)
|
||||
.putString(TaskWorker.taskActions, task.actions)
|
||||
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
|
||||
.build()
|
||||
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
|
||||
WorkManager.getInstance().enqueue(actionRequest)
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
TASK_CONDITION_CHARGE -> {
|
||||
val statusNew = inputData.getInt("status_new", -1)
|
||||
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)
|
||||
for (task in taskList) {
|
||||
Log.d(TAG, "task = $task")
|
||||
|
||||
// 根据任务信息执行相应操作
|
||||
val conditionList = Gson().fromJson(task.conditions, Array<TaskSetting>::class.java).toMutableList()
|
||||
if (conditionList.isEmpty()) {
|
||||
Log.d(TAG, "任务${task.id}:conditionList is empty")
|
||||
continue
|
||||
}
|
||||
val firstCondition = conditionList.firstOrNull()
|
||||
if (firstCondition == null) {
|
||||
Log.d(TAG, "任务${task.id}:firstCondition is null")
|
||||
continue
|
||||
}
|
||||
|
||||
val chargeSetting = Gson().fromJson(firstCondition.setting, ChargeSetting::class.java)
|
||||
if (chargeSetting == null) {
|
||||
Log.d(TAG, "任务${task.id}:chargeSetting 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
|
||||
}
|
||||
|
||||
//TODO:判断其他条件是否满足
|
||||
|
||||
//TODO: 组装消息体 && 执行具体任务
|
||||
val msgInfo = MsgInfo("task", task.name, msg, Date(), task.description)
|
||||
val actionData = Data.Builder()
|
||||
.putLong(TaskWorker.taskId, task.id)
|
||||
.putString(TaskWorker.taskActions, task.actions)
|
||||
.putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
|
||||
.build()
|
||||
val actionRequest = OneTimeWorkRequestBuilder<ActionWorker>().setInputData(actionData).build()
|
||||
WorkManager.getInstance().enqueue(actionRequest)
|
||||
}
|
||||
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
else -> {
|
||||
Log.d(TAG, "conditionType is $conditionType")
|
||||
return Result.failure()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -347,34 +347,188 @@
|
||||
<LinearLayout
|
||||
style="@style/settingBarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_location_tag"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_location"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="RelativeOverlap" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_location_tips"
|
||||
android:textSize="9sp"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_enable_location"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/enable_location_tag_tips"
|
||||
android:textSize="9sp"
|
||||
tools:ignore="SmallSp" />
|
||||
</LinearLayout>
|
||||
|
||||
<com.xuexiang.xui.widget.button.switchbutton.SwitchButton
|
||||
android:id="@+id/sb_enable_location_tag"
|
||||
style="@style/SwitchButtonStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content" />
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/accuracy"
|
||||
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">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_accuracy_fine"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:checked="true"
|
||||
android:text="@string/accuracy_fine" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_accuracy_coarse"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/accuracy_coarse" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_accuracy_no_requirement"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/no_requirement" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/power_requirement"
|
||||
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">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_power_requirement_low"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:checked="true"
|
||||
android:text="@string/power_requirement_low" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_power_requirement_medium"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/power_requirement_medium" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_power_requirement_high"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/power_requirement_high" />
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_power_requirement_no_requirement"
|
||||
style="@style/rg_rb_style_wrap"
|
||||
android:text="@string/no_requirement" />
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
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
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/min_interval"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||
android:id="@+id/xsb_min_interval"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
app:xsb_max="120"
|
||||
app:xsb_min="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:text="@string/seconds"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:text="@string/min_distance"
|
||||
android:textSize="10sp"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="SmallSp" />
|
||||
|
||||
<com.xuexiang.xui.widget.picker.XSeekBar
|
||||
android:id="@+id/xsb_min_distance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
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/seconds"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -0,0 +1,256 @@
|
||||
<?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">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_margin="10dp"
|
||||
android:contentDescription="@string/task_leave_address"
|
||||
app:srcCompat="@drawable/auto_task_icon_leave_address"
|
||||
tools:ignore="ImageContrastCheck" />
|
||||
|
||||
<LinearLayout
|
||||
style="@style/taskBarStyle"
|
||||
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/task_leave_address"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="?attr/xui_config_color_separator_light" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_calc_type"
|
||||
style="@style/rg_style"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/config_padding_5dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_calc_type_distance"
|
||||
style="@style/rg_rb_style_match"
|
||||
android:checked="true"
|
||||
android:text="@string/calc_type_distance"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_calc_type_distance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/longitude" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_longitude"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:text="@string/latitude" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_latitude"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/btn_current_coordinates"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:text="@string/current_coordinates"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10sp"
|
||||
app:sb_color_unpressed="@color/colorPrimary"
|
||||
app:sb_ripple_color="@color/white"
|
||||
app:sb_ripple_duration="500"
|
||||
app:sb_shape_type="rectangle"
|
||||
tools:ignore="SmallSp,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/distance1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_distance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/distance2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_calc_type_address"
|
||||
style="@style/rg_rb_style_match"
|
||||
android:text="@string/calc_type_address"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_calc_type_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/keyword_leave_address_1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/keyword"
|
||||
android:importantForAutofill="no"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="RtlCompat,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/keyword_leave_address_2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</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"
|
||||
android:visibility="gone"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
256
app/src/main/res/layout/fragment_tasks_condition_to_address.xml
Normal file
256
app/src/main/res/layout/fragment_tasks_condition_to_address.xml
Normal file
@ -0,0 +1,256 @@
|
||||
<?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">
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:layout_margin="10dp"
|
||||
android:contentDescription="@string/task_to_address"
|
||||
app:srcCompat="@drawable/auto_task_icon_to_address"
|
||||
tools:ignore="ImageContrastCheck" />
|
||||
|
||||
<LinearLayout
|
||||
style="@style/taskBarStyle"
|
||||
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/task_to_address"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="?attr/xui_config_color_separator_light" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/rg_calc_type"
|
||||
style="@style/rg_style"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/config_padding_5dp">
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_calc_type_distance"
|
||||
style="@style/rg_rb_style_match"
|
||||
android:checked="true"
|
||||
android:text="@string/calc_type_distance"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_calc_type_distance"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/longitude" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_longitude"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:text="@string/latitude" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_latitude"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<com.xuexiang.xui.widget.button.shadowbutton.RippleShadowShadowButton
|
||||
android:id="@+id/btn_current_coordinates"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="5dp"
|
||||
android:gravity="center"
|
||||
android:padding="5dp"
|
||||
android:text="@string/current_coordinates"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="10sp"
|
||||
app:sb_color_unpressed="@color/colorPrimary"
|
||||
app:sb_ripple_color="@color/white"
|
||||
app:sb_ripple_duration="500"
|
||||
app:sb_shape_type="rectangle"
|
||||
tools:ignore="SmallSp,TextContrastCheck,TouchTargetSizeCheck" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/distance1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_distance"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="numberDecimal"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="LabelFor,RtlCompat,SpeakableTextPresentCheck,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/distance2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<RadioButton
|
||||
android:id="@+id/rb_calc_type_address"
|
||||
style="@style/rg_rb_style_match"
|
||||
android:text="@string/calc_type_address"
|
||||
tools:ignore="TouchTargetSizeCheck" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layout_calc_type_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="@dimen/config_margin_10dp"
|
||||
android:layout_marginEnd="@dimen/config_margin_10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/keyword_to_address_1" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="5dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="@string/keyword"
|
||||
android:importantForAutofill="no"
|
||||
android:textAlignment="center"
|
||||
tools:ignore="RtlCompat,TextContrastCheck,TextFields,TouchTargetSizeCheck" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:text="@string/keyword_to_address_2" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</RadioGroup>
|
||||
|
||||
</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"
|
||||
android:visibility="gone"
|
||||
tools:ignore="RtlSymmetry" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -895,6 +895,7 @@
|
||||
<string name="api_wol_tips">Turn on your Wake-On-LAN enabled devices remotely</string>
|
||||
<string name="api_location">Location</string>
|
||||
<string name="api_location_tips">Remote query mobile phone location</string>
|
||||
<string name="api_location_permission_tips">\'Enable Location Function\' in the \'Settings\' first.</string>
|
||||
<string name="location_longitude">Longitude:%s</string>
|
||||
<string name="location_latitude">Latitude:%s</string>
|
||||
<string name="location_address">Address:%s</string>
|
||||
@ -1085,8 +1086,19 @@
|
||||
<string name="ipv4">IPv4</string>
|
||||
<string name="ipv6">IPv6</string>
|
||||
|
||||
<string name="enable_location_tag">Enable {{LOCATION}} Tag</string>
|
||||
<string name="enable_location_tag_tips">Insert location info into forwarded msg.</string>
|
||||
<string name="enable_location">Enable Location Function</string>
|
||||
<string name="enable_location_tips">Used for locating the phone, {{LOCATION}} tag.</string>
|
||||
<string name="accuracy">Accuracy</string>
|
||||
<string name="accuracy_fine">Fine</string>
|
||||
<string name="accuracy_coarse">Coarse</string>
|
||||
<string name="no_requirement">No Requirement</string>
|
||||
<string name="power_requirement">Power Requirement</string>
|
||||
<string name="power_requirement_low">Low</string>
|
||||
<string name="power_requirement_medium">Medium</string>
|
||||
<string name="power_requirement_high">High</string>
|
||||
<string name="min_interval">Min Interval For Update</string>
|
||||
<string name="min_distance">Min Distance</string>
|
||||
<string name="meter">m</string>
|
||||
<string name="uid">UID</string>
|
||||
|
||||
<string name="task_name_status">Name/Status</string>
|
||||
@ -1116,8 +1128,8 @@
|
||||
<string name="select_task_action">Please select action</string>
|
||||
<string name="bottom_sheet_close">Close</string>
|
||||
<string name="task_cron">Cron</string>
|
||||
<string name="to_address">To Address</string>
|
||||
<string name="leave_address">Leave Address</string>
|
||||
<string name="task_to_address">To Address</string>
|
||||
<string name="task_leave_address">Leave Address</string>
|
||||
<string name="task_network">Network</string>
|
||||
<string name="task_sim">SIM Status</string>
|
||||
<string name="task_battery">Battery</string>
|
||||
@ -1206,4 +1218,27 @@
|
||||
<string name="time_after_screen_on">Time After Screen On (Minutes)</string>
|
||||
<string name="time_after_screen_on_description">%sAfter Screen On</string>
|
||||
<string name="duration_minute">%s minutes </string>
|
||||
|
||||
<string name="calc_type_distance">Calculate distance based on GPS coordinates.</string>
|
||||
<string name="calc_type_address">Determine based on address keywords.</string>
|
||||
<string name="longitude">Longitude</string>
|
||||
<string name="latitude">Latitude</string>
|
||||
<string name="distance">Distance</string>
|
||||
<string name="distance1">Create an e-fence:</string>
|
||||
<string name="distance2">m radius</string>
|
||||
<string name="current_coordinates">Current</string>
|
||||
<string name="keyword">Keyword</string>
|
||||
<string name="keyword_to_address_1">GPS address contains</string>
|
||||
<string name="keyword_to_address_2"> = arrived</string>
|
||||
<string name="keyword_leave_address_1">GPS address NOT contains</string>
|
||||
<string name="keyword_leave_address_2"> = leaved</string>
|
||||
<string name="calc_type_distance_error">Latitude and longitude or distance cannot be empty.</string>
|
||||
<string name="calc_type_address_error">Address keyword cannot be empty.</string>
|
||||
<string name="to_address_distance_description">Around longitude %s, latitude %s, within a %s-meter radius.</string>
|
||||
<string name="to_address_keyword_description">GPS address contains %s means arrival.</string>
|
||||
<string name="leave_address_distance_description">Leave around longitude %s, latitude %s, within a %s-meter radius.</string>
|
||||
<string name="leave_address_keyword_description">GPS address NOT contains %s means leaved.</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="only_one_location_condition">Only one condition, either "To Address" or "Leave Address" can be added.</string>
|
||||
</resources>
|
||||
|
@ -896,6 +896,7 @@
|
||||
<string name="api_wol_tips">远程打开启用LAN唤醒功能(Wake-On-LAN)的设备</string>
|
||||
<string name="api_location">远程找手机</string>
|
||||
<string name="api_location_tips">远程查询手机定位,方便找回手机/防止老少走丢</string>
|
||||
<string name="api_location_permission_tips">请先在【通用设置】中【启用GPS定位功能】</string>
|
||||
<string name="location_longitude">经度:%s</string>
|
||||
<string name="location_latitude">维度:%s</string>
|
||||
<string name="location_address">地址:%s</string>
|
||||
@ -1086,8 +1087,19 @@
|
||||
<string name="ipv4">IPv4</string>
|
||||
<string name="ipv6">IPv6</string>
|
||||
|
||||
<string name="enable_location_tag">启用 {{定位信息}} 标签</string>
|
||||
<string name="enable_location_tag_tips">在转发信息中插入手机的当前定位信息</string>
|
||||
<string name="enable_location">启用GPS定位功能</string>
|
||||
<string name="enable_location_tips">用于支持 查找手机、{{定位信息}}标签 功能</string>
|
||||
<string name="accuracy">位置精度</string>
|
||||
<string name="accuracy_fine">精确位置</string>
|
||||
<string name="accuracy_coarse">模糊位置</string>
|
||||
<string name="no_requirement">不要求</string>
|
||||
<string name="power_requirement">电量消耗</string>
|
||||
<string name="power_requirement_low">低</string>
|
||||
<string name="power_requirement_medium">中</string>
|
||||
<string name="power_requirement_high">高</string>
|
||||
<string name="min_interval">位置更新最小间隔</string>
|
||||
<string name="min_distance">最小距离</string>
|
||||
<string name="meter">米</string>
|
||||
<string name="uid">UID</string>
|
||||
|
||||
<string name="task_name_status">任务名称/状态</string>
|
||||
@ -1117,8 +1129,8 @@
|
||||
<string name="select_task_action">请选择动作</string>
|
||||
<string name="bottom_sheet_close">关 闭</string>
|
||||
<string name="task_cron">定时任务</string>
|
||||
<string name="to_address">到达地点</string>
|
||||
<string name="leave_address">离开地点</string>
|
||||
<string name="task_to_address">到达地点</string>
|
||||
<string name="task_leave_address">离开地点</string>
|
||||
<string name="task_network">网络状态</string>
|
||||
<string name="task_sim">SIM卡状态</string>
|
||||
<string name="task_battery">电量使用</string>
|
||||
@ -1207,4 +1219,27 @@
|
||||
<string name="time_after_screen_on">屏幕解锁后多长时间(分钟)</string>
|
||||
<string name="time_after_screen_on_description">屏幕解锁%s后</string>
|
||||
<string name="duration_minute">%s分钟</string>
|
||||
|
||||
<string name="calc_type_distance">根据GPS坐标计算距离</string>
|
||||
<string name="calc_type_address">根据地址关键字判断</string>
|
||||
<string name="longitude">经度</string>
|
||||
<string name="latitude">维度</string>
|
||||
<string name="distance">距离</string>
|
||||
<string name="distance1">以经纬度为中心,</string>
|
||||
<string name="distance2">米半径建立电子围栏</string>
|
||||
<string name="current_coordinates">当前坐标</string>
|
||||
<string name="keyword">关键字</string>
|
||||
<string name="keyword_to_address_1">当前GPS地址包含</string>
|
||||
<string name="keyword_to_address_2">则表示到达</string>
|
||||
<string name="keyword_leave_address_1">当前GPS地址不包含</string>
|
||||
<string name="keyword_leave_address_2">则表示离开</string>
|
||||
<string name="calc_type_distance_error">经纬度或距离都不能为空</string>
|
||||
<string name="calc_type_address_error">地址关键字不能为空</string>
|
||||
<string name="to_address_distance_description">进入以经度:%s,维度:%s 为中心,%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_keyword_description">离开GPS地址包含 %s 关键字区域</string>
|
||||
<string name="condition_already_exists">已经添加过该类型条件</string>
|
||||
<string name="action_already_exists">已经添加过该类型动作</string>
|
||||
<string name="only_one_location_condition">只能添加一个 进入地点 或 离开地址 类型条件</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user