当前位置:首页 > 行业动态 > 正文

安卓开发获得移动网络信号强度

获取移动网络信号强度的实现方法

核心原理

安卓系统通过 TelephonyManagerCellInfo 相关 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 权限。

安卓开发获得移动网络信号强度  第1张

获取信号强度

通过 TelephonyManagerCellInfo 获取信号强度:

// 获取 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:直接等价。

注意事项

  1. 权限问题READ_PHONE_STATE 是危险权限,需动态申请。
  2. 空值处理:部分设备可能返回空列表或 null,需做空值校验。
  3. 网络类型兼容:需判断 CellInfo 的具体类型(如 GSM、LTE)。
  4. 性能优化:频繁调用 getAllCellInfo() 可能增加功耗,建议通过回调监听变化。

相关问题与解答

问题 1:如何监听移动网络信号强度的实时变化?

解答
使用 PhoneStateListeneronSignalStrengthsChanged 方法,注册回调后可实时监听信号变化:

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)信号
    }
}
0