在 Android 中检索 GSM 信号强度

发布于 2024-12-01 11:59:23 字数 61 浏览 0 评论 0原文

我是 Android 新手。

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

I'm a newbie to Android.

How do I get the GSM signal Strength in terms of percentage (1 - 100%)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

傲影 2024-12-08 11:59:23

提出问题的用户应该提供更多信息或反馈。也就是说......

这个问题根本不是微不足道的:因为它是以分贝为单位的,所以它不是线性的,因此当信号较低时,较小的变化会产生更大的影响,而当信号值较高时,较大的变化则不太重要。这就是为什么我很遗憾地说所有其他答案都会得到不准确的值,与手机上显示的值不匹配。

假设您已经有一个 SignalStrength 对象(如果没有,还有另一个很好的答案展示了如何做到这一点),在 Marshmallow 中它可以通过方法 getGsmLevel() 解决(有也是所有其他信号甚至组合信号的方法),返回线性化比例 0-4。您可以从类 信号强度

/**
 * 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 信号中的增益因子。

The user who asked should have provided more information or feedback. That said...

The question is not trivial at all: since it's a scale in decibels it's not linear and thus smaller changes have a greater impact when the signal is low, while bigger changes are less important when the value is high. That's why I'm sorry to say that all the other answers will be getting inaccurate values that would not match the one displayed on the phone.

Assuming you already have a SignalStrength object (if not, there's another nice answer that shows how to do it), in Marshmallow it's solved with the method getGsmLevel() (there are also methods for all other signals and even combined) that returns a linearized scale 0-4. You can check the source code from the class 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;
}

Having a 0-100% scale it's not significative because it's a small granularity for this matter, that's why it's more commonly used a 0-4 range and in this method it's already linearized. If not in Marshmallow, just adapt this method to receive the object as a value. If you'd really need a 0-100 range for some reason you should use a dB to linear conversion function, but I'm unaware of the gain factor in GSM signals.

酒与心事 2024-12-08 11:59:23
    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);
}

}
    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);
}

}
几味少女 2024-12-08 11:59:23

请注意 .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% 的质量。所以从这里开始你必须发挥创意。

Be aware that .getGsmSignalStrength(); now only returns bars: 0-5,99

The actual values are now hidden. You can still get to them using reflection:

                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

The above example is for ASU only, which seems to work better than Dbm. After you get the ASU value, you can then dump it into percentage:

                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);

As a reminder, this is for when you have a GSM signal not a CDMA signal. Use TelephonyManager.getPhoneType(); to determine which:
1=GSM, 2=CDMA, 3=SIP

BUT WAIT! This says I only have a 50% signal strength yet I have 5 bars! This is wrong!

Well, not exactly. Unless your phone is right in front of the transmitter, it's probably not going to be 100%. But 50% signal is about 100% quality. So from here you have to get creative.

ゞ记忆︶ㄣ 2024-12-08 11:59:23

更好的解决方案是使用:

signalStrength.level

这会返回一个 0 到 4 的值,您应该在 Android 设备上熟悉该值。将其视为信号的条数。这与 GSM 和 CDMA 兼容。

A better solution is to use:

signalStrength.level

This returns a 0 to 4 value that you should be familiar with from your android device. Think of it as the number of bars of signal. This is compatible across GSM and CDMA.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文