在安卓系统中获取GSM信号强度

5

我是一个安卓新手。

如何以百分比(1-100%)的形式获取GSM信号强度?


1
你有去这里吗 http://www.firstdroid.com/2010/05/12/get-provider-gsm-signal-strength/ - PedroAGSantos
如果这是您要查找的内容,请在提问之前进行搜索。 - PedroAGSantos
4个回答

6
该提问者应该提供更多信息或反馈。话虽如此...
这个问题并不琐碎:由于它是以分贝为单位的比例尺,因此当信号较弱时,较小的变化会产生更大的影响,而当数值较高时,较大的变化则不那么重要。这就是为什么很抱歉地说,所有其他答案都将得到不准确的值,这些值将无法匹配显示在手机上的值。
假设你已经有了一个SignalStrength对象(如果没有,还有另一个不错的答案介绍了如何创建),在Marshmallow中,可以使用方法getGsmLevel()(还有其他信号和甚至组合的方法)来解决这个问题,它返回一个线性化的0-4比例尺。您可以从类SignalStrength中检查源代码。
/**
 * Get gsm as level 0..4
 *
 * @hide
 */
public int getGsmLevel() {
    int level;
    // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5
    // asu = 0 (-113dB or less) is very weak
    // signal, its better to show 0 bars to the user in such cases.
    // asu = 99 is a special case, where the signal strength is unknown.
    int asu = getGsmSignalStrength();
    if (asu <= 2 || asu == 99) level = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
    else if (asu >= 12) level = SIGNAL_STRENGTH_GREAT;
    else if (asu >= 8)  level = SIGNAL_STRENGTH_GOOD;
    else if (asu >= 5)  level = SIGNAL_STRENGTH_MODERATE;
    else level = SIGNAL_STRENGTH_POOR;
    if (DBG) log("getGsmLevel=" + level);
    return level;
}

将0-100%的刻度用于此事不具有意义,因为这是一个小的粒度。因此通常使用0-4范围,并且在这种方法中已经线性化。如果不是在Marshmallow中,则只需适应此方法以接收对象作为值。如果您真的需要某些原因的0-100范围,您应该使用dB到线性转换函数,但我不知道GSM信号的增益因子。


getGsmLevel仅适用于特定版本。有通用的解决方案吗? - gtzinos
当然可以:只需获取 getGsmLevel() 的代码并将其调整为一个静态方法,该方法以 SignalStrength 对象作为参数,并使用它来获取调用 getGsmSignalStrength() 的 ASU 值,该方法在所有版本中都存在。 - Yago Méndez Vidal

3
    public class MyActivity extends Activity {
    public static final int UNKNOW_CODE = 99;
    int MAX_SIGNAL_DBM_VALUE = 31;

    TelephonyManager tel;
MyPhoneStateListener myPhoneStateListener;

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    View view = getLayoutInflater().inflate(R.layout.activity_about, null);
    setContentView(view);

    myPhoneStateListener = new MyPhoneStateListener();
    tel = (TelephonyManager) PpsApplication.getAppContext().getSystemService(Context.TELEPHONY_SERVICE);
    tel.listen(myPhoneStateListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
}

private class MyPhoneStateListener extends PhoneStateListener {
    /* Get the Signal strength from the provider, each tiome there is an update */
    @Override
    public void onSignalStrengthsChanged(SignalStrength signalStrength) {
        super.onSignalStrengthsChanged(signalStrength);

        if (null != signalStrength && signalStrength.getGsmSignalStrength() != UNKNOW_CODE) {
            int signalStrengthPercent = calculateSignalStrengthInPercent(signalStrength.getGsmSignalStrength());
            viewModel.setSignalStrengthString(IntegerHelper.getString(signalStrengthPercent));
        }
    }
}

private int calculateSignalStrengthInPercent(int signalStrength) {
    return (int) ((float) signalStrength / MAX_SIGNAL_DBM_VALUE * 100);
}

}

1
我能否获取类似于1/4的GSM信号强度状态?我需要一个适用于4.x-7.x的解决方案。 - gtzinos

2

请注意,.getGsmSignalStrength();现在只返回0-5、99之间的信号强度条。

实际值现已隐藏。您仍然可以使用反射获取它们:

                int strength=signalStrength.getGsmSignalStrength();//number of bars not ASU
                Log.v("Mobile","BARS: "+strength);
                try{//Actual signal strength is hidden
                    Class classFromName = Class.forName(SignalStrength.class.getName());
                    java.lang.reflect.Method method = classFromName.getDeclaredMethod("getAsuLevel");//getDbm
                    strength = (int) method.invoke(signalStrength);
                }catch (Exception ex){Log.v("Mobile","cant retreive");}
                if (strength == 99 ) { Log.v("Mobile", "ERROR!  GSM signal strength not available!");return;}//99 = Unknown
                if (strength == 255) { Log.v("Mobile", "ERROR!  UMTS signal strength not available!");return;}//255 = Unknown

以上示例仅适用于ASU,似乎比Dbm更有效。获得ASU值后,您可以将其转换为百分比:

                Log.v("Mobile","ASU: "+strength);
                //Data.mobile_signal=strength*20;//Number of bars 0-5
                //Data.mobile_signal = 100-((strength-113)/62);//GSM DBM
                Data.mobile_signal =(int)((double)strength*100/31);//GSM ASU
                Data.mobile_signal =(int)((double)strength*100/91);//UMTS ASU
               Log.v("Mobile","Set GSM signal from "+strength+" to "+Data.mobile_signal);

作为提醒,此内容适用于您有GSM信号而非CDMA信号的情况。使用TelephonyManager.getPhoneType()来确定是哪种类型:1=GSM,2=CDMA,3=SIP。
但等等!这里说我只有50%的信号强度,但我有5个信号条!这是错误的!
嗯,并不完全是这样。除非您的手机就在发射器前面,否则它可能不会达到100%。但是50%的信号大约相当于100%的质量。所以从这里开始,您需要变得有创意。

它实际上返回值0-31,99。请参考此处。顺便问一下,你有没有想过为什么它在大多数情况下返回99? - Alex Newman
不适用于LTE UMTS信号,它会给你0-91,255。当我第一次遇到这个问题时,我也感到困惑。我本来期望的最大值是31,但实际上我收到了47的数值!99或255表示没有可用数据。 - R M

0
更好的解决方案是使用:
signalStrength.level

此函数返回一个0到4的值,您应该从您的Android设备中熟悉它。可以将其视为信号条数。这在GSM和CDMA上都兼容。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接