新增:定时推送电池状态 (#131)

* 修复:手动重发消息中UTC时间未转换本地时间 (#122)

* 新增:Webhook发送通道支持设置Header (#128)

* 优化:抽取电池状态信息工具类

* 新增:定时推送电池状态 (#121)
pull/140/head
Naccl 2 years ago committed by GitHub
parent 733f375821
commit 28397ec622
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -32,6 +32,7 @@ import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastUtils;
import com.idormy.sms.forwarder.adapter.LogAdapter;
import com.idormy.sms.forwarder.model.vo.LogVo;
import com.idormy.sms.forwarder.sender.BatteryReportCronTask;
import com.idormy.sms.forwarder.sender.HttpServer;
import com.idormy.sms.forwarder.sender.SendUtil;
import com.idormy.sms.forwarder.sender.SenderUtil;
@ -148,6 +149,15 @@ public class MainActivity extends AppCompatActivity implements RefreshListView.I
}
}
//电池状态定时推送
if (SettingUtil.getSwitchEnableBatteryCron()) {
try {
BatteryReportCronTask.getSingleton().updateTimer();
} catch (Exception e) {
Log.e(TAG, "BatteryReportCronTask:", e);
}
}
}
@Override

@ -2,6 +2,7 @@ package com.idormy.sms.forwarder;
import android.annotation.SuppressLint;
import android.app.ActivityManager;
import android.app.TimePickerDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
@ -35,6 +36,7 @@ import com.hjq.permissions.Permission;
import com.hjq.permissions.XXPermissions;
import com.hjq.toast.ToastUtils;
import com.idormy.sms.forwarder.receiver.RebootBroadcastReceiver;
import com.idormy.sms.forwarder.sender.BatteryReportCronTask;
import com.idormy.sms.forwarder.sender.HttpServer;
import com.idormy.sms.forwarder.sender.SenderUtil;
import com.idormy.sms.forwarder.sender.SmsHubApiTask;
@ -53,6 +55,7 @@ import com.idormy.sms.forwarder.view.StepBar;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -101,6 +104,10 @@ public class SettingActivity extends AppCompatActivity {
switchBatteryReceiver(findViewById(R.id.switch_battery_receiver));
//电量预警
editBatteryLevelAlarm(findViewById(R.id.et_battery_level_alarm_min), findViewById(R.id.et_battery_level_alarm_max), findViewById(R.id.cb_battery_level_alarm_once));
//定时推送电池状态
switchBatteryCron(findViewById(R.id.switch_battery_cron));
//设置推送电池状态时机
editBatteryCronTiming(findViewById(R.id.et_battery_cron_start_time), findViewById(R.id.et_battery_cron_interval));
//开机启动
checkWithReboot(findViewById(R.id.switch_with_reboot), findViewById(R.id.tv_auto_startup));
@ -432,6 +439,71 @@ public class SettingActivity extends AppCompatActivity {
});
}
//定时推送电池状态
@SuppressLint("UseSwitchCompatOrMaterialCode")
private void switchBatteryCron(Switch switch_battery_cron) {
boolean isOn = SettingUtil.getSwitchEnableBatteryCron();
switch_battery_cron.setChecked(isOn);
final LinearLayout layout_battery_cron = findViewById(R.id.layout_battery_cron);
layout_battery_cron.setVisibility(isOn ? View.VISIBLE : View.GONE);
switch_battery_cron.setOnCheckedChangeListener((buttonView, isChecked) -> {
Log.d(TAG, "onCheckedChanged:" + isChecked);
layout_battery_cron.setVisibility(isChecked ? View.VISIBLE : View.GONE);
SettingUtil.switchEnableBatteryCron(isChecked);
BatteryReportCronTask.getSingleton().updateTimer();
});
}
//设置推送电池状态时机
private void editBatteryCronTiming(final EditText et_battery_cron_start_time, final EditText et_battery_cron_interval) {
et_battery_cron_start_time.setText(SettingUtil.getBatteryCronStartTime());
Calendar calendar = Calendar.getInstance();
et_battery_cron_start_time.setOnClickListener(view -> {
TimePickerDialog dialog = new TimePickerDialog(SettingActivity.this, (timePicker, hourOfDay, minute) -> {
StringBuilder sb = new StringBuilder();
if (hourOfDay < 10) {
sb.append("0");
}
sb.append(hourOfDay);
sb.append(":");
if (minute < 10) {
sb.append("0");
}
sb.append(minute);
String startTime = sb.toString();
et_battery_cron_start_time.setText(startTime);
SettingUtil.setBatteryCronStartTime(startTime);
BatteryReportCronTask.getSingleton().updateTimer();
}, calendar.get(Calendar.HOUR_OF_DAY) + 1, 0, true);
dialog.show();
});
et_battery_cron_interval.setText(String.valueOf(SettingUtil.getBatteryCronInterval()));
et_battery_cron_interval.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
String interval = et_battery_cron_interval.getText().toString().trim();
if (!interval.isEmpty() && Integer.parseInt(interval) > 0) {
SettingUtil.setBatteryCronInterval(Integer.parseInt(interval));
BatteryReportCronTask.getSingleton().updateTimer();
} else {
SettingUtil.setBatteryCronInterval(60);
}
}
});
}
//开机启动
private void checkWithReboot(@SuppressLint("UseSwitchCompatOrMaterialCode") Switch withrebootSwitch, TextView tvAutoStartup) {
tvAutoStartup.setText(getAutoStartTips());

@ -0,0 +1,104 @@
package com.idormy.sms.forwarder.sender;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.util.Log;
import com.idormy.sms.forwarder.MyApplication;
import com.idormy.sms.forwarder.model.vo.SmsHubVo;
import com.idormy.sms.forwarder.model.vo.SmsVo;
import com.idormy.sms.forwarder.utils.BatteryUtils;
import com.idormy.sms.forwarder.utils.SettingUtil;
import com.idormy.sms.forwarder.utils.SmsHubActionHandler;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class BatteryReportCronTask {
private static final String TAG = "BatteryReportCronTask";
private volatile static BatteryReportCronTask singleton;
private static Timer timer;
private BatteryReportCronTask() {
}
public static BatteryReportCronTask getSingleton() {
if (singleton == null) {
synchronized (BatteryReportCronTask.class) {
if (singleton == null) {
singleton = new BatteryReportCronTask();
}
}
}
return singleton;
}
public void updateTimer() {
cancelTimer();
if (SettingUtil.getSwitchEnableBatteryCron()) {
startTimer();
} else {
Log.d(TAG, "Cancel Task");
}
}
private void cancelTimer() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
private void startTimer() {
String startTime = SettingUtil.getBatteryCronStartTime();
int interval = SettingUtil.getBatteryCronInterval();
Log.i(TAG, "Task started, startTime: " + startTime + ", interval: " + interval);
int hour = Integer.parseInt(startTime.split(":")[0]);
int minute = Integer.parseInt(startTime.split(":")[1]);
Calendar startTimeCalendar = Calendar.getInstance();
startTimeCalendar.set(Calendar.HOUR_OF_DAY, hour);
startTimeCalendar.set(Calendar.MINUTE, minute);
startTimeCalendar.set(Calendar.SECOND, 0);
Calendar currentTimeCalendar = Calendar.getInstance();
if (startTimeCalendar.before(currentTimeCalendar)) {
//首次发送时间在当前时间之前,日期加一天
startTimeCalendar.add(Calendar.DATE, 1);
}
Log.d(TAG, startTimeCalendar.getTime().toString());
timer = new Timer("BatteryReportCronTimer", true);
timer.schedule(new Task(), startTimeCalendar.getTime(), interval * 60 * 1000L);
}
static class Task extends TimerTask {
@Override
public void run() {
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED);
Intent intent = MyApplication.getContext().registerReceiver(null, intentFilter);
String msg = BatteryUtils.getBatteryInfo(intent);
sendMessage(MyApplication.getContext(), msg);
}
//发送信息
private void sendMessage(Context context, String msg) {
Log.i(TAG, msg);
try {
SmsVo smsVo = new SmsVo("88888888", msg, new Date(), "电池状态定时推送");
SendUtil.send_msg(context, smsVo, 1, "app");
//SmsHubApi
if (SettingUtil.getSwitchEnableSmsHubApi()) {
SmsHubActionHandler.putData(new SmsHubVo(SmsHubVo.Type.phone, null, msg, "电池状态定时推送"));
}
} catch (Exception e) {
Log.e(TAG, "sendMessage e:" + e.getMessage());
}
}
}
}

@ -6,7 +6,6 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
import android.os.IBinder;
import android.util.Log;
@ -14,6 +13,7 @@ import com.idormy.sms.forwarder.MyApplication;
import com.idormy.sms.forwarder.model.vo.SmsHubVo;
import com.idormy.sms.forwarder.model.vo.SmsVo;
import com.idormy.sms.forwarder.sender.SendUtil;
import com.idormy.sms.forwarder.utils.BatteryUtils;
import com.idormy.sms.forwarder.utils.SettingUtil;
import com.idormy.sms.forwarder.utils.SmsHubActionHandler;
@ -74,7 +74,7 @@ public class BatteryService extends Service {
int levelCur = intent.getIntExtra("level", 0);
int levelPre = SettingUtil.getBatteryLevelCurrent();
if (levelCur != levelPre) {
String msg = batteryReceiver(intent);
String msg = BatteryUtils.getBatteryInfo(intent);
SettingUtil.setBatteryLevelCurrent(levelCur);
int levelMin = SettingUtil.getBatteryLevelAlarmMin();
@ -103,99 +103,15 @@ public class BatteryService extends Service {
if (SettingUtil.getSwitchEnableBatteryReceiver()) {
int oldStatus = SettingUtil.getBatteryStatus();
if (status != oldStatus) {
String msg = batteryReceiver(intent);
String msg = BatteryUtils.getBatteryInfo(intent);
SettingUtil.setBatteryStatus(status);
msg = "【充电状态】发生变化:" + getStatus(oldStatus) + " → " + getStatus(status) + msg;
msg = "【充电状态】发生变化:" + BatteryUtils.getStatus(oldStatus) + " → " + BatteryUtils.getStatus(status) + msg;
sendMessage(context, msg);
}
}
}
};
@SuppressLint("DefaultLocale")
private String batteryReceiver(Intent intent) {
Log.i(TAG, "BatteryReceiver--------------");
String action = intent.getAction();
Log.i(TAG, " 0 action:" + action);
Log.i(TAG, "ACTION_BATTERY_CHANGED");
int status = intent.getIntExtra("status", 0);
int health = intent.getIntExtra("health", 0);
//boolean present = intent.getBooleanExtra("present", false);
int levelCur = intent.getIntExtra("level", 0);
int scale = intent.getIntExtra("scale", 0);
//int icon_small = intent.getIntExtra("icon-small", 0);
int plugged = intent.getIntExtra("plugged", 0);
int voltage = intent.getIntExtra("voltage", 0);
int temperature = intent.getIntExtra("temperature", 0);
//String technology = intent.getStringExtra("technology");
String msg = "";
msg += "\n剩余电量" + levelCur + "%";
if (scale > 0) msg += "\n充满电量" + scale + "%";
if (voltage > 0) msg += "\n当前电压" + String.format("%.2f", voltage / 1000F) + "V";
if (temperature > 0) msg += "\n当前温度" + String.format("%.2f", temperature / 10F) + "℃";
msg += "\n电池状态" + getStatus(status);
if (health > 0) msg += "\n健康度" + getHealth(health);
switch (plugged) {
case BatteryManager.BATTERY_PLUGGED_AC:
msg += "\n充电器AC";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
msg += "\n充电器USB";
break;
case BatteryManager.BATTERY_PLUGGED_WIRELESS:
msg += "\n充电器无线";
break;
}
Log.i(TAG, msg);
return msg;
}
//电池状态
private String getStatus(int status) {
switch (status) {
case BatteryManager.BATTERY_STATUS_CHARGING:
return "充电中";
case BatteryManager.BATTERY_STATUS_DISCHARGING:
return "放电中";
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
return "未充电";
case BatteryManager.BATTERY_STATUS_FULL:
return "充满电";
case BatteryManager.BATTERY_STATUS_UNKNOWN:
default:
return "未知";
}
}
//健康度
private String getHealth(int health) {
switch (health) {
case 2:
return "良好";
case 3:
return "过热";
case 4:
return "没电";
case 5:
return "过电压";
case 6:
return "未知错误";
case 7:
return "温度过低";
default:
case 1:
return "未知";
}
}
//发送信息
private void sendMessage(Context context, String msg) {
Log.i(TAG, msg);

@ -0,0 +1,94 @@
package com.idormy.sms.forwarder.utils;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.BatteryManager;
import android.util.Log;
public class BatteryUtils {
private static final String TAG = "BatteryUtils";
@SuppressLint("DefaultLocale")
public static String getBatteryInfo(Intent intent) {
Log.i(TAG, "getBatteryInfo--------------");
String action = intent.getAction();
Log.i(TAG, " 0 action:" + action);
Log.i(TAG, "ACTION_BATTERY_CHANGED");
int status = intent.getIntExtra("status", 0);
int health = intent.getIntExtra("health", 0);
//boolean present = intent.getBooleanExtra("present", false);
int levelCur = intent.getIntExtra("level", 0);
int scale = intent.getIntExtra("scale", 0);
//int icon_small = intent.getIntExtra("icon-small", 0);
int plugged = intent.getIntExtra("plugged", 0);
int voltage = intent.getIntExtra("voltage", 0);
int temperature = intent.getIntExtra("temperature", 0);
//String technology = intent.getStringExtra("technology");
String msg = "";
msg += "\n剩余电量" + levelCur + "%";
if (scale > 0) msg += "\n充满电量" + scale + "%";
if (voltage > 0) msg += "\n当前电压" + String.format("%.2f", voltage / 1000F) + "V";
if (temperature > 0) msg += "\n当前温度" + String.format("%.2f", temperature / 10F) + "℃";
msg += "\n电池状态" + getStatus(status);
if (health > 0) msg += "\n健康度" + getHealth(health);
switch (plugged) {
case BatteryManager.BATTERY_PLUGGED_AC:
msg += "\n充电器AC";
break;
case BatteryManager.BATTERY_PLUGGED_USB:
msg += "\n充电器USB";
break;
case BatteryManager.BATTERY_PLUGGED_WIRELESS:
msg += "\n充电器无线";
break;
}
Log.i(TAG, msg);
return msg;
}
//电池状态
public static String getStatus(int status) {
switch (status) {
case BatteryManager.BATTERY_STATUS_CHARGING:
return "充电中";
case BatteryManager.BATTERY_STATUS_DISCHARGING:
return "放电中";
case BatteryManager.BATTERY_STATUS_NOT_CHARGING:
return "未充电";
case BatteryManager.BATTERY_STATUS_FULL:
return "充满电";
case BatteryManager.BATTERY_STATUS_UNKNOWN:
default:
return "未知";
}
}
//健康度
public static String getHealth(int health) {
switch (health) {
case 2:
return "良好";
case 3:
return "过热";
case 4:
return "没电";
case 5:
return "过电压";
case 6:
return "未知错误";
case 7:
return "温度过低";
default:
case 1:
return "未知";
}
}
}

@ -20,6 +20,9 @@ public class Define {
public static final String SP_MSG_KEY_STRING_SMS_TEMPLATE = "tsms_msg_key_string_sms_template";
public static final String SP_MSG_KEY_STRING_BATTERY_STATUS = "tsms_msg_key_string_battery_status";
public static final String SP_MSG_KEY_STRING_BATTERY_RECEIVER = "tsms_msg_key_switch_battery_receiver";
public static final String SP_MSG_KEY_STRING_BATTERY_CRON = "tsms_msg_key_switch_battery_cron";
public static final String SP_MSG_KEY_STRING_BATTERY_CRON_START_TIME = "tsms_msg_key_switch_battery_cron_start_time";
public static final String SP_MSG_KEY_STRING_BATTERY_CRON_INTERVAL = "tsms_msg_key_switch_battery_cron_interval";
public static final String SP_MSG_KEY_STRING_BATTERY_LEVEL_CURRENT = "tsms_msg_key_string_battery_level_current";
public static final String SP_MSG_KEY_STRING_BATTERY_LEVEL_ALARM = "tsms_msg_key_string_battery_level_alarm";
public static final String SP_MSG_KEY_STRING_BATTERY_LEVEL_MAX = "tsms_msg_key_string_battery_level_max";

@ -282,6 +282,30 @@ public class SettingUtil {
sp_setting.edit().putInt(Define.SP_MSG_KEY_STRING_DELAY_TIME, delay_time).apply();
}
public static void switchEnableBatteryCron(Boolean enable) {
sp_setting.edit().putBoolean(Define.SP_MSG_KEY_STRING_BATTERY_CRON, enable).apply();
}
public static boolean getSwitchEnableBatteryCron() {
return sp_setting.getBoolean(Define.SP_MSG_KEY_STRING_BATTERY_CRON, false);
}
public static void setBatteryCronStartTime(String startTime) {
sp_setting.edit().putString(Define.SP_MSG_KEY_STRING_BATTERY_CRON_START_TIME, startTime).apply();
}
public static String getBatteryCronStartTime() {
return sp_setting.getString(Define.SP_MSG_KEY_STRING_BATTERY_CRON_START_TIME, "00:00");
}
public static void setBatteryCronInterval(int interval) {
sp_setting.edit().putInt(Define.SP_MSG_KEY_STRING_BATTERY_CRON_INTERVAL, interval).apply();
}
public static int getBatteryCronInterval() {
return sp_setting.getInt(Define.SP_MSG_KEY_STRING_BATTERY_CRON_INTERVAL, 60);
}
//获取当前版本名称
public static String getVersionName() {
// 获取PackageManager的实例

@ -512,6 +512,113 @@
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:background="@color/setting_bar_color"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="15dp">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="4"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/timing_report_battery_status"
android:textStyle="bold" />
</LinearLayout>
<Switch
android:id="@+id/switch_battery_cron"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="end"
android:textSize="16sp"
tools:ignore="UseSwitchCompatOrMaterialXml" />
</LinearLayout>
<LinearLayout
android:id="@+id/layout_battery_cron"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="2dp"
android:background="@color/setting_bar_color"
android:gravity="center_vertical"
android:orientation="vertical"
android:padding="15dp"
android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/timer_rule"
android:textStyle="bold" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first_send_time"
android:textSize="12sp"
android:textStyle="bold" />
<EditText
android:id="@+id/et_battery_cron_start_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="false"
android:maxLines="1"
android:ems="5"
android:autofillHints=""
android:text=""
android:textAlignment="center"
android:textSize="12sp"
tools:ignore="LabelFor,TextFields" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="@string/interval_minutes"
android:textSize="12sp"
android:textStyle="bold" />
<EditText
android:id="@+id/et_battery_cron_interval"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:inputType="number"
android:digits="0123456789"
android:maxLength="4"
android:ems="4"
android:autofillHints=""
android:text=""
android:textAlignment="center"
android:textSize="12sp"
tools:ignore="LabelFor" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"

@ -273,6 +273,10 @@
<string name="zero">0</string>
<string name="monitor_battery_status_changes">Monitor battery status changes</string>
<string name="battery_status_changes_tips">Notify when charging status changes (charging/discharging/uncharged/fully charged)</string>
<string name="timing_report_battery_status">Regularly report battery status</string>
<string name="timer_rule">Timer rule</string>
<string name="first_send_time">First time: </string>
<string name="interval_minutes">Interval(minutes): </string>
<string name="proxy_settings">Proxy Settings</string>
<string name="proxy_none">None</string>
<string name="proxy_http">HTTP</string>

@ -272,6 +272,10 @@
<string name="zero">0</string>
<string name="monitor_battery_status_changes">监听电池状态变化</string>
<string name="battery_status_changes_tips">充电状态改变(充电中/放电中/未充电/已充满)时发出通知</string>
<string name="timing_report_battery_status">定时推送电池状态</string>
<string name="timer_rule">定时规则</string>
<string name="first_send_time">首次发送时间:</string>
<string name="interval_minutes">间隔(分钟)</string>
<string name="proxy_settings">代理设置</string>
<string name="proxy_none">无代理</string>
<string name="proxy_http">HTTP</string>

Loading…
Cancel
Save