diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index b3210a90..c4dddf2c 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -79,6 +79,7 @@
android:configChanges="screenSize|keyboardHidden|orientation|keyboard"
android:defaultToDeviceProtectedStorage="true"
android:directBootAware="true"
+ android:enableOnBackInvokedCallback="false"
android:fullBackupContent="@xml/backup_descriptor"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
@@ -222,19 +223,13 @@
android:value="640" />
-
-
-
+
+
+
+
+
-
+
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/App.kt b/app/src/main/java/com/idormy/sms/forwarder/App.kt
index 8ef5b6af..9c1a3510 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/App.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/App.kt
@@ -19,16 +19,14 @@ import com.idormy.sms.forwarder.core.Core
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.database.repository.*
import com.idormy.sms.forwarder.entity.SimInfo
+import com.idormy.sms.forwarder.receiver.BatteryReceiver
import com.idormy.sms.forwarder.receiver.CactusReceiver
-import com.idormy.sms.forwarder.service.BatteryService
import com.idormy.sms.forwarder.service.ForegroundService
-import com.idormy.sms.forwarder.service.HttpService
-import com.idormy.sms.forwarder.service.NetworkStateService
+import com.idormy.sms.forwarder.service.HttpServerService
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.task.AlarmUtils
import com.idormy.sms.forwarder.utils.tinker.TinkerLoadLibrary
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
@@ -121,23 +119,18 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
startService(serviceIntent)
}
- //网络状态监听
- Intent(this, NetworkStateService::class.java).also {
- startService(it)
- }
-
- //电池状态监听
- Intent(this, BatteryService::class.java).also {
- startService(it)
- }
-
//启动HttpServer
if (HttpServerUtils.enableServerAutorun) {
- Intent(this, HttpService::class.java).also {
+ Intent(this, HttpServerService::class.java).also {
startService(it)
}
}
+ //监听电量&充电状态变化
+ val batteryReceiver = BatteryReceiver()
+ val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED)
+ registerReceiver(batteryReceiver, filter)
+
//Cactus 集成双进程前台服务,JobScheduler,onePix(一像素),WorkManager,无声音乐
if (SettingUtils.enableCactus) {
//注册广播监听器
@@ -207,10 +200,6 @@ class App : Application(), CactusCallback, Configuration.Provider by Core {
XUpdateInit.init(this)
// 运营统计数据
UMengInit.init(this)
- // 定时任务初始化
- AlarmUtils.initialize(this)
- // 三方时间库初始化
- //AndroidThreeTen.init(this)
}
@SuppressLint("CheckResult")
diff --git a/app/src/main/java/com/idormy/sms/forwarder/database/dao/TaskDao.kt b/app/src/main/java/com/idormy/sms/forwarder/database/dao/TaskDao.kt
index 6a64e999..68f64c92 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/database/dao/TaskDao.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/database/dao/TaskDao.kt
@@ -37,7 +37,7 @@ interface TaskDao {
@RawQuery(observedEntities = [Task::class])
fun getAllRaw(query: SupportSQLiteQuery): List
- @Query("SELECT * FROM Task WHERE type = :taskType")
+ @Query("SELECT * FROM Task WHERE status = 1 AND type = :taskType")
fun getByType(taskType: Int): List
//TODO:根据条件查询,不推荐使用
diff --git a/app/src/main/java/com/idormy/sms/forwarder/entity/BatteryInfo.kt b/app/src/main/java/com/idormy/sms/forwarder/entity/BatteryInfo.kt
index 4b2425d3..2940dac3 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/entity/BatteryInfo.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/entity/BatteryInfo.kt
@@ -4,6 +4,7 @@ import com.idormy.sms.forwarder.R
import com.xuexiang.xui.utils.ResUtils
import java.io.Serializable
+@Suppress("DEPRECATION")
data class BatteryInfo(
var level: String = "",
var scale: String = "",
diff --git a/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt b/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt
index 43d6af63..d620bf4b 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/entity/MsgInfo.kt
@@ -5,12 +5,14 @@ import android.text.TextUtils
import android.util.Log
import com.idormy.sms.forwarder.App
import com.idormy.sms.forwarder.R
+import com.idormy.sms.forwarder.utils.BatteryUtils
import com.idormy.sms.forwarder.utils.CALL_TYPE_MAP
import com.idormy.sms.forwarder.utils.HttpServerUtils
import com.idormy.sms.forwarder.utils.SettingUtils
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.enableSmsTemplate
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.extraDeviceMark
import com.idormy.sms.forwarder.utils.SettingUtils.Companion.smsTemplate
+import com.idormy.sms.forwarder.utils.task.TaskUtils
import com.xuexiang.xui.utils.ResUtils.getString
import com.xuexiang.xutil.app.AppUtils
import java.io.Serializable
@@ -109,6 +111,10 @@ data class MsgInfo(
.replace(getString(R.string.tag_device_name), deviceMark)
.replace(getString(R.string.tag_app_version), versionName)
.replace(getString(R.string.tag_call_type), CALL_TYPE_MAP[callType.toString()] ?: getString(R.string.unknown_call))
+ .replace(getString(R.string.tag_battery_pct), TaskUtils.batteryPct.toString())
+ .replace(getString(R.string.tag_battery_status), BatteryUtils.getStatus(TaskUtils.batteryStatus))
+ .replace(getString(R.string.tag_battery_plugged), BatteryUtils.getPlugged(TaskUtils.batteryPlugged))
+ .replace(getString(R.string.tag_battery_info), TaskUtils.batteryInfo)
.trim()
return replaceLocationTag(replaceAppName(regexReplace(smsVoForSend, regexReplace), from))
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/entity/task/BatterySetting.kt b/app/src/main/java/com/idormy/sms/forwarder/entity/task/BatterySetting.kt
index 31ff9dd2..0880c65a 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/entity/task/BatterySetting.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/entity/task/BatterySetting.kt
@@ -2,6 +2,7 @@ package com.idormy.sms.forwarder.entity.task
import android.os.BatteryManager
import com.idormy.sms.forwarder.R
+import com.xuexiang.xutil.resource.ResUtils.getString
import java.io.Serializable
data class BatterySetting(
@@ -19,4 +20,30 @@ data class BatterySetting(
else -> R.id.rb_battery_charging
}
}
+
+ fun getMsg(statusNew: Int, levelNew: Int, levelOld: Int, batteryInfo: String): String {
+
+ when (statusNew) {
+ BatteryManager.BATTERY_STATUS_CHARGING, BatteryManager.BATTERY_STATUS_FULL -> { //充电中
+ if (status != BatteryManager.BATTERY_STATUS_CHARGING) return ""
+ if (keepReminding && levelOld < levelNew && levelNew >= levelMax) {
+ return String.format(getString(R.string.over_level_max), batteryInfo)
+ } else if (!keepReminding && levelOld < levelNew && levelNew == levelMax) {
+ return String.format(getString(R.string.reach_level_max), batteryInfo)
+ }
+ }
+
+ BatteryManager.BATTERY_STATUS_DISCHARGING, BatteryManager.BATTERY_STATUS_NOT_CHARGING -> { //放电中
+ if (status != BatteryManager.BATTERY_STATUS_DISCHARGING) return ""
+ if (keepReminding && levelOld > levelNew && levelNew <= levelMin) {
+ return String.format(getString(R.string.below_level_min), batteryInfo)
+ } else if (!keepReminding && levelOld > levelNew && levelNew == levelMin) {
+ return String.format(getString(R.string.reach_level_min), batteryInfo)
+ }
+ }
+ }
+
+ return ""
+
+ }
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/entity/task/ChargeSetting.kt b/app/src/main/java/com/idormy/sms/forwarder/entity/task/ChargeSetting.kt
index 1f0b29a8..0732a3b3 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/entity/task/ChargeSetting.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/entity/task/ChargeSetting.kt
@@ -71,4 +71,11 @@ data class ChargeSetting(
else -> R.id.rb_plugged_unknown
}
}
+
+ fun getMsg(statusNew: Int, statusOld: Int, pluggedNew: Int, pluggedOld: Int, batteryInfo: String): String {
+
+ if (statusNew != status || pluggedNew != plugged) return ""
+
+ return getString(R.string.battery_status_changed) + getStatusStr(statusOld) + "(" + getPluggedStr(pluggedOld) + ") → " + getStatusStr(statusNew) + "(" + getPluggedStr(pluggedNew) + ")" + batteryInfo
+ }
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
index 30928d50..002b9a0e 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/ServerFragment.kt
@@ -22,7 +22,7 @@ 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.HttpService
+import com.idormy.sms.forwarder.service.HttpServerService
import com.idormy.sms.forwarder.utils.*
import com.xuexiang.xaop.annotation.SingleClick
import com.xuexiang.xpage.annotation.Page
@@ -241,9 +241,9 @@ class ServerFragment : BaseFragment(), View.OnClickListe
binding!!.sbApiLocation.isChecked = HttpServerUtils.enableApiLocation
binding!!.sbApiLocation.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
HttpServerUtils.enableApiLocation = isChecked
- if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
+ if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpServerService")) {
Log.d("ServerFragment", "onClick: 重启服务")
- Intent(appContext, HttpService::class.java).also {
+ Intent(appContext, HttpServerService::class.java).also {
appContext?.stopService(it)
Thread.sleep(500)
appContext?.startService(it)
@@ -272,8 +272,8 @@ class ServerFragment : BaseFragment(), View.OnClickListe
checkCallPermission()
checkContactsPermission()
checkLocationPermission()
- Intent(appContext, HttpService::class.java).also {
- if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
+ Intent(appContext, HttpServerService::class.java).also {
+ if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpServerService")) {
appContext?.stopService(it)
} else {
appContext?.startService(it)
@@ -348,8 +348,8 @@ class ServerFragment : BaseFragment(), View.OnClickListe
HttpServerUtils.serverWebPath = webPath
XToastUtils.info(getString(R.string.restarting_httpserver))
- Intent(appContext, HttpService::class.java).also {
- if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
+ Intent(appContext, HttpServerService::class.java).also {
+ if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpServerService")) {
appContext?.stopService(it)
Thread.sleep(500)
appContext?.startService(it)
@@ -381,7 +381,7 @@ class ServerFragment : BaseFragment(), View.OnClickListe
//刷新按钮
private fun refreshButtonText() {
- if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
+ if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpServerService")) {
binding!!.btnToggleServer.text = resources.getText(R.string.stop_server)
binding!!.ivCopy.visibility = View.VISIBLE
try {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt
index b451742f..c45561d1 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/SettingsFragment.kt
@@ -32,7 +32,7 @@ import com.idormy.sms.forwarder.adapter.spinner.AppListSpinnerAdapter
import com.idormy.sms.forwarder.core.BaseFragment
import com.idormy.sms.forwarder.databinding.FragmentSettingsBinding
import com.idormy.sms.forwarder.entity.SimInfo
-import com.idormy.sms.forwarder.receiver.BootReceiver
+import com.idormy.sms.forwarder.receiver.BootCompletedReceiver
import com.idormy.sms.forwarder.service.ForegroundService
import com.idormy.sms.forwarder.utils.*
import com.idormy.sms.forwarder.workers.LoadAppListWorker
@@ -44,16 +44,12 @@ import com.xuexiang.xui.widget.button.SmoothCheckBox
import com.xuexiang.xui.widget.button.switchbutton.SwitchButton
import com.xuexiang.xui.widget.dialog.materialdialog.DialogAction
import com.xuexiang.xui.widget.dialog.materialdialog.MaterialDialog
-import com.xuexiang.xui.widget.picker.XRangeSlider
-import com.xuexiang.xui.widget.picker.XRangeSlider.OnRangeSliderListener
import com.xuexiang.xui.widget.picker.XSeekBar
import com.xuexiang.xui.widget.picker.widget.builder.OptionsPickerBuilder
-import com.xuexiang.xui.widget.picker.widget.builder.TimePickerBuilder
import com.xuexiang.xui.widget.picker.widget.listener.OnOptionsSelectListener
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.XUtil.getPackageManager
import com.xuexiang.xutil.app.AppUtils.getAppPackageName
-import com.xuexiang.xutil.data.DateUtils
import kotlinx.coroutines.*
import java.util.*
@@ -125,15 +121,6 @@ class SettingsFragment : BaseFragment(), View.OnClickL
//监听网络状态变化
switchNetworkStateReceiver(binding!!.sbNetworkStateReceiver)
- //监听电池状态变化
- switchBatteryReceiver(binding!!.sbBatteryReceiver)
- //电量预警
- editBatteryLevelAlarm(binding!!.xrsBatteryLevelAlarm, binding!!.scbBatteryLevelAlarmOnce)
- //定时推送电池状态
- switchBatteryCron(binding!!.sbBatteryCron)
- //设置推送电池状态时机
- editBatteryCronTiming(binding!!.etBatteryCronStartTime, binding!!.etBatteryCronInterval)
-
//开机启动
checkWithReboot(binding!!.sbWithReboot, binding!!.tvAutoStartup)
//忽略电池优化设置
@@ -629,85 +616,6 @@ class SettingsFragment : BaseFragment(), View.OnClickL
}
}
- //监听电池状态变化
- @SuppressLint("UseSwitchCompatOrMaterialCode")
- fun switchBatteryReceiver(sbBatteryReceiver: SwitchButton) {
- sbBatteryReceiver.isChecked = SettingUtils.enableBatteryReceiver
- sbBatteryReceiver.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
- SettingUtils.enableBatteryReceiver = isChecked
- }
- }
-
- //设置低电量报警
- private fun editBatteryLevelAlarm(
- xrsBatteryLevelAlarm: XRangeSlider, scbBatteryLevelAlarmOnce: SmoothCheckBox
- ) {
- xrsBatteryLevelAlarm.setStartingMinMax(
- SettingUtils.batteryLevelMin, SettingUtils.batteryLevelMax
- )
- xrsBatteryLevelAlarm.setOnRangeSliderListener(object : OnRangeSliderListener {
- override fun onMaxChanged(slider: XRangeSlider, maxValue: Int) {
- //SettingUtils.batteryLevelMin = slider.selectedMin
- SettingUtils.batteryLevelMax = slider.selectedMax
- }
-
- override fun onMinChanged(slider: XRangeSlider, minValue: Int) {
- SettingUtils.batteryLevelMin = slider.selectedMin
- //SettingUtils.batteryLevelMax = slider.selectedMax
- }
- })
-
- scbBatteryLevelAlarmOnce.isChecked = SettingUtils.batteryLevelOnce
- scbBatteryLevelAlarmOnce.setOnCheckedChangeListener { _: SmoothCheckBox, isChecked: Boolean ->
- SettingUtils.batteryLevelOnce = isChecked
- if (isChecked && 0 == SettingUtils.batteryLevelMin && 0 == SettingUtils.batteryLevelMax) {
- XToastUtils.warning(R.string.tips_battery_level_alarm_once)
- }
- }
- }
-
- //定时推送电池状态
- @SuppressLint("UseSwitchCompatOrMaterialCode")
- fun switchBatteryCron(sbBatteryCron: SwitchButton) {
- sbBatteryCron.isChecked = SettingUtils.enableBatteryCron
- binding!!.layoutBatteryCron.visibility = if (SettingUtils.enableBatteryCron) View.VISIBLE else View.GONE
- sbBatteryCron.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
- binding!!.layoutBatteryCron.visibility = if (isChecked) View.VISIBLE else View.GONE
- SettingUtils.enableBatteryCron = isChecked
- }
- }
-
- //设置推送电池状态时机
- private fun editBatteryCronTiming(
- etBatteryCronStartTime: EditText, etBatteryCronInterval: EditText
- ) {
- etBatteryCronStartTime.setText(SettingUtils.batteryCronStartTime)
- etBatteryCronStartTime.setOnClickListener {
- val calendar = Calendar.getInstance()
- calendar.time = DateUtils.getNowDate()
- val mTimePicker = TimePickerBuilder(context) { date: Date?, _: View? ->
- etBatteryCronStartTime.setText(DateUtils.date2String(date, DateUtils.HHmm.get()))
- }.setType(false, false, false, true, true, false).setTitleText(getString(R.string.time_picker)).setSubmitText(getString(R.string.ok)).setCancelText(getString(R.string.cancel)).setDate(calendar).build()
- mTimePicker.show()
- }
-
- etBatteryCronInterval.setText(SettingUtils.batteryCronInterval.toString())
- etBatteryCronInterval.addTextChangedListener(object : TextWatcher {
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
- override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
- override fun afterTextChanged(s: Editable) {
- val interval = etBatteryCronInterval.text.toString().trim()
- if (interval.isNotEmpty() && interval.toInt() > 0) {
- SettingUtils.batteryCronInterval = interval.toInt()
- //TODO:BatteryReportCronTask
- //BatteryReportCronTask.getSingleton().updateTimer()
- } else {
- SettingUtils.batteryCronInterval = 60
- }
- }
- })
- }
-
//开机启动
private fun checkWithReboot(
@SuppressLint("UseSwitchCompatOrMaterialCode") sbWithReboot: SwitchButton, tvAutoStartup: TextView
@@ -715,7 +623,7 @@ class SettingsFragment : BaseFragment(), View.OnClickL
tvAutoStartup.text = getAutoStartTips()
//获取组件
- val cm = ComponentName(getAppPackageName(), BootReceiver::class.java.name)
+ val cm = ComponentName(getAppPackageName(), BootCompletedReceiver::class.java.name)
val pm: PackageManager = getPackageManager()
val state = pm.getComponentEnabledSetting(cm)
sbWithReboot.isChecked = !(state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/fragment/TasksEditFragment.kt b/app/src/main/java/com/idormy/sms/forwarder/fragment/TasksEditFragment.kt
index 51d7a74b..e816a7c7 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/fragment/TasksEditFragment.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/fragment/TasksEditFragment.kt
@@ -335,9 +335,6 @@ class TasksEditFragment : BaseFragment(), View.OnClic
//定时任务
TASK_CONDITION_CRON -> {
//取消旧任务的定时器 & 设置新的定时器
- //AlarmUtils.cancelAlarm(task)
- //AlarmUtils.scheduleAlarm(task)
-
CronJobScheduler.cancelTask(task.id)
CronJobScheduler.scheduleTask(task)
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/AlarmReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/AlarmReceiver.kt
deleted file mode 100644
index 856c7e33..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/receiver/AlarmReceiver.kt
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.idormy.sms.forwarder.receiver
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.util.Log
-import com.google.gson.Gson
-import com.idormy.sms.forwarder.App
-import com.idormy.sms.forwarder.database.AppDatabase
-import com.idormy.sms.forwarder.database.entity.Task
-import com.idormy.sms.forwarder.entity.task.CronSetting
-import com.idormy.sms.forwarder.entity.task.TaskSetting
-import com.idormy.sms.forwarder.utils.task.AlarmUtils
-import gatewayapps.crondroid.CronExpression
-import java.util.Date
-
-@Suppress("PropertyName", "DEPRECATION")
-class AlarmReceiver : BroadcastReceiver() {
-
- val TAG: String = AlarmReceiver::class.java.simpleName
-
- override fun onReceive(context: Context, intent: Intent) {
- val task = intent.getParcelableExtra("TASK")
- if (task == null) {
- Log.d(TAG, "onReceive task is null")
- return
- }
-
- Log.d(TAG, "onReceive task $task")
- Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
- try {
- //取消旧任务的定时器
- AlarmUtils.cancelAlarm(task)
-
- // 根据任务信息执行相应操作
- val conditionList = Gson().fromJson(task.conditions, Array::class.java).toMutableList()
- if (conditionList.isEmpty()) {
- Log.d(TAG, "onReceive conditionList is empty")
- return
- }
- val firstCondition = conditionList.firstOrNull()
- if (firstCondition == null) {
- Log.d(TAG, "onReceive firstCondition is null")
- return
- }
- val cronSetting = Gson().fromJson(firstCondition.setting, CronSetting::class.java)
- if (cronSetting == null) {
- Log.d(TAG, "onReceive cronSetting is null")
- return
- }
- // 更新任务的上次执行时间和下次执行时间
- val cronExpression = CronExpression(cronSetting.expression)
- task.lastExecTime = Date()
- task.nextExecTime = cronExpression.getNextValidTimeAfter(task.lastExecTime)
- Log.d(TAG, "lastExecTime = ${task.lastExecTime}, nextExecTime = ${task.nextExecTime}")
- // 自动禁用任务
- if (task.nextExecTime <= task.lastExecTime) {
- task.status = 0
- }
- // 更新任务信息
- AppDatabase.getInstance(App.context).taskDao().update(task)
- if (task.status == 0) {
- Log.d(TAG, "onReceive task is disabled")
- return
- }
- //设置新的定时器
- AlarmUtils.scheduleAlarm(task)
- } catch (e: Exception) {
- Log.e(TAG, "onReceive error $e")
- }
-
- }
-}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/BatteryReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/BatteryReceiver.kt
new file mode 100644
index 00000000..cdc7ccff
--- /dev/null
+++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/BatteryReceiver.kt
@@ -0,0 +1,79 @@
+package com.idormy.sms.forwarder.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.os.BatteryManager
+import android.util.Log
+import androidx.work.OneTimeWorkRequestBuilder
+import androidx.work.WorkManager
+import androidx.work.workDataOf
+import com.idormy.sms.forwarder.utils.BatteryUtils
+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 com.idormy.sms.forwarder.workers.BatteryWorker
+
+@Suppress("PropertyName")
+class BatteryReceiver : BroadcastReceiver() {
+
+ val TAG: String = BatteryReceiver::class.java.simpleName
+
+ override fun onReceive(context: Context?, intent: Intent?) {
+
+ if (context == null || intent?.action != Intent.ACTION_BATTERY_CHANGED) return
+
+ val batteryInfo = BatteryUtils.getBatteryInfo(intent).toString()
+ TaskUtils.batteryInfo = batteryInfo
+
+ val levelNew = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0)
+ val levelOld = TaskUtils.batteryLevel
+ val isLevelChanged = levelNew != levelOld
+ TaskUtils.batteryLevel = levelNew
+
+ val scale: Int = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100)
+ TaskUtils.batteryPct = levelNew.toFloat() / scale.toFloat() * 100
+
+ val pluggedNew: Int = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1)
+ val pluggedOld = TaskUtils.batteryPlugged
+ val isPluggedChanged = pluggedNew != pluggedOld
+ TaskUtils.batteryPlugged = pluggedNew
+
+ val statusNew: Int = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
+ val statusOld = TaskUtils.batteryStatus
+ val isStatusChanged = statusNew != statusOld
+ TaskUtils.batteryStatus = statusNew
+
+ //电量改变
+ if (isLevelChanged) {
+ Log.d(TAG, "电量改变")
+ val request = OneTimeWorkRequestBuilder().setInputData(
+ workDataOf(
+ TaskWorker.conditionType to TASK_CONDITION_BATTERY,
+ "status" to statusNew,
+ "level_new" to levelNew,
+ "level_old" to levelOld,
+ )
+ ).build()
+ WorkManager.getInstance(context).enqueue(request)
+ }
+
+ //充电状态改变
+ if (isPluggedChanged || isStatusChanged) {
+ Log.d(TAG, "充电状态改变")
+ val request = OneTimeWorkRequestBuilder().setInputData(
+ workDataOf(
+ TaskWorker.conditionType to TASK_CONDITION_CHARGE,
+ "status_new" to statusNew,
+ "status_old" to statusOld,
+ "plugged_new" to pluggedNew,
+ "plugged_old" to pluggedOld,
+ )
+ ).build()
+ WorkManager.getInstance(context).enqueue(request)
+ }
+
+ }
+
+}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/BootCompletedReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/BootCompletedReceiver.kt
new file mode 100644
index 00000000..ae76be40
--- /dev/null
+++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/BootCompletedReceiver.kt
@@ -0,0 +1,28 @@
+package com.idormy.sms.forwarder.receiver
+
+import android.content.BroadcastReceiver
+import android.content.Context
+import android.content.Intent
+import android.util.Log
+import com.idormy.sms.forwarder.activity.SplashActivity
+
+@Suppress("PropertyName")
+class BootCompletedReceiver : BroadcastReceiver() {
+
+ val TAG: String = BootCompletedReceiver::class.java.simpleName
+
+ override fun onReceive(context: Context, intent: Intent?) {
+
+ if (intent?.action != Intent.ACTION_BOOT_COMPLETED && intent?.action != Intent.ACTION_LOCKED_BOOT_COMPLETED) return
+
+ try {
+ Log.d(TAG, "强制重启APP一次")
+ val intent1 = Intent(context, SplashActivity::class.java)
+ intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ context.startActivity(intent1)
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/BootReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/BootReceiver.kt
deleted file mode 100644
index 842e522b..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/receiver/BootReceiver.kt
+++ /dev/null
@@ -1,28 +0,0 @@
-package com.idormy.sms.forwarder.receiver
-
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.util.Log
-import com.idormy.sms.forwarder.activity.SplashActivity
-
-@Suppress("PropertyName")
-class BootReceiver : BroadcastReceiver() {
-
- val TAG: String = BootReceiver::class.java.simpleName
-
- override fun onReceive(context: Context, intent: Intent?) {
- val receiveAction: String? = intent?.action
- Log.d(TAG, "onReceive intent $receiveAction")
- if (receiveAction == Intent.ACTION_BOOT_COMPLETED || receiveAction == Intent.ACTION_LOCKED_BOOT_COMPLETED) {
- try {
- Log.d(TAG, "强制重启APP一次")
- val intent1 = Intent(context, SplashActivity::class.java)
- intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
- context.startActivity(intent1)
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/SimStateReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/SimStateReceiver.kt
index f618e774..8de3d445 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/receiver/SimStateReceiver.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/SimStateReceiver.kt
@@ -22,7 +22,7 @@ import java.util.Date
@Suppress("PrivatePropertyName", "UNUSED_PARAMETER")
class SimStateReceiver : BroadcastReceiver() {
- private var TAG = "SimStateReceiver"
+ private var TAG = SimStateReceiver::class.java.simpleName
override fun onReceive(context: Context, intent: Intent) {
//纯客户端模式
diff --git a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
index ae32f046..94c7b511 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/receiver/SmsReceiver.kt
@@ -23,7 +23,7 @@ import java.util.Date
@Suppress("PrivatePropertyName")
class SmsReceiver : BroadcastReceiver() {
- private var TAG = "SmsReceiver"
+ private var TAG = SmsReceiver::class.java.simpleName
private var from = ""
private var msg = ""
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt
deleted file mode 100644
index eaf4f18a..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt
+++ /dev/null
@@ -1,172 +0,0 @@
-package com.idormy.sms.forwarder.service
-
-import android.annotation.SuppressLint
-import android.app.Service
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.os.IBinder
-import android.text.TextUtils
-import android.util.Log
-import androidx.work.OneTimeWorkRequestBuilder
-import androidx.work.WorkManager
-import androidx.work.workDataOf
-import com.google.gson.Gson
-import com.idormy.sms.forwarder.App
-import com.idormy.sms.forwarder.R
-import com.idormy.sms.forwarder.core.Core
-import com.idormy.sms.forwarder.database.AppDatabase
-import com.idormy.sms.forwarder.entity.MsgInfo
-import com.idormy.sms.forwarder.utils.BatteryUtils
-import com.idormy.sms.forwarder.utils.CacheUtils
-import com.idormy.sms.forwarder.utils.HistoryUtils
-import com.idormy.sms.forwarder.utils.SettingUtils
-import com.idormy.sms.forwarder.utils.Worker
-import com.idormy.sms.forwarder.workers.SendWorker
-import com.xuexiang.xutil.file.FileUtils
-import frpclib.Frpclib
-import kotlinx.coroutines.DelicateCoroutinesApi
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.async
-import java.util.*
-
-@OptIn(DelicateCoroutinesApi::class)
-@Suppress("DeferredResultUnused")
-class BatteryService : Service() {
-
- override fun onBind(intent: Intent): IBinder? {
- return null
- }
-
- override fun onCreate() {
- super.onCreate()
- Log.i(TAG, "onCreate--------------")
-
- //纯客户端模式
- //if (SettingUtils.enablePureClientMode) return
-
- val batteryFilter = IntentFilter()
- batteryFilter.addAction(Intent.ACTION_BATTERY_CHANGED)
- registerReceiver(batteryReceiver, batteryFilter)
- }
-
- override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
- Log.i(TAG, "onStartCommand--------------")
- return START_STICKY
- }
-
- override fun onDestroy() {
- Log.i(TAG, "onDestroy--------------")
- super.onDestroy()
-
- //纯客户端模式
- //if (SettingUtils.enablePureClientMode) return
-
- unregisterReceiver(batteryReceiver)
- }
-
- // 接收电池信息更新的广播
- private val batteryReceiver: BroadcastReceiver = object : BroadcastReceiver() {
- @SuppressLint("DefaultLocale")
- override fun onReceive(context: Context, intent: Intent) {
-
- if (intent.action != Intent.ACTION_BATTERY_CHANGED) return
-
- //自动删除N天前的转发记录
- if (SettingUtils.autoCleanLogsDays > 0) {
- Log.d(TAG, "自动删除N天前的转发记录")
- val cal = Calendar.getInstance()
- cal.add(Calendar.DAY_OF_MONTH, 0 - SettingUtils.autoCleanLogsDays)
- Core.msg.deleteTimeAgo(cal.timeInMillis)
-
- //清理缓存
- HistoryUtils.clearPreference()
- CacheUtils.clearAllCache(context)
- }
-
- //守护自启动的Frpc
- if (FileUtils.isFileExists(filesDir.absolutePath + "/libs/libgojni.so")) {
- GlobalScope.async(Dispatchers.IO) {
- val frpcList = AppDatabase.getInstance(App.context).frpcDao().getAutorun()
-
- if (frpcList.isEmpty()) {
- Log.d(TAG, "没有自启动的Frpc")
- return@async
- }
-
- for (frpc in frpcList) {
- if (!Frpclib.isRunning(frpc.uid)) {
- val error = Frpclib.runContent(frpc.uid, frpc.config)
- if (!TextUtils.isEmpty(error)) {
- Log.e(TAG, error)
- }
- }
- }
- }
- }
-
- //电量发生变化
- val levelCur: Int = intent.getIntExtra("level", 0)
- val levelPre: Int = SettingUtils.batteryLevelCurrent
- if (levelCur != levelPre) {
- var msg: String = BatteryUtils.getBatteryInfo(intent).toString()
- SettingUtils.batteryLevelCurrent = levelCur
- val levelMin: Int = SettingUtils.batteryLevelMin
- val levelMax: Int = SettingUtils.batteryLevelMax
- if (SettingUtils.batteryLevelOnce && levelMin > 0 && levelPre > levelCur && levelCur <= levelMin) { //电量下降到下限
- msg = String.format(getString(R.string.below_level_min), msg)
- sendMessage(context, msg)
- return
- } else if (SettingUtils.batteryLevelOnce && levelMax > 0 && levelPre < levelCur && levelCur >= levelMax) { //电量上升到上限
- msg = String.format(getString(R.string.over_level_max), msg)
- sendMessage(context, msg)
- return
- } else if (!SettingUtils.batteryLevelOnce && levelMin > 0 && levelPre > levelCur && levelCur == levelMin) { //电量下降到下限
- msg = String.format(getString(R.string.reach_level_min), msg)
- sendMessage(context, msg)
- return
- } else if (!SettingUtils.batteryLevelOnce && levelMax > 0 && levelPre < levelCur && levelCur == levelMax) { //电量上升到上限
- msg = String.format(getString(R.string.reach_level_max), msg)
- sendMessage(context, msg)
- return
- }
- }
-
- //充电状态改变
- val status: Int = intent.getIntExtra("status", 0)
- if (SettingUtils.enableBatteryReceiver) {
- val oldStatus: Int = SettingUtils.batteryStatus
- if (status != oldStatus) {
- var msg: String = BatteryUtils.getBatteryInfo(intent).toString()
- SettingUtils.batteryStatus = status
- msg = getString(R.string.battery_status_changed) + BatteryUtils.getStatus(
- oldStatus
- ) + " → " + BatteryUtils.getStatus(status) + msg
- sendMessage(context, msg)
- }
- }
- }
- }
-
- //发送信息
- private fun sendMessage(context: Context, msg: String) {
- Log.i(TAG, msg)
- try {
- val msgInfo = MsgInfo("app", "88888888", msg, Date(), getString(R.string.battery_status_monitor), -1)
- val request = OneTimeWorkRequestBuilder().setInputData(
- workDataOf(
- Worker.sendMsgInfo to Gson().toJson(msgInfo),
- )
- ).build()
- WorkManager.getInstance(context).enqueue(request)
- } catch (e: Exception) {
- Log.e(TAG, "getLog e:" + e.message)
- }
- }
-
- companion object {
- private const val TAG = "BatteryReceiver"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt
index e32f1953..d12bb923 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/service/ForegroundService.kt
@@ -49,7 +49,7 @@ import java.util.Date
@Suppress("PrivatePropertyName", "DeferredResultUnused", "OPT_IN_USAGE", "DEPRECATION", "LiftReturnOrAssignment")
class ForegroundService : Service() {
- private val TAG: String = "ForegroundService"
+ private val TAG: String = ForegroundService::class.java.simpleName
private var notificationManager: NotificationManager? = null
private val compositeDisposable = CompositeDisposable()
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/HttpServerService.kt
similarity index 88%
rename from app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt
rename to app/src/main/java/com/idormy/sms/forwarder/service/HttpServerService.kt
index cd8347a1..6ac713f2 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/service/HttpService.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/service/HttpServerService.kt
@@ -9,13 +9,12 @@ import com.idormy.sms.forwarder.utils.HTTP_SERVER_TIME_OUT
import com.idormy.sms.forwarder.utils.SettingUtils
import com.yanzhenjie.andserver.AndServer
import com.yanzhenjie.andserver.Server
-import java.util.*
import java.util.concurrent.TimeUnit
@Suppress("PrivatePropertyName")
-class HttpService : Service(), Server.ServerListener {
+class HttpServerService : Service(), Server.ServerListener {
- private val TAG: String = "HttpService"
+ private val TAG: String = HttpServerService::class.java.simpleName
private val server by lazy {
AndServer.webServer(this).port(HTTP_SERVER_PORT).listener(this).timeout(HTTP_SERVER_TIME_OUT, TimeUnit.SECONDS).build()
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt
deleted file mode 100644
index 3f12af40..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt
+++ /dev/null
@@ -1,265 +0,0 @@
-package com.idormy.sms.forwarder.service
-
-import android.annotation.SuppressLint
-import android.app.Service
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.net.ConnectivityManager
-import android.net.wifi.WifiInfo
-import android.net.wifi.WifiManager
-import android.os.IBinder
-import android.util.Log
-import androidx.work.OneTimeWorkRequestBuilder
-import androidx.work.WorkManager
-import androidx.work.workDataOf
-import com.google.gson.Gson
-import com.idormy.sms.forwarder.R
-import com.idormy.sms.forwarder.entity.MsgInfo
-import com.idormy.sms.forwarder.utils.CommonUtils
-import com.idormy.sms.forwarder.utils.SettingUtils
-import com.idormy.sms.forwarder.utils.Worker
-import com.idormy.sms.forwarder.workers.SendWorker
-import com.xuexiang.xutil.app.ServiceUtils
-import com.xuexiang.xutil.net.NetworkUtils
-import java.util.*
-
-import android.os.Build
-import android.telephony.SubscriptionInfo
-import android.telephony.SubscriptionManager
-import androidx.annotation.RequiresApi
-import com.idormy.sms.forwarder.App
-import com.idormy.sms.forwarder.utils.PhoneUtils
-import java.lang.reflect.Method
-
-@Suppress("DEPRECATION")
-class NetworkStateService : Service() {
-
- override fun onBind(intent: Intent): IBinder? {
- return null
- }
-
- override fun onCreate() {
- super.onCreate()
- Log.i(TAG, "onCreate--------------")
-
- //纯客户端模式
- //if (SettingUtils.enablePureClientMode) return
-
- val networkStateFilter = IntentFilter()
- networkStateFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
- registerReceiver(networkStateReceiver, networkStateFilter)
- }
-
- override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
- Log.i(TAG, "onStartCommand--------------")
- return START_STICKY
- }
-
- override fun onDestroy() {
- Log.i(TAG, "onDestroy--------------")
- super.onDestroy()
-
- //纯客户端模式
- //if (SettingUtils.enablePureClientMode) return
-
- unregisterReceiver(networkStateReceiver)
- }
-
- // 接收网络状态更新的广播
- private val networkStateReceiver: BroadcastReceiver = object : BroadcastReceiver() {
- @RequiresApi(Build.VERSION_CODES.Q)
- @SuppressLint("DefaultLocale")
- override fun onReceive(context: Context, intent: Intent) {
-
- if (intent.action != ConnectivityManager.CONNECTIVITY_ACTION) return
-
- if (!SettingUtils.enableNetworkStateReceiver) return
-
- Log.i(TAG, "网络状态已经改变,延时2秒后获取信息")
- Thread.sleep(2000)
-
- val msg = StringBuilder()
-
- //枚举网络状态 NET_NO:没有网络 , NET_2G:2g网络 , NET_3G:3g网络, NET_4G:4g网络, NET_5G:5g网络, NET_WIFI:wifi, NET_ETHERNET:有线网络, NET_UNKNOWN:未知网络
- val netStateType = NetworkUtils.getNetStateType()
- Log.d(TAG, "netStateType: $netStateType")
- val netStateTypeName = when (netStateType) {
- NetworkUtils.NetState.NET_NO -> getString(R.string.no_network)
- NetworkUtils.NetState.NET_2G -> getString(R.string.net_2g)
- NetworkUtils.NetState.NET_3G -> getString(R.string.net_3g)
- NetworkUtils.NetState.NET_4G -> getString(R.string.net_4g)
- NetworkUtils.NetState.NET_5G -> getString(R.string.net_5g)
- NetworkUtils.NetState.NET_WIFI -> getString(R.string.net_wifi)
- NetworkUtils.NetState.NET_ETHERNET -> getString(R.string.net_ethernet)
- NetworkUtils.NetState.NET_UNKNOWN -> getString(R.string.net_unknown)
- else -> getString(R.string.net_unknown)
- }
- msg.append(getString(R.string.network_type)).append(": ").append(netStateTypeName).append("\n")
-
- if (netStateType == NetworkUtils.NetState.NET_2G || netStateType == NetworkUtils.NetState.NET_3G || netStateType == NetworkUtils.NetState.NET_4G || netStateType == NetworkUtils.NetState.NET_5G) {
- // 获取当前使用的 SIM index
- val simIndex = getSlotId(context)
- if (simIndex != -1) {
- // 获取 SIM 卡信息
- App.SimInfoList = PhoneUtils.getSimMultiInfo()
- Log.d(TAG, App.SimInfoList.toString())
- if (App.SimInfoList[simIndex]?.mCarrierName != null) {
- //获取网络运营商名称:中国移动、中国联通、中国电信
- msg.append(getString(R.string.carrier_name)).append(": ").append(App.SimInfoList[simIndex]?.mCarrierName).append("\n")
- }
- msg.append(getString(R.string.data_sim_index)).append(": SIM-").append(simIndex + 1).append("\n")
- }
- } else if (netStateType == NetworkUtils.NetState.NET_WIFI) {
- //获取当前连接的WiFi名称
- val wifiSSID = getWifiSSID(context)
- msg.append(getString(R.string.wifi_ssid)).append(": ").append(wifiSSID).append("\n")
- }
-
- //获取IP地址
- val ipList = CommonUtils.getIPAddresses().filter { !isLocalAddress(it) }
- if (ServiceUtils.isServiceRunning("com.idormy.sms.forwarder.service.HttpService")) {
- ipList.forEach {
- msg.append(getString(R.string.host_address)).append(": ").append(it).append("\n")
- val hostAddress = if (it.indexOf(':', 0, false) > 0) "[${CommonUtils.removeInterfaceFromIP(it)}]" else it
- msg.append(getString(R.string.http_server)).append(": ").append("http://${hostAddress}:5000").append("\n")
- }
- } else {
- ipList.forEach {
- msg.append(getString(R.string.host_address)).append(": ").append(it).append("\n")
- }
- }
-
- sendMessage(context, msg.toString().trimEnd())
- }
- }
-
- // 判断手机数据流量是否打开
- @Suppress("rawtypes", "unchecked")
- private fun isMobileDataOpen(context: Context): Boolean {
- return try {
- val mConnectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
- val ownerClass = mConnectivityManager.javaClass
- val method = ownerClass.getMethod("getMobileDataEnabled")
- method.invoke(mConnectivityManager) as Boolean
- } catch (e: Exception) {
- false
- }
- }
-
- // 获取当前数据连接的卡槽ID
- @RequiresApi(Build.VERSION_CODES.Q)
- private fun getSlotId(context: Context): Int {
- if (!isMobileDataOpen(context)) {
- return -1
- }
- var dataSubId = 0
- try {
- dataSubId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
- SubscriptionManager.getDefaultDataSubscriptionId()
- } else {
- getDataSubId(context)
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- return SubscriptionManager.getSlotIndex(dataSubId)
- }
-
- // 获取数据连接的订阅ID
- @SuppressLint("DiscouragedPrivateApi")
- private fun getDataSubId(context: Context): Int {
- val defaultDataSlotId = getDefaultDataSlotId(context)
- try {
- val obj = Class.forName("android.telephony.SubscriptionManager")
- .getDeclaredMethod("getSubId", Int::class.javaPrimitiveType)
- .invoke(null, defaultDataSlotId)
- if (obj != null) {
- if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
- return (obj as LongArray)[0].toInt()
- }
- return (obj as IntArray)[0]
- }
- } catch (e: Exception) {
- e.printStackTrace()
- }
- return defaultDataSlotId
- }
-
- // 获取默认数据卡的卡槽ID
- private fun getDefaultDataSlotId(context: Context): Int {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
- val subscriptionManager = SubscriptionManager.from(context.applicationContext)
- if (subscriptionManager != null) {
- try {
- val subClass = Class.forName(subscriptionManager.javaClass.name)
- val getSubID = subClass.getMethod("getDefaultDataSubscriptionInfo")
- val subInfo = getSubID.invoke(subscriptionManager) as SubscriptionInfo
- return subInfo.simSlotIndex
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- } else {
- try {
- val cls = Class.forName("android.telephony.SubscriptionManager")
- val getSubId: Method = try {
- cls.getDeclaredMethod("getDefaultDataSubId")
- } catch (e: NoSuchMethodException) {
- cls.getDeclaredMethod("getDefaultDataSubscriptionId")
- }
- val subId = getSubId.invoke(null) as Int
- val slotId: Int = if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) {
- val getSlotId = cls.getDeclaredMethod("getSlotId", Long::class.javaPrimitiveType)
- getSlotId.invoke(null, subId.toLong()) as Int
- } else {
- val getSlotId = cls.getDeclaredMethod("getSlotId", Int::class.javaPrimitiveType)
- getSlotId.invoke(null, subId) as Int
- }
- return slotId
- } catch (e: Exception) {
- e.printStackTrace()
- }
- }
- return -1
- }
-
- //发送信息
- private fun sendMessage(context: Context, msg: String) {
- Log.i(TAG, msg)
- try {
- val msgInfo = MsgInfo("app", "77777777", msg, Date(), getString(R.string.network_state_monitor), -1)
- val request = OneTimeWorkRequestBuilder().setInputData(
- workDataOf(
- Worker.sendMsgInfo to Gson().toJson(msgInfo),
- )
- ).build()
- WorkManager.getInstance(context).enqueue(request)
- } catch (e: Exception) {
- Log.e(TAG, "getLog e:" + e.message)
- }
- }
-
- //获取当前连接的WiFi名称
- @SuppressLint("WifiManagerPotentialLeak")
- private fun getWifiSSID(context: Context): String {
- val wifiManager = context.getSystemService(Context.WIFI_SERVICE) as WifiManager
- val wifiInfo: WifiInfo? = wifiManager.connectionInfo
-
- if (wifiInfo != null && wifiInfo.networkId != -1) {
- return wifiInfo.ssid.replace("\"", "")
- }
-
- return "Not connected to WiFi"
- }
-
- //检查IP地址是否为本地地址
- private fun isLocalAddress(ip: String): Boolean {
- return ip == "127.0.0.1" || ip == "::1" || ip.startsWith("fe80:") || ip.startsWith("fec0:")
- }
-
- companion object {
- private const val TAG = "NetworkStateReceiver"
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.kt b/app/src/main/java/com/idormy/sms/forwarder/service/NotificationService.kt
similarity index 95%
rename from app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.kt
rename to app/src/main/java/com/idormy/sms/forwarder/service/NotificationService.kt
index c69b6f64..ed924120 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/service/NotifyService.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/service/NotificationService.kt
@@ -24,9 +24,9 @@ import java.util.*
@Suppress("PrivatePropertyName", "DEPRECATION")
-class NotifyService : NotificationListenerService() {
+class NotificationService : NotificationListenerService() {
- private val TAG: String = "NotifyService"
+ private val TAG: String = NotificationService::class.java.simpleName
override fun onListenerConnected() {
Log.d(TAG, "onListenerConnected")
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/BatteryUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/BatteryUtils.kt
index 59ca3f7e..626d0c6e 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/BatteryUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/BatteryUtils.kt
@@ -7,6 +7,7 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.entity.BatteryInfo
import com.xuexiang.xui.utils.ResUtils.getString
+@Suppress("DEPRECATION", "MemberVisibilityCanBePrivate")
object BatteryUtils {
private const val TAG = "BatteryUtils"
@@ -27,22 +28,8 @@ object BatteryUtils {
if (voltage > 0) batteryInfo.voltage = "${String.format("%.2f", voltage / 1000f)}V"
if (temperature > 0) batteryInfo.temperature = "${String.format("%.2f", temperature / 10f)}℃"
batteryInfo.status = getStatus(status)
- batteryInfo.health = when (health) {
- BatteryManager.BATTERY_HEALTH_UNKNOWN -> getString(R.string.battery_unknown)
- BatteryManager.BATTERY_HEALTH_GOOD -> getString(R.string.battery_good)
- BatteryManager.BATTERY_HEALTH_OVERHEAT -> getString(R.string.battery_overheat)
- BatteryManager.BATTERY_HEALTH_DEAD -> getString(R.string.battery_dead)
- BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE -> getString(R.string.battery_over_voltage)
- BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE -> getString(R.string.battery_unspecified_failure)
- BatteryManager.BATTERY_HEALTH_COLD -> getString(R.string.battery_cold)
- else -> getString(R.string.battery_unknown)
- }
- batteryInfo.plugged = when (plugged) {
- BatteryManager.BATTERY_PLUGGED_AC -> getString(R.string.battery_ac)
- BatteryManager.BATTERY_PLUGGED_USB -> getString(R.string.battery_usb)
- BatteryManager.BATTERY_PLUGGED_WIRELESS -> getString(R.string.battery_wireless)
- else -> getString(R.string.battery_unknown)
- }
+ batteryInfo.health = getHealth(health)
+ batteryInfo.plugged = getPlugged(plugged)
Log.i(TAG, batteryInfo.toString())
return batteryInfo
}
@@ -58,4 +45,26 @@ object BatteryUtils {
}
}
+ fun getHealth(health: Int): String {
+ return when (health) {
+ BatteryManager.BATTERY_HEALTH_UNKNOWN -> getString(R.string.battery_unknown)
+ BatteryManager.BATTERY_HEALTH_GOOD -> getString(R.string.battery_good)
+ BatteryManager.BATTERY_HEALTH_OVERHEAT -> getString(R.string.battery_overheat)
+ BatteryManager.BATTERY_HEALTH_DEAD -> getString(R.string.battery_dead)
+ BatteryManager.BATTERY_HEALTH_OVER_VOLTAGE -> getString(R.string.battery_over_voltage)
+ BatteryManager.BATTERY_HEALTH_UNSPECIFIED_FAILURE -> getString(R.string.battery_unspecified_failure)
+ BatteryManager.BATTERY_HEALTH_COLD -> getString(R.string.battery_cold)
+ else -> getString(R.string.battery_unknown)
+ }
+ }
+
+ fun getPlugged(plugged: Int): String {
+ return when (plugged) {
+ BatteryManager.BATTERY_PLUGGED_AC -> getString(R.string.battery_ac)
+ BatteryManager.BATTERY_PLUGGED_USB -> getString(R.string.battery_usb)
+ BatteryManager.BATTERY_PLUGGED_WIRELESS -> getString(R.string.battery_wireless)
+ else -> getString(R.string.battery_unknown)
+ }
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtils.kt
index 65043232..9cd4df68 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/CommonUtils.kt
@@ -23,7 +23,7 @@ import com.idormy.sms.forwarder.core.webview.AgentWebFragment
import com.idormy.sms.forwarder.entity.ImageInfo
import com.idormy.sms.forwarder.fragment.MarkdownFragment
import com.idormy.sms.forwarder.fragment.ServiceProtocolFragment
-import com.idormy.sms.forwarder.service.NotifyService
+import com.idormy.sms.forwarder.service.NotificationService
import com.xuexiang.xpage.base.XPageFragment
import com.xuexiang.xpage.core.PageOption
import com.xuexiang.xui.utils.ColorUtils
@@ -273,10 +273,10 @@ class CommonUtils private constructor() {
fun toggleNotificationListenerService(context: Context) {
val pm = context.packageManager
pm.setComponentEnabledSetting(
- ComponentName(context.applicationContext, NotifyService::class.java), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP
+ ComponentName(context.applicationContext, NotificationService::class.java), PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP
)
pm.setComponentEnabledSetting(
- ComponentName(context.applicationContext, NotifyService::class.java), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
+ ComponentName(context.applicationContext, NotificationService::class.java), PackageManager.COMPONENT_ENABLED_STATE_ENABLED, PackageManager.DONT_KILL_APP
)
}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt
index 67659b74..c59eb647 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/Constants.kt
@@ -16,9 +16,14 @@ object Worker {
const val rule = "rule"
const val senderIndex = "sender_index"
const val msgId = "msg_id"
+}
+
+object TaskWorker {
const val taskId = "task_id"
- const val actionType = "action_type"
- const val actionSetting = "action_setting"
+ const val task = "task"
+ const val taskActions = "task_actions"
+ const val conditionType = "condition_type"
+ const val msgInfo = "msg_info"
}
//初始化相关
@@ -59,17 +64,6 @@ const val SP_AUTO_CLEAN_LOGS_DAYS = "auto_clean_logs_days"
const val SP_NET_STATE_RECEIVER = "enable_network_state_receiver"
-const val SP_BATTERY_RECEIVER = "enable_battery_receiver"
-const val SP_BATTERY_STATUS = "battery_status"
-const val SP_BATTERY_LEVEL_MIN = "battery_level_min"
-const val SP_BATTERY_LEVEL_MAX = "battery_level_max"
-const val SP_BATTERY_LEVEL_ONCE = "battery_level_once"
-const val SP_BATTERY_LEVEL_CURRENT = "battery_level_current"
-
-const val SP_BATTERY_CRON = "enable_battery_cron"
-const val SP_BATTERY_CRON_START_TIME = "battery_cron_start_time"
-const val SP_BATTERY_CRON_INTERVAL = "battery_cron_interval"
-
const val SP_ENABLE_EXCLUDE_FROM_RECENTS = "enable_exclude_from_recents"
const val SP_ENABLE_PLAY_SILENCE_MUSIC = "enable_play_silence_music"
const val SP_ENABLE_ONE_PIXEL_ACTIVITY = "enable_one_pixel_activity"
@@ -581,4 +575,9 @@ var TASK_ACTION_FRAGMENT_LIST = listOf(
CoreAnim.slide,
R.drawable.auto_task_icon_http_server
),
-)
\ No newline at end of file
+)
+
+const val SP_BATTERY_STATUS = "battery_status"
+const val SP_BATTERY_LEVEL = "battery_level"
+const val SP_BATTERY_PCT = "battery_pct"
+const val SP_BATTERY_PLUGGED = "battery_plugged"
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
index ecb74ea5..a0dae5a3 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SettingUtils.kt
@@ -77,33 +77,6 @@ class SettingUtils private constructor() {
//是否监听网络状态变化
var enableNetworkStateReceiver: Boolean by SharedPreference(SP_NET_STATE_RECEIVER, false)
- //是否监听电池状态变化
- var enableBatteryReceiver: Boolean by SharedPreference(SP_BATTERY_RECEIVER, false)
-
- //电量预警当前状态
- var batteryStatus: Int by SharedPreference(SP_BATTERY_STATUS, 0)
-
- //电量预警当前值
- var batteryLevelCurrent: Int by SharedPreference(SP_BATTERY_LEVEL_CURRENT, 0)
-
- //电量预警最低值
- var batteryLevelMin: Int by SharedPreference(SP_BATTERY_LEVEL_MIN, 0)
-
- //电量预警最高值
- var batteryLevelMax: Int by SharedPreference(SP_BATTERY_LEVEL_MAX, 100)
-
- //是否持续电量预警
- var batteryLevelOnce: Boolean by SharedPreference(SP_BATTERY_LEVEL_ONCE, false)
-
- //是否定时推送电池状态
- var enableBatteryCron: Boolean by SharedPreference(SP_BATTERY_CRON, false)
-
- //是否定时推送电池状态——开始时间
- var batteryCronStartTime: String by SharedPreference(SP_BATTERY_CRON_START_TIME, "00:00")
-
- //是否定时推送电池状态——间隔时间(分钟)
- var batteryCronInterval: Int by SharedPreference(SP_BATTERY_CRON_INTERVAL, 60)
-
//是否不在最近任务列表中显示
var enableExcludeFromRecents: Boolean by SharedPreference(SP_ENABLE_EXCLUDE_FROM_RECENTS, false)
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/SmsCommandUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/SmsCommandUtils.kt
index 33ebf27a..433e8764 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/SmsCommandUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/SmsCommandUtils.kt
@@ -9,12 +9,10 @@ import android.util.Log
import androidx.core.app.ActivityCompat
import com.google.gson.Gson
import com.idormy.sms.forwarder.App
-import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.server.model.SmsSendData
-import com.idormy.sms.forwarder.service.HttpService
+import com.idormy.sms.forwarder.service.HttpServerService
import com.xuexiang.xrouter.utils.TextUtils
-import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xutil.XUtil
import com.xuexiang.xutil.file.FileUtils
import com.xuexiang.xutil.system.DeviceUtils
@@ -101,7 +99,7 @@ class SmsCommandUtils {
}
"httpserver" -> {
- Intent(context, HttpService::class.java).also {
+ Intent(context, HttpServerService::class.java).also {
if (action == "start") {
context.startService(it)
} else if (action == "stop") {
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/task/AlarmUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/task/AlarmUtils.kt
deleted file mode 100644
index c56c3a4f..00000000
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/task/AlarmUtils.kt
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.idormy.sms.forwarder.utils.task
-
-import android.annotation.SuppressLint
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.content.Context
-import android.content.Intent
-import android.os.Build
-import com.idormy.sms.forwarder.database.entity.Task
-import com.idormy.sms.forwarder.receiver.AlarmReceiver
-
-class AlarmUtils {
- companion object {
-
- @SuppressLint("StaticFieldLeak")
- private lateinit var context: Context
-
- fun initialize(context: Context) {
- this.context = context.applicationContext
- }
-
- fun cancelAlarm(task: Task?) {
- val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
- val alarmIntent = Intent(context, AlarmReceiver::class.java)
- val requestCode = task?.id?.toInt() ?: -1
-
- val pendingIntent = PendingIntent.getBroadcast(
- context,
- requestCode,
- alarmIntent,
- PendingIntent.FLAG_NO_CREATE or PendingIntent.FLAG_MUTABLE
- )
- pendingIntent?.let {
- alarmManager.cancel(it)
- it.cancel()
- }
- }
-
- @SuppressLint("ScheduleExactAlarm")
- fun scheduleAlarm(task: Task) {
- val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
- val alarmIntent = Intent(context, AlarmReceiver::class.java)
- val requestCode = task.id.toInt()
- alarmIntent.putExtra("TASK", task)
- val pendingIntent = PendingIntent.getBroadcast(
- context,
- requestCode,
- alarmIntent,
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
- )
-
- // TODO:设置闹钟,低电量模式下无法设置精确闹钟
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
- alarmManager.setExactAndAllowWhileIdle(
- AlarmManager.RTC_WAKEUP,
- task.nextExecTime.time,
- pendingIntent
- )
- } else {
- alarmManager.setExact(
- AlarmManager.RTC_WAKEUP,
- task.nextExecTime.time,
- pendingIntent
- )
- }
- }
-
- }
-}
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/task/CronJobScheduler.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/task/CronJobScheduler.kt
index fbcacf5d..05aa4d0c 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/task/CronJobScheduler.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/task/CronJobScheduler.kt
@@ -6,6 +6,7 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import com.idormy.sms.forwarder.database.entity.Task
+import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.workers.CronWorker
import java.util.concurrent.TimeUnit
@@ -19,7 +20,7 @@ class CronJobScheduler {
fun scheduleTask(task: Task) {
val currentTimeMillis = System.currentTimeMillis()
val delayInMillis = task.nextExecTime.time / 1000 * 1000 - currentTimeMillis
- val inputData = Data.Builder().putLong("taskId", task.id).build()
+ val inputData = Data.Builder().putLong(TaskWorker.taskId, task.id).build()
val taskRequest = if (delayInMillis <= 0L) {
Log.d(TAG, "任务${task.id}:立即执行,delayInMillis = $delayInMillis")
OneTimeWorkRequestBuilder()
diff --git a/app/src/main/java/com/idormy/sms/forwarder/utils/task/TaskUtils.kt b/app/src/main/java/com/idormy/sms/forwarder/utils/task/TaskUtils.kt
index 7771e14e..5dd476e1 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/utils/task/TaskUtils.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/utils/task/TaskUtils.kt
@@ -1,6 +1,10 @@
package com.idormy.sms.forwarder.utils.task
-import com.idormy.sms.forwarder.utils.SP_ENABLE_SERVER_AUTORUN
+import android.os.BatteryManager
+import com.idormy.sms.forwarder.utils.SP_BATTERY_LEVEL
+import com.idormy.sms.forwarder.utils.SP_BATTERY_PCT
+import com.idormy.sms.forwarder.utils.SP_BATTERY_PLUGGED
+import com.idormy.sms.forwarder.utils.SP_BATTERY_STATUS
import com.idormy.sms.forwarder.utils.SharedPreference
/**
@@ -10,7 +14,19 @@ class TaskUtils private constructor() {
companion object {
- //是否启用HttpServer开机自启
- var enableServerAutorun: Boolean by SharedPreference(SP_ENABLE_SERVER_AUTORUN, false)
+ //电池信息
+ var batteryInfo: String by SharedPreference("batteryInfo", "")
+
+ //当前电量
+ var batteryLevel: Int by SharedPreference(SP_BATTERY_LEVEL, 0)
+
+ //当前电量百分比(level/scale)
+ var batteryPct: Float by SharedPreference(SP_BATTERY_PCT, 0.00F)
+
+ //电池状态
+ var batteryStatus: Int by SharedPreference(SP_BATTERY_STATUS, BatteryManager.BATTERY_STATUS_UNKNOWN)
+
+ //充电方式
+ var batteryPlugged: Int by SharedPreference(SP_BATTERY_PLUGGED, BatteryManager.BATTERY_PLUGGED_AC)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/workers/ActionWorker.kt b/app/src/main/java/com/idormy/sms/forwarder/workers/ActionWorker.kt
index 2f682352..b4897507 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/workers/ActionWorker.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/workers/ActionWorker.kt
@@ -13,76 +13,94 @@ import com.idormy.sms.forwarder.R
import com.idormy.sms.forwarder.database.entity.Rule
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.task.SmsSetting
+import com.idormy.sms.forwarder.entity.task.TaskSetting
import com.idormy.sms.forwarder.utils.PhoneUtils
import com.idormy.sms.forwarder.utils.SendUtils
import com.idormy.sms.forwarder.utils.TASK_ACTION_NOTIFICATION
import com.idormy.sms.forwarder.utils.TASK_ACTION_SENDSMS
-import com.idormy.sms.forwarder.utils.Worker
+import com.idormy.sms.forwarder.utils.TaskWorker
import com.xuexiang.xui.utils.ResUtils
import com.xuexiang.xutil.XUtil
+//执行每个task具体动作任务
@Suppress("PrivatePropertyName", "DEPRECATION")
class ActionWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
private val TAG: String = ActionWorker::class.java.simpleName
override suspend fun doWork(): Result {
- val taskId = inputData.getLong(Worker.taskId, -1L)
- val actionType = inputData.getInt(Worker.actionType, -1)
- val actionSetting = inputData.getString(Worker.actionSetting)
- val msgInfoJson = inputData.getString(Worker.sendMsgInfo)
- Log.d(TAG, "taskId: $taskId, actionType: $actionType, actionSetting: $actionSetting, msgInfoJson: $msgInfoJson")
- if (taskId == -1L || actionSetting == null) {
+ val taskId = inputData.getLong(TaskWorker.taskId, -1L)
+ val taskActionsJson = inputData.getString(TaskWorker.taskActions)
+ val msgInfoJson = inputData.getString(TaskWorker.msgInfo)
+ Log.d(TAG, "taskId: $taskId, taskActionsJson: $taskActionsJson, msgInfoJson: $msgInfoJson")
+ if (taskId == -1L || taskActionsJson.isNullOrEmpty() || msgInfoJson.isNullOrEmpty()) {
Log.d(TAG, "taskId is -1L or actionSetting is null")
return Result.failure()
}
+
+ val actionList = Gson().fromJson(taskActionsJson, Array::class.java).toMutableList()
+ if (actionList.isEmpty()) {
+ Log.d(TAG, "任务$taskId:actionList is empty")
+ return Result.failure()
+ }
+
val msgInfo = Gson().fromJson(msgInfoJson, MsgInfo::class.java)
+ if (msgInfo == null) {
+ Log.d(TAG, "任务$taskId:msgInfo is null")
+ return Result.failure()
+ }
- when (actionType) {
- TASK_ACTION_SENDSMS -> {
- val smsSetting = Gson().fromJson(actionSetting, SmsSetting::class.java)
- if (smsSetting == null) {
- Log.d(TAG, "任务$taskId:smsSetting is null")
- return Result.failure()
- }
- //获取卡槽信息
- if (App.SimInfoList.isEmpty()) {
- App.SimInfoList = PhoneUtils.getSimMultiInfo()
- }
- Log.d(TAG, App.SimInfoList.toString())
+ var successNum = 0
+ for (action in actionList) {
+ when (action.type) {
+ TASK_ACTION_SENDSMS -> {
+ val smsSetting = Gson().fromJson(action.setting, SmsSetting::class.java)
+ if (smsSetting == null) {
+ Log.d(TAG, "任务$taskId:smsSetting is null")
+ continue
+ }
+ //获取卡槽信息
+ if (App.SimInfoList.isEmpty()) {
+ App.SimInfoList = PhoneUtils.getSimMultiInfo()
+ }
+ Log.d(TAG, App.SimInfoList.toString())
- //发送卡槽: 1=SIM1, 2=SIM2
- val simSlotIndex = smsSetting.simSlot - 1
- //TODO:取不到卡槽信息时,采用默认卡槽发送
- val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
+ //发送卡槽: 1=SIM1, 2=SIM2
+ val simSlotIndex = smsSetting.simSlot - 1
+ //TODO:取不到卡槽信息时,采用默认卡槽发送
+ val mSubscriptionId: Int = App.SimInfoList[simSlotIndex]?.mSubscriptionId ?: -1
- val msg = if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
- ResUtils.getString(R.string.no_sms_sending_permission)
- } else {
- PhoneUtils.sendSms(mSubscriptionId, smsSetting.phoneNumbers, smsSetting.msgContent) ?: "success"
+ val msg = if (ActivityCompat.checkSelfPermission(XUtil.getContext(), Manifest.permission.SEND_SMS) != PackageManager.PERMISSION_GRANTED) {
+ ResUtils.getString(R.string.no_sms_sending_permission)
+ } else {
+ PhoneUtils.sendSms(mSubscriptionId, smsSetting.phoneNumbers, smsSetting.msgContent)
+ successNum++
+ }
+
+ Log.d(TAG, "任务$taskId:send sms result: $msg")
+ continue
}
- Log.d(TAG, "任务$taskId:send sms result: $msg")
- return Result.success()
- }
-
- TASK_ACTION_NOTIFICATION -> {
- return try {
- val settingVo = Gson().fromJson(actionSetting, Rule::class.java)
- //自动任务的不需要吐司或者更新日志,特殊处理 logId = -1,msgId = -1
- SendUtils.sendMsgSender(msgInfo, settingVo, 0, -1L, -1L)
- Result.success()
- } catch (e: Exception) {
- e.printStackTrace()
- Result.failure()
+ TASK_ACTION_NOTIFICATION -> {
+ try {
+ val settingVo = Gson().fromJson(action.setting, Rule::class.java)
+ //自动任务的不需要吐司或者更新日志,特殊处理 logId = -1,msgId = -1
+ SendUtils.sendMsgSender(msgInfo, settingVo, 0, -1L, -1L)
+ successNum++
+ } catch (e: Exception) {
+ e.printStackTrace()
+ }
+ continue
}
- }
- else -> {
- Log.d(TAG, "任务$taskId:action.type is $actionType")
- return Result.failure()
+ else -> {
+ Log.d(TAG, "任务$taskId:action.type is ${action.type}")
+ continue
+ }
}
}
+
+ return if (successNum == actionList.size) Result.success() else Result.failure()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/workers/BatteryWorker.kt b/app/src/main/java/com/idormy/sms/forwarder/workers/BatteryWorker.kt
new file mode 100644
index 00000000..619ab326
--- /dev/null
+++ b/app/src/main/java/com/idormy/sms/forwarder/workers/BatteryWorker.kt
@@ -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 BatteryWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
+
+ private val TAG: String = BatteryWorker::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(TASK_CONDITION_BATTERY)
+ for (task in taskList) {
+ Log.d(TAG, "task = $task")
+
+ // 根据任务信息执行相应操作
+ val conditionList = Gson().fromJson(task.conditions, Array::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().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(TASK_CONDITION_CHARGE)
+ for (task in taskList) {
+ Log.d(TAG, "task = $task")
+
+ // 根据任务信息执行相应操作
+ val conditionList = Gson().fromJson(task.conditions, Array::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.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().setInputData(actionData).build()
+ WorkManager.getInstance().enqueue(actionRequest)
+ }
+
+ return Result.success()
+ }
+
+ else -> {
+ Log.d(TAG, "conditionType is $conditionType")
+ return Result.failure()
+ }
+ }
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/idormy/sms/forwarder/workers/CronWorker.kt b/app/src/main/java/com/idormy/sms/forwarder/workers/CronWorker.kt
index dc89184e..30e66c6f 100644
--- a/app/src/main/java/com/idormy/sms/forwarder/workers/CronWorker.kt
+++ b/app/src/main/java/com/idormy/sms/forwarder/workers/CronWorker.kt
@@ -13,7 +13,7 @@ import com.idormy.sms.forwarder.database.AppDatabase
import com.idormy.sms.forwarder.entity.MsgInfo
import com.idormy.sms.forwarder.entity.task.CronSetting
import com.idormy.sms.forwarder.entity.task.TaskSetting
-import com.idormy.sms.forwarder.utils.Worker
+import com.idormy.sms.forwarder.utils.TaskWorker
import com.idormy.sms.forwarder.utils.task.CronJobScheduler
import gatewayapps.crondroid.CronExpression
import java.util.Date
@@ -24,7 +24,7 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
private val TAG: String = CronWorker::class.java.simpleName
override suspend fun doWork(): Result {
- val taskId = inputData.getLong("taskId", -1L)
+ val taskId = inputData.getLong(TaskWorker.taskId, -1L)
if (taskId == -1L) {
Log.d(TAG, "taskId is -1L")
return Result.failure()
@@ -82,25 +82,15 @@ class CronWorker(context: Context, params: WorkerParameters) : CoroutineWorker(c
return Result.success()
}
- //组装消息体
+ //TODO: 组装消息体 && 执行具体任务
val msgInfo = MsgInfo("task", task.name, task.description, Date(), task.name)
-
- // TODO: 执行具体任务
- val actionList = Gson().fromJson(task.actions, Array::class.java).toMutableList()
- if (actionList.isEmpty()) {
- Log.d(TAG, "任务${task.id}:actionsList is empty")
- return Result.failure()
- }
- for (action in actionList) {
- val actionData = Data.Builder()
- .putLong(Worker.taskId, task.id)
- .putInt(Worker.actionType, action.type)
- .putString(Worker.actionSetting, action.setting)
- .putString(Worker.sendMsgInfo, Gson().toJson(msgInfo))
- .build()
- val actionRequest = OneTimeWorkRequestBuilder().setInputData(actionData).build()
- WorkManager.getInstance().enqueue(actionRequest)
- }
+ val actionData = Data.Builder()
+ .putLong(TaskWorker.taskId, task.id)
+ .putString(TaskWorker.taskActions, task.actions)
+ .putString(TaskWorker.msgInfo, Gson().toJson(msgInfo))
+ .build()
+ val actionRequest = OneTimeWorkRequestBuilder().setInputData(actionData).build()
+ WorkManager.getInstance().enqueue(actionRequest)
// 为新的 nextExecTime 调度下一次任务执行
CronJobScheduler.cancelTask(task.id)
diff --git a/app/src/main/res/layout/fragment_settings.xml b/app/src/main/res/layout/fragment_settings.xml
index fb02d0ce..6bb7aa63 100644
--- a/app/src/main/res/layout/fragment_settings.xml
+++ b/app/src/main/res/layout/fragment_settings.xml
@@ -758,206 +758,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml
index db921d74..1c4cb0d9 100644
--- a/app/src/main/res/values-en/strings.xml
+++ b/app/src/main/res/values-en/strings.xml
@@ -353,8 +353,6 @@
Label of SIM,\neg. AT&T_88888888
Number must be greater than 0!
^[1-9]?\\d+$
- Low Power Alarm
- Value range: 0–99.\nLeft blank or 0 is disabled
Retry Interval
Disabled when times = 0,\nthe interval is incremented
Filter Duplicate Messages
@@ -476,10 +474,6 @@
%
0
- Monitor Battery Status Changes
- Notify when charge status changes (charging/discharging/uncharged/full)
- Push Battery Status Regularly
- Please set the daily first sending time and re-sending interval
First time:
Interval(minutes):
Proxy Settings
@@ -566,8 +560,6 @@
[Note] You need to manually create APP forwarding rules, package name: 77777777
Network State Change Remind
Send a notification when the network status changes (connection mode/IP change)
- Battery Monitor
- [Note] You need to manually create APP forwarding rules, package name: 88888888
Keep Alive
It is recommended to open the first three switch, do not disable the notification bar, to avoid APP being killed
Custom Settings
@@ -611,6 +603,10 @@
{{SCHEME}}
{{CALL_TYPE}}
{{LOCATION}}
+ {{BATTERY_PCT}}
+ {{BATTERY_STATUS}}
+ {{BATTERY_PLUGGED}}
+ {{BATTERY_INFO}}
{{UID}}
SMS
CALL
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index e2daba84..4406bb98 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -354,8 +354,6 @@
序号/运营商_手机号
数字必须大于0!
^[1-9]?\\d+$
- 安全电量范围(%)
- 超出安全范围将发出预警
请求重试机制
次数=0禁用,逐次递增
自动过滤多久内重复消息
@@ -477,10 +475,6 @@
%
高于
0
- 监听电池状态变化
- 充电状态改变(充电中/放电中/未充电/已充满)时发出通知
- 定时推送电池状态
- 请设置每日首次发送时间与再次发送间隔时间
首次发送时间:
间隔(分钟):
代理设置
@@ -567,8 +561,6 @@
需要手动创建APP转发规则,包名:77777777
网络状态改变提醒
网络状态改变(连接方式/IP变化)时发出通知
- 电池监控
- 需要手动创建APP转发规则,包名:88888888
保活措施
建议开启前三项授权或设置,不要禁用通知栏,避免APP被杀
个性设置
@@ -612,6 +604,10 @@
{{通知Scheme}}
{{通话类型}}
{{定位信息}}
+ {{电池电量}}
+ {{电池状态}}
+ {{充电方式}}
+ {{电池信息}}
{{UID}}
短信
来电
@@ -974,8 +970,8 @@
电池状态监听
【电量预警】已低于电量预警下限,请及时充电!%s
【电量预警】已高于电量预警上限,请拔掉充电器!%s
- 【电量预警】已低于电量预警下限,请及时充电!%s
- 【电量预警】已高于电量预警上限,请拔掉充电器!%s
+ 【电量预警】已达到电量预警下限,请及时充电!%s
+ 【电量预警】已达到电量预警上限,请拔掉充电器!%s
【充电状态】发生变化:
第一行不允许缩进
服务端启用签名密钥,sign节点必传