refactor(mqtt): 优化MQTT连接管理与设备状态上报

- 使用DeviceStatus对象替代手动拼接JSON字符串
- 启用HiveMQ自动重连机制,移除自定义重连逻辑
- 添加连接状态标记防止并发重复建连
- 优化断线回调,记录服务端断开原因
- 使用设备序列号作为MQTT客户端标识
- 新增信号强度和真实屏幕分辨率获取方法
- 修复SystemUtils中系统属性获取方式
- 添加DeviceStatus单元测试
This commit is contained in:
TongTongStudio
2026-08-12 08:27:33 +08:00
parent ef34590570
commit 4e93deaf65
5 changed files with 408 additions and 103 deletions

View File

@@ -18,6 +18,8 @@ import android.content.pm.ResolveInfo;
import android.content.pm.UserInfo;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
@@ -26,9 +28,13 @@ import android.os.IBinder;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.telephony.CellInfo;
import android.telephony.CellSignalStrength;
import android.telephony.SignalStrength;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -78,15 +84,14 @@ public class SystemUtils {
* @return
*/
public static String getProperty(String key, String defaultValue) {
String value = defaultValue;
// SystemProperties.get();
try {
Class<?> c = Class.forName("android.os.SystemProperties");
Method get = c.getMethod("get", String.class, String.class);
value = (String) (get.invoke(c, key, Build.UNKNOWN));
return (String) (get.invoke(c, key, defaultValue));
} catch (Exception e) {
e.printStackTrace();
} finally {
return value;
return defaultValue;
}
}
@@ -366,6 +371,135 @@ public class SystemUtils {
return "";
}
/**
* 获取当前蜂窝信号强度等级0~4对应 ASU 的粗略分级4 最强)。
* 该值可用于状态栏信号格显示,与 {@link android.telephony.SignalStrength#getLevel()} 一致。
*
* @param context 上下文
* @return 信号等级 0~4无 SIM / 非蜂窝网络 / 获取失败返回 -1
*/
@SuppressLint("MissingPermission")
public static int getSignalLevel(Context context) {
try {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
return -1;
}
// Android 9 (API 28) 及以下无 getAllCellInfo/SignalStrength 的公开 getLevel
// 这里统一用 getAllCellInfo 取最强小区的 level覆盖绝大多数系统版本。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
List<CellInfo> cellInfos = tm.getAllCellInfo();
if (cellInfos != null) {
int maxLevel = -1;
for (CellInfo info : cellInfos) {
if (info == null || !info.isRegistered()) {
continue;
}
CellSignalStrength strength = info.getCellSignalStrength();
if (strength != null) {
maxLevel = Math.max(maxLevel, strength.getLevel());
}
}
if (maxLevel >= 0) {
return maxLevel;
}
}
}
// 兜底API 29+ 可直接取 SignalStrength 的 level
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
SignalStrength signalStrength = tm.getSignalStrength();
if (signalStrength != null) {
return signalStrength.getLevel();
}
}
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
/**
* 获取当前蜂窝信号强度dBm如 -75 表示较强,-113 接近无信号)。
* 优先使用各制式 CellInfo 的 dBm找不到则回退到 ASU 换算asu - 113 - 2 * (asu & 1))。
*
* @param context 上下文
* @return 信号强度 dBm无信号 / 获取失败返回 {@code null}
*/
@SuppressLint("MissingPermission")
public static Integer getSignalDbm(Context context) {
try {
TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
return null;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
List<CellInfo> cellInfos = tm.getAllCellInfo();
if (cellInfos != null) {
int bestDbm = Integer.MIN_VALUE;
for (CellInfo info : cellInfos) {
if (info == null || !info.isRegistered()) {
continue;
}
CellSignalStrength strength = info.getCellSignalStrength();
if (strength != null) {
int dbm = strength.getDbm();
if (dbm != Integer.MAX_VALUE && dbm > bestDbm) {
bestDbm = dbm;
}
}
}
if (bestDbm != Integer.MIN_VALUE) {
return bestDbm;
}
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
SignalStrength signalStrength = tm.getSignalStrength();
if (signalStrength != null) {
int dbm = signalStrength.getDbm();
if (dbm != Integer.MAX_VALUE && dbm != Integer.MIN_VALUE) {
return dbm;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 根据当前活跃网络获取信号强度 (RSSI/dBm)
* 优先返回 Wi-Fi 信号强度,如果未连接 Wi-Fi 则返回移动网络信号强度
*
* @param context 上下文
* @return 信号强度 (dBm);获取失败返回 null
*/
public static Integer getCurrentNetworkRssi(Context context) {
try {
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
if (cm == null) return null;
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
if (activeNetwork == null || !activeNetwork.isConnected()) {
return null;
}
if (activeNetwork.getType() == ConnectivityManager.TYPE_WIFI) {
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
WifiInfo info = wifiManager.getConnectionInfo();
if (info != null) {
return info.getRssi();
}
} else if (activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE) {
return getSignalDbm(context);
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String getNetworkTypeName(int networkType) {
switch (networkType) {
case TelephonyManager.NETWORK_TYPE_GPRS:
@@ -504,11 +638,11 @@ public class SystemUtils {
}
public static String getBuildId() {
return getProperty(Build.ID, Build.UNKNOWN);
return getProperty("ro.build.id", Build.ID);
}
public static String getBuildDisplayId() {
return getProperty(Build.DISPLAY, Build.UNKNOWN);
return getProperty("ro.build.display.id", Build.DISPLAY);
}
// ==================================================================
@@ -527,7 +661,7 @@ public class SystemUtils {
}
public static String getDeviceManufacturer() {
return getProperty(Build.MANUFACTURER, Build.UNKNOWN);
return getProperty("ro.product.manufacturer", Build.MANUFACTURER);
}
public static String getHardware() {
@@ -535,7 +669,7 @@ public class SystemUtils {
}
public static String getHost() {
return getProperty(Build.HOST, Build.UNKNOWN);
return getProperty("ro.build.host", Build.HOST);
}
public static String getAndroidId(Context context) {
@@ -547,23 +681,23 @@ public class SystemUtils {
}
public static String getBuildFingerprint() {
return getProperty(Build.FINGERPRINT, Build.UNKNOWN);
return getProperty("ro.build.fingerprint", Build.FINGERPRINT);
}
public static String getBuildType() {
return getProperty(Build.TYPE, Build.UNKNOWN);
return getProperty("ro.build.type", Build.TYPE);
}
public static String getBuildUser() {
return getProperty(Build.USER, Build.UNKNOWN);
return getProperty("ro.build.user", Build.USER);
}
public static String getBuildHost() {
return getProperty(Build.HOST, Build.UNKNOWN);
return getProperty("ro.build.host", Build.HOST);
}
public static String getBuildTags() {
return getProperty(Build.TAGS, Build.UNKNOWN);
return getProperty("ro.build.tags", Build.TAGS);
}
public static long getBuildTime() {
@@ -600,13 +734,30 @@ public class SystemUtils {
public static String getScreenResolution(Context context) {
try {
android.util.DisplayMetrics dm = context.getResources().getDisplayMetrics();
android.util.DisplayMetrics dm = getRealDisplayMetrics(context);
return dm.widthPixels + "x" + dm.heightPixels;
} catch (Throwable t) {
return "";
}
}
/**
* 获取设备真实屏幕显示参数(包含状态栏、导航栏,不被窗口裁切)。
* 优先使用 getRealMetrics显示设备真实分辨率低版本无此 API 时回退 getMetrics。
*/
private static android.util.DisplayMetrics getRealDisplayMetrics(Context context) {
android.util.DisplayMetrics dm = new android.util.DisplayMetrics();
android.view.WindowManager wm =
(android.view.WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
android.view.Display display = wm.getDefaultDisplay();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
display.getRealMetrics(dm);
} else {
display.getMetrics(dm);
}
return dm;
}
public static int getScreenDensity(Context context) {
try {
return (int) Math.round(context.getResources().getDisplayMetrics().density);
@@ -635,7 +786,7 @@ public class SystemUtils {
}
public static String getProductName() {
return getProperty(Build.PRODUCT, Build.UNKNOWN);
return getProperty("ro.product.name", Build.PRODUCT);
}
public static String getProductModel() {
@@ -682,7 +833,7 @@ public class SystemUtils {
}
public static String getBootloader() {
return getProperty(Build.BOOTLOADER, Build.UNKNOWN);
return getProperty("ro.bootloader", Build.BOOTLOADER);
}
public static String getBasebandVersion() {
@@ -699,7 +850,7 @@ public class SystemUtils {
public static String getScreenSize(Context context) {
try {
android.util.DisplayMetrics dm = context.getResources().getDisplayMetrics();
android.util.DisplayMetrics dm = getRealDisplayMetrics(context);
double diagonal = Math.sqrt(Math.pow(dm.widthPixels / dm.xdpi, 2)
+ Math.pow(dm.heightPixels / dm.ydpi, 2));
return String.format(Locale.US, "%.1f", diagonal);
@@ -710,7 +861,7 @@ public class SystemUtils {
public static double getScreenInch(Context context) {
try {
android.util.DisplayMetrics dm = context.getResources().getDisplayMetrics();
android.util.DisplayMetrics dm = getRealDisplayMetrics(context);
double diagonal = Math.sqrt(Math.pow(dm.widthPixels / dm.xdpi, 2)
+ Math.pow(dm.heightPixels / dm.ydpi, 2));
return Math.round(diagonal * 10.0) / 10.0;