手机信号强度首先分为两部分,一个是WiFi信号强度,一个是蜂巢网络(数据流量)信号强度。
信号强度会返回一个dbm单位的数据,这个数据就代表了当前环境下手机的信号如何。具体信号强度等级请参考下方表格。
WiFi
范围 | 等级 |
---|---|
0 -(-55) | 信号很强 |
(-55) - (-100) | 信号一般 |
<font color=red>信号强度,都是dbm为负值则正确,否则数据异常,越接近0信号越好</font>
这些等级可以根据我们自己的需求来定义,信号范围是(-100) - 0,我们可以确定自己需要输出几个等级,从而调用方法WiFiManager#calculateSignalLevel()来推算出当前WIFi信号强度属于哪个等级。
WiFi信号强度比较容易获取,直接通过WifiManager对象来获取Rssi即可。代码如下:
WifiManager wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
if (wifiManager != null) {
WifiInfo info = wifiManager.getConnectionInfo();
if (info != null) {
return info.getRssi();
}
}
4G/5G
(由于3G已经几乎没人用了,所以没有必要去获取3G的)
范围 | 等级 |
---|---|
(-89)-(-51) | 满格(Great) |
(-97)-(-89) | 很好(Good) |
(-103)-(-97) | 良好(MODERATE) |
(-107)- (-103) | 很差(poor) |
(-113) - (-107) | 无信号(min) |
获取4G的信号强度,还是有很多方法的,网上搜了一大堆,但是真正能用的还是下方我整合后的这种。因为5G手机现在市面上太多人用了,所以顺便把5G获取信号强度的方法也整合了进去。
先创建一个类继承于PhoneStateListener,用于重写监听方法,同时实现监听和取消监听方法以便我们工具调用。
public static class MyPhoneStateListener extends PhoneStateListener{
private InfoCallback callback;
private Context context;
private TelephonyManager tm;
public void init(@NonNull Context context,@NonNull InfoCallback callback){
this.context = context;
this.callback = callback;
this.tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
}
/**
* 开始监听
*/
public void register(){
if (tm == null){
callback.onGetMobileInfoResult(1);
return;
}
tm.listen(this,PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}
/**
* 取消监听
*/
public void unRegister(){
if (tm != null){
tm.listen(this,PhoneStateListener.LISTEN_NONE);
}
}
@Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
super.onSignalStrengthsChanged(signalStrength);
// 检查权限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (context.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
callback.onGetMobileInfoResult(2);
return;
}
}
List<CellInfo> cellInfoList = tm.getAllCellInfo();
List<Integer> dbms = new ArrayList<>();
if (null != cellInfoList) {
for (CellInfo cellInfo : cellInfoList) {
try {
int dbm = 1;
if (cellInfo instanceof CellInfoGsm) {
CellSignalStrengthGsm cellSignalStrengthGsm = ((CellInfoGsm) cellInfo).getCellSignalStrength();
dbm = cellSignalStrengthGsm.getDbm();
} else if (cellInfo instanceof CellInfoCdma) {
CellSignalStrengthCdma cellSignalStrengthCdma = ((CellInfoCdma) cellInfo).getCellSignalStrength();
dbm = cellSignalStrengthCdma.getDbm();
} else if (cellInfo instanceof CellInfoWcdma) {
CellSignalStrengthWcdma cellSignalStrengthWcdma = ((CellInfoWcdma) cellInfo).getCellSignalStrength();
dbm = cellSignalStrengthWcdma.getDbm();
} else if (cellInfo instanceof CellInfoLte) {
CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) cellInfo).getCellSignalStrength();
dbm = cellSignalStrengthLte.getDbm();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q && cellInfo instanceof CellInfoNr) { // 5G
CellSignalStrengthNr cellSignalStrengthNr = (CellSignalStrengthNr) ((CellInfoNr) cellInfo).getCellSignalStrength();
dbm = cellSignalStrengthNr.getDbm();
}
dbms.add(dbm);
} catch (Exception ignore) {
}
}
}
Collections.sort(dbms);
if (dbms.size() > 1) {
callback.onGetMobileInfoResult(dbms.get(dbms.size() - 1));
} else {
callback.onGetMobileInfoResult(1);
}
}
}
之后,我们可以直接封装方法。
public static void getMobileSignalStrength(@NonNull final Context context,
@NonNull final InfoCallback callback) {
final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
if (tm == null) {
callback.onGetMobileInfoResult(1);
return ;
}
final MyPhoneStateListener myPhoneStateListener = new MyPhoneStateListener();
myPhoneStateListener.init(context, new GetMobileInfoCallback() {
@Override
public void onGetMobileInfoResult(int rssi) {
myPhoneStateListener.unRegister();
callback.onGetMobileInfoResult(rssi);
}
});
myPhoneStateListener.register();
}
核心思想就是用PhoneStateListener来监听信号强度,当信号强度刷新时,触发方法,生成一系列相关的Cell对象。我们获取到所有CellInfo对象,然后取其中数值最小的dbm即可,或者也可以取这些dbm的平均值。
<font color=red>注意:这个方法会定时回调一次,所以当我们获取到我们想要的数据后,需要调用tm.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);来取消注册</font>
对于5G,通过查看源码发现其实就是多了一个实例对象,其他获取方法都一样。
关于RSSI
<font color=red>Rssi意思就是信号强度的意思,与此有关系的还有一个RSRP,RSRP代表信号功率。</font>
关于两者的详细含义,具体看百度百科。
-
RSRP(Reference Signal Receiving Power)是在某个Symbol内承载Reference Signal的所有RE上接收到的信号功百率的平均值;
-
RSSI(Received Signal Strength Indicator)则是在这个Symbol内接收到的所有信号(包括度导频信号和数据信号,邻区干扰信号,噪音信号等)功率的平均值,是指接收的信号强度指示,是无问限发送层的可选用部分,用来判定链接的质量,以及是否增大广播发送强答度;
-
RSRQ(Reference Signal Receiving Quality)则是RSRP和RSSI的比值,当然因回为两者测量所基于的带宽可能不同,会用一个系数来调整,也就是 RSRQ = N*RSRP/RSS
网友评论