I want to detect if a phone has a slow internet connection or high-speed internet.
Now they have deprecated NetworkInfo and suggesting that we should use ConnectivityManager#getNetworkCapabilities using this I am able to get the signal strength but not able to figure out how to use integer value returned by networkCapabilities.getSignalStrength()
It is returning an Integer value I am getting these values (-39, -71, -31).
My question is how should we define that signal strength is good/poor.
Here is my code to get Signal Strength:
ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
Network activeNetwork = cm.getActiveNetwork();
NetworkCapabilities networkCapabilities = cm.getNetworkCapabilities(activeNetwork);
int signalStrength = networkCapabilities.getSignalStrength();
First this is a directive approach rather than being a direct answer to the question.
int signalStrength = networkCapabilities.getSignalStrength();
Doc:
This is a signed integer, with higher values indicating a stronger signal. The exact units are bearer-dependent. For example, Wi-Fi uses the same RSSI units reported by wifi code.
This means that signalStrength holds a value that is relevant to the signal bearer; for instance if the bearer is WiFi, then the signalStrength will reflect the same WiFi RSSI units.
RSSI, or “Received Signal Strength Indicator,” is a measurement of how well your device can hear a signal from an access point or router. It’s a value that is useful for determining if you have enough signal to get a good wireless connection.
So, you need to map those units to some quality gauge to know whether the signal is weak/strong. This is communication/signal dependent rather than a programming point of view... This thread and also this one may help you for that in case of WiFi bearer.
But you need to customize this quality level for other types of signal bearers the same-wise according to their RSSI units.
GSM signal for instance you may use CellSignalStrengthGsm which has getRssi()
CellSignalStrengthLte is for LTE and so on.
You may also get the level of signal strength from the android.telephony API's SignalStrength class... there is a getLevel() method which returns an integer from 0 to 4 representing the general signal quality. Here you can find a listener to that.
Related
I would like to get the overall signal strenght received with the mobile antenna. Ideally, I would love to get the electric field measured with my phone antenna.
I did found a lot of methods to get the signal strength but they all give a specific signal strenth (either GSM, Wifi, GPRS ...) but not the overall signal. Moreover, if there are no SIM card in the phone, the GSMsignalStrength will return 0 or null and even if there is a SIM card, I will only get the strength of the signal of that operator only.
Could you please help me?
I simply want to check if my device is receiving GSM signals or not. I know about SignalStrength class and its getGsmSignalStrength(). I have worked with PhoneStateListener and onSignalStrengthsChanged().
But even where I am not receiving any signals, I still get greater than 0 GSM signals strength, as shown in the screenshot:
See the signals level, its not even low, its red crossed. And the getGsmSignalStrength() returned me 16. (Current is a different number, please ignore it.)
If you are only interested in the GSM signal from your operator then use getMnc() from CellIdentityGsm to establish if the signal you are measuring is valid.
If you want the GSM signal only when the device is in service (ie successfully connected to a network) then use the ServiceState checker to establish what state the device is in.
As per above comments, the symptoms indicate that you are measuring other operators' GSM signals.
How do I detect when the GSM signal strength is low and the cellular network is lost?
What about dual SIM devices?
Android: how to detect “no carrier” SIM card mode ?
The PhoneStateListener class is designed to serve this purpose. When using it, you can get callbacks when the GSM signal bound to your current provider is changing.
Make sure you have the following android.intent.action.PHONE_STATE set in your manifest file.
Next, you'll need to invoke the TelephonyManager and bind your PhoneStateListener to it :
TelephonyManager telManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
telManager.listen(this.phoneListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
You can implement your PhoneStateListener as such :
private final PhoneStateListener phoneListener = new PhoneStateListener() {
#Override
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
Log.d("onSignalStrengthsChanged", "The new singal strength is "
+ signalStrength.getGsmSignalStrength());
}
};
GSM signal strengths values are defined in TS 27.007 8.5. Basically a value of 0 is low, a value of 31 is good, and a value of 99 means not known or not detectable. Valid values are (0-31, 99) as stated in the Android Developers manual.
The above covers GSM signals, so if you are only interested in GSM signals, stick to my previous example. If you might be interested in stating whether a data network is available or not due to a lack of signal strength, you can also get other signal values for all the available data networks :
SignalStrength.getCdmaDbm() returns the RSSI value in dBm for CDMA networks.
SignalStrength.getEvdoDbm() returns the RSSI value in dBm for Evdo networks.
You can know what is the type of the current data network by calling the TelephonyManager.getNetworkType() method.
What about dual SIM devices ?
I don't know, never worked on them. However I don't see why the above may not be applicable to multi-SIM devices. It should be working as such.
I am looking through the documentation on the SignalStrength class for an app I plan to make, but there is a lot of telecommunications terminology that I'm not very familiar with. I was wondering if anyone could briefly shed some light on some of the methods in this class, specifically these:
int getCdmaDbm()
Get the CDMA RSSI value in dBm
int getCdmaEcio()
Get the CDMA Ec/Io value in dB*10
int getEvdoDbm()
Get the EVDO RSSI value in dBm
int getEvdoEcio()
Get the EVDO Ec/Io value in dB*10
int getEvdoSnr()
Get the signal to noise ratio.
int getGsmBitErrorRate()
Get the GSM bit error rate (0-7, 99) as defined in TS 27.007 8.5
int getGsmSignalStrength()
Get the GSM Signal Strength, valid values are (0-31, 99) as defined in TS 27.007 8.5
As I understand it, GSM and CDMA are two different protocols for mobile cellular networks, EVDO is the standard by which data is moved through CDMA, and HSPA is the equivalent data standard on GSM. Why then, are there no corresponding HSPA methods, as well as no getCDMASignalStrength() or getCDMABitErrorRate()? I'm also not too clear on what RSSI or Ec/Io are.
Ok, Here we go.
You got the part that GSM is different than CDMA correctly.
Also The part that EVDO is the data transport protocols on CDMA while HSPA is the equivalent in GSM.
The Modulation (data representation in the signal) is completely different between CDMA and GSM. That is why you can't use equivalent units (B.E.R) to calculate the quality of a signal sent by those different protocols.
Now for the measurement values we got:
DBM is a pure signal power measurement unit (in decibel) the more you get the higher reception you have. This covers (getCdmaDbm() and getGsmSignalStrength())
Bit Error Rate: Is a simple quality measurement unit for GSM link, the lower it is the higher the quality of the received signal (independent of signal strength).
EC/IO Represents the ration of Power of signal received to the power of interference signal. the higher this value the higher the quality of the signal you are getting (Regardless of its strength) . in details
RSSI is a signal power measurement unit also.
Now the reason there is two APIS for RSSI and ECIO is that EVDO is carried on part of the CDMA signal so it makes sense that it may have different quality figures than the whole CDMA signal.
hope that helps
RSSI is the raw power measured in the channel. Ec/Io is the Energy of the Carrier relative to the Interference and Noise, so it is a measure of the quality of the signal. dBm is the unit of RF power relative to 1 milliwatt, on the dB (Decibel) scale. EVDO SNR is the Signal to Noise Ratio, which is another representation of the quality of the signal in the presence of interference.
RSSI- received signal strength indicator. It's the amount of power in the signal.
ECIO- it's another ratio of power density.
Why CDMA doesn't have signal strength- my guess is that Dbm is a good enough measure of it, but I can't swear to that.
If you need to use signal strength, you're going to need to do serious research. Unless all you're doing is the equivalent of showing how many bars of signal you have. Even that's non-trivial, the iphone got it wrong for years.
In my application, TelephonyManager has a PhoneStateListener set to listen to LISTEN_SIGNAL_STRENGTHS. I get a call to onSignalStrengthsChanged and get the SignalStrength. But since SignalStrength has multiple methods for getting the signal strength, (for cdma, evdo and gsm) I'm not sure which one to use.
How do I correctly determine which of cmda, evdo and gsm methods to use?
For GSM, the signal strength structure has a isGsm flag. If it's true, then you know it's GSM and can ignore the others.
When isGsm is false, apparently the use of cdma and evdo is carrier specific. Some carrier uses cmda for voice, evdo for data or vice versa. In short, there appears to be no way to determine programmatically which one is being used for data. As I'm not an expert on this, I could very well be wrong.