安卓开发获得移动网络信号强度
- 行业动态
- 2025-04-21
- 4
获取移动网络信号强度的实现方法
核心原理
安卓系统通过 TelephonyManager
和 CellInfo
相关 API 获取移动网络信号强度,信号强度通常以 dBm(毫分贝)或 ASU(Arbitrary Strength Unit)为单位返回,
- dBm:数值越大(如 -50dBm)表示信号越强,数值越小(如 -120dBm)表示信号越弱。
- ASU:范围通常是 0~31(部分设备可能不同),数值越大信号越强。
实现步骤
添加权限
在 AndroidManifest.xml
中声明以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" />
对于 Android 6.0+,需动态申请 READ_PHONE_STATE
权限。
获取信号强度
通过 TelephonyManager
和 CellInfo
获取信号强度:
// 获取 TelephonyManager 实例 TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); // 检查权限(Android 6.0+ 需动态申请) if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) { // 申请权限 ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.READ_PHONE_STATE}, REQUEST_CODE); } // 获取所有小区信息(API < 29) List<CellInfo> cellInfoList = telephonyManager.getAllCellInfo(); // 遍历 CellInfo 提取信号强度 for (CellInfo cellInfo : cellInfoList) { if (cellInfo instanceof CellInfoGsm) { CellSignalStrengthGsm signalStrength = ((CellInfoGsm) cellInfo).getCellSignalStrength(); int asu = signalStrength.getAsuLevel(); // ASU 值 int dbm = signalStrength.getDbm(); // dBm 值 } else if (cellInfo instanceof CellInfoLte) { CellSignalStrengthLte signalStrength = ((CellInfoLte) cellInfo).getCellSignalStrength(); int asu = signalStrength.getAsuLevel(); int dbm = signalStrength.getDbm(); } // 其他网络类型(如 CDMA、NR)类似处理 }
适配 Android Q(API 29)及以上
Android Q 限制了 getAllCellInfo()
的调用频率,需使用 registerNetworkCallback
监听信号变化:
// 创建 NetworkCallback PhoneStateListener listener = new PhoneStateListener() { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { super.onSignalStrengthsChanged(signalStrength); int level = signalStrength.getLevel(); // 信号等级(0~4) int asu = signalStrength.getAsuLevel(); // ASU 值 } }; telephonyManager.listen(listener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
信号强度单位转换
单位 | 描述 | 典型范围 |
---|---|---|
dBm | 功率单位(相对于 1mW) | -120dBm ~ -50dBm |
ASU | 设备厂商自定义的强度值 | 0 ~ 31(设备相关) |
RSSI | 接收信号强度指示(等同于 dBm) | 同 dBm |
转换公式:
- ASU → dBm:设备相关,无通用公式。
- dBm → RSSI:直接等价。
注意事项
- 权限问题:
READ_PHONE_STATE
是危险权限,需动态申请。 - 空值处理:部分设备可能返回空列表或 null,需做空值校验。
- 网络类型兼容:需判断
CellInfo
的具体类型(如 GSM、LTE)。 - 性能优化:频繁调用
getAllCellInfo()
可能增加功耗,建议通过回调监听变化。
相关问题与解答
问题 1:如何监听移动网络信号强度的实时变化?
解答:
使用 PhoneStateListener
的 onSignalStrengthsChanged
方法,注册回调后可实时监听信号变化:
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE); PhoneStateListener listener = new PhoneStateListener() { @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { int level = signalStrength.getLevel(); // 信号等级(0~4) int asu = signalStrength.getAsuLevel(); // ASU 值 // 处理信号变化逻辑 } }; telephonyManager.listen(listener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
注意:需在 onDestroy
中调用 telephonyManager.listen(listener, 0)
取消监听,避免内存泄漏。
问题 2:如何区分不同网络类型(如 4G、5G)的信号强度?
解答:
通过 CellInfo
的子类类型判断网络制式,并提取对应信号强度:
| 网络类型 | 类名 | 获取信号强度的方式 |
|———-|——————–|————————————–|
| GSM | CellInfoGsm
| getCellSignalStrength().getDbm()
|
| LTE | CellInfoLte
| getCellSignalStrength().getDbm()
|
| NR(5G) | CellInfoNr
| getCellSignalStrength().getDbm()
|
| CDMA | CellInfoCdma
| getCellSignalStrength().getDbm()
|
示例代码:
for (CellInfo cellInfo : telephonyManager.getAllCellInfo()) { if (cellInfo instanceof CellInfoLte) { // 处理 LTE(4G)信号 } else if (cellInfo instanceof CellInfoNr) { // 处理 NR(5G)信号 } }