In this tutorial I would show how to measure the signal strengths in Android. Since Android is a mobile operating system, therefore measuring signal strengths from device itself would be a very easy task. Android onSignalStrengthsChanged is a method in Android PhoneStateListener class which observes the changes in telephony states of a device. In my previous tutorials I utilized the power of Android PhoneStateListener class to determine the changes in message waiting indicator, service state, data activity and also to monitor the change in cell info. If you wish to read the full series, links are below:
1) Android PhoneStateListener Example
2) Android onDataConnectionStateChanged – Detect Network Type
3) Android onSignalStrengthsChanged – LTE Strength Measurement
To listen the change in signal strengths a flag PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
is used in the listen method of TelphonyManager
class. By using this flag we will start getting the callbacks in onSignalStrengthsChanged(SignalStrength signalStrength)
method whenever the signal strength of network changes.
No Permissions needed
Now the interesting part here is that, to use the Android onSignalStrengthsChanged method we don’t need to add any permissions in our manifest. I tested this on a Kitkat 4.4.4 device.
Lets start with PhoneStateListener Activity:
package com.truiton.phonestatelistener; import android.support.v7.app.ActionBarActivity; import android.telephony.PhoneStateListener; import android.telephony.TelephonyManager; import android.annotation.TargetApi; import android.os.Build; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class PhoneStateListenerActivity extends ActionBarActivity { TelephonyManager tManager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_phone_state_listener); tManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); tManager.listen(new CustomPhoneStateListener(this), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.phone_state_listener, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
As you can see in the above class, a custom Android PhoneStateListener is used to capture the updates of signal strengths with the help of TelephonyManager class. as soon as the listener is registered, we start receiving callbacks in Android PhoneStateListener onSignalStrengthsChanged method.
Android onSignalStrengthsChanged LTE measurement
LTE (Long-Term Evolution) is a new emerging standard for wireless communication. LTE is an upgrade for both GSM/UMTS and CDMA2000 Networks. Here the good part is, android supports LTE standard. With the help of PhoneStateListener and Android onSignalStrengthsChanged method we can measure LTE signal strengths. In this Android onSignalStrengthsChanged – LTE Strength Measurement tutorial I would show how to measure the signal strength for LTE network by using the Java Reflection APIs. Lets define the custom PhoneStateListener:
package com.truiton.phonestatelistener; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import android.content.Context; import android.telephony.PhoneStateListener; import android.telephony.SignalStrength; import android.util.Log; public class CustomPhoneStateListener extends PhoneStateListener { Context mContext; public static String LOG_TAG = "CustomPhoneStateListener"; public CustomPhoneStateListener(Context context) { mContext = context; } /** * In this method Java Reflection API is being used please see link before * using. * * @see <a * href="http://docs.oracle.com/javase/tutorial/reflect/">http://docs.oracle.com/javase/tutorial/reflect/</a> * */ @Override public void onSignalStrengthsChanged(SignalStrength signalStrength) { super.onSignalStrengthsChanged(signalStrength); Log.i(LOG_TAG, "onSignalStrengthsChanged: " + signalStrength); if (signalStrength.isGsm()) { Log.i(LOG_TAG, "onSignalStrengthsChanged: getGsmBitErrorRate " + signalStrength.getGsmBitErrorRate()); Log.i(LOG_TAG, "onSignalStrengthsChanged: getGsmSignalStrength " + signalStrength.getGsmSignalStrength()); } else if (signalStrength.getCdmaDbm() > 0) { Log.i(LOG_TAG, "onSignalStrengthsChanged: getCdmaDbm " + signalStrength.getCdmaDbm()); Log.i(LOG_TAG, "onSignalStrengthsChanged: getCdmaEcio " + signalStrength.getCdmaEcio()); } else { Log.i(LOG_TAG, "onSignalStrengthsChanged: getEvdoDbm " + signalStrength.getEvdoDbm()); Log.i(LOG_TAG, "onSignalStrengthsChanged: getEvdoEcio " + signalStrength.getEvdoEcio()); Log.i(LOG_TAG, "onSignalStrengthsChanged: getEvdoSnr " + signalStrength.getEvdoSnr()); } // Reflection code starts from here try { Method[] methods = android.telephony.SignalStrength.class .getMethods(); for (Method mthd : methods) { if (mthd.getName().equals("getLteSignalStrength") || mthd.getName().equals("getLteRsrp") || mthd.getName().equals("getLteRsrq") || mthd.getName().equals("getLteRssnr") || mthd.getName().equals("getLteCqi")) { Log.i(LOG_TAG, "onSignalStrengthsChanged: " + mthd.getName() + " " + mthd.invoke(signalStrength)); } } } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } // Reflection code ends here } }
Before moving forward let me give a brief intro to Java Reflection API. Reflection API is used to examine or modify the run-time behavior of any application in running in virtual machine (DVM or ART). Since this is a very powerful API, it is advised to use this only if you know what you are doing. To read more about reflection API, please go here. Coming back to this tutorial, here we are using the reflection APIs to invoke following methods which are not included in Android APIs:
getLteSignalStrength
– Returns LTE signal strengthgetLteRsrp
– Returns LTE Reference Signal Received PowergetLteRsrq
– Returns LTE Reference Signal Received QualitygetLteRssnr
– Returns LTE rssnrgetLteCqi
– Returns LTE Channel Quality Indication
Android Signal Strength
Although if we go by standard Android APIs, whenever Android onSignalStrengthsChanged method is invoked an object of SignalStrength
is passed as an argument. As its shown in the above code, with this object we can determine the type of signal being receiving on device. It could be any type of network like GSM, CDMA or EVDO, hence one can get signal strength as well. Hope this helped you out, if it did please share it with your friends.
Born in New Delhi, India. A software engineer by profession, an android enthusiast and an evangelist. My motive here is to create a group of skilled developers, who can develop something new and good. Reason being programming is my passion, and also it feels good to make a device do something you want. In a very short span of time professionally I have worked with many tech firms. As of now too, I am employed as a senior engineer in a leading tech company. In total I may have worked on more than 20 projects professionally, and whenever I get spare time I share my thoughts here at Truiton.
Hi Mohit,
Android standard API never returns the neighbor cells for LTE.
Is there any workaround?
Thanks & Regards,
Akshit Chauhan
Hey
That was a very good article covering LTE. Now, I need to look at UMTS signal strengths. I know there is list that can give me WCDMA details, but my target is phone has only API 16. Do you know on how I would be able to get the UMTS signal information.
Thanks in advance
Hi Mohit, Can you please suggest methods for capturing SINR and RSSI values on LTE network
Hi Sir,How to pass signalstrength value from customphonestatelistener to tabfragment activity.
Hi,
Please refer to these links:
https://www.truiton.com/2015/12/android-activity-fragment-communication/
https://www.truiton.com/2015/06/android-tabs-example-fragments-viewpager/