From eb20d8ea055f53dedce0bfcfdb7b35bcfab40c78 Mon Sep 17 00:00:00 2001 From: pppscn <35696959@qq.com> Date: Tue, 12 Dec 2023 22:37:37 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=C2=B7=E5=BF=AB=E6=8D=B7=E6=8C=87=E4=BB=A4=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E7=94=B5=E6=B1=A0=E7=94=B5=E9=87=8F&?= =?UTF-8?q?=E5=85=85=E7=94=B5=E7=8A=B6=E6=80=81=E6=94=B9=E5=8F=98=EF=BC=88?= =?UTF-8?q?=E5=BA=9F=E5=BC=83=EF=BC=9A`88888888`=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/AndroidManifest.xml | 23 +- .../main/java/com/idormy/sms/forwarder/App.kt | 27 +- .../sms/forwarder/database/dao/TaskDao.kt | 2 +- .../sms/forwarder/entity/BatteryInfo.kt | 1 + .../idormy/sms/forwarder/entity/MsgInfo.kt | 6 + .../forwarder/entity/task/BatterySetting.kt | 27 ++ .../forwarder/entity/task/ChargeSetting.kt | 7 + .../sms/forwarder/fragment/ServerFragment.kt | 16 +- .../forwarder/fragment/SettingsFragment.kt | 96 +------ .../forwarder/fragment/TasksEditFragment.kt | 3 - .../sms/forwarder/receiver/AlarmReceiver.kt | 73 ----- .../sms/forwarder/receiver/BatteryReceiver.kt | 79 ++++++ .../receiver/BootCompletedReceiver.kt | 28 ++ .../sms/forwarder/receiver/BootReceiver.kt | 28 -- .../forwarder/receiver/SimStateReceiver.kt | 2 +- .../sms/forwarder/receiver/SmsReceiver.kt | 2 +- .../sms/forwarder/service/BatteryService.kt | 172 ------------ .../forwarder/service/ForegroundService.kt | 2 +- .../{HttpService.kt => HttpServerService.kt} | 5 +- .../forwarder/service/NetworkStateService.kt | 265 ------------------ ...otifyService.kt => NotificationService.kt} | 4 +- .../sms/forwarder/utils/BatteryUtils.kt | 41 +-- .../idormy/sms/forwarder/utils/CommonUtils.kt | 6 +- .../idormy/sms/forwarder/utils/Constants.kt | 27 +- .../sms/forwarder/utils/SettingUtils.kt | 27 -- .../sms/forwarder/utils/SmsCommandUtils.kt | 6 +- .../sms/forwarder/utils/task/AlarmUtils.kt | 69 ----- .../forwarder/utils/task/CronJobScheduler.kt | 3 +- .../sms/forwarder/utils/task/TaskUtils.kt | 22 +- .../sms/forwarder/workers/ActionWorker.kt | 106 ++++--- .../sms/forwarder/workers/BatteryWorker.kt | 149 ++++++++++ .../sms/forwarder/workers/CronWorker.kt | 30 +- app/src/main/res/layout/fragment_settings.xml | 200 ------------- .../fragment_tasks_condition_charge.xml | 4 +- app/src/main/res/values-en/strings.xml | 12 +- app/src/main/res/values/strings.xml | 16 +- 36 files changed, 483 insertions(+), 1103 deletions(-) delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/receiver/AlarmReceiver.kt create mode 100644 app/src/main/java/com/idormy/sms/forwarder/receiver/BatteryReceiver.kt create mode 100644 app/src/main/java/com/idormy/sms/forwarder/receiver/BootCompletedReceiver.kt delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/receiver/BootReceiver.kt delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/service/BatteryService.kt rename app/src/main/java/com/idormy/sms/forwarder/service/{HttpService.kt => HttpServerService.kt} (88%) delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/service/NetworkStateService.kt rename app/src/main/java/com/idormy/sms/forwarder/service/{NotifyService.kt => NotificationService.kt} (95%) delete mode 100644 app/src/main/java/com/idormy/sms/forwarder/utils/task/AlarmUtils.kt create mode 100644 app/src/main/java/com/idormy/sms/forwarder/workers/BatteryWorker.kt 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节点必传