get SignalStrength without Using PhoneStateListener onSignalStrengthchanged - android

does anyone know how to get the signal strength without having to call the onSignalStrengthChanged. The problem with onSignalStrengthchanged is that is it called when the signal strength changes and I need to get the value of signalstrength according to a different criteria.
Thanks in advance.

On API level 17 only, here's some code that can be used in an Activity (or any other Context child class):
import android.telephony.CellInfo;
import android.telephony.CellInfoCdma;
import android.telephony.CellInfoGsm;
import android.telephony.CellInfoLte;
import android.telephony.CellSignalStrengthCdma;
import android.telephony.CellSignalStrengthGsm;
import android.telephony.CellSignalStrengthLte;
import android.telephony.TelephonyManager;
try {
final TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
for (final CellInfo info : tm.getAllCellInfo()) {
if (info instanceof CellInfoGsm) {
final CellSignalStrengthGsm gsm = ((CellInfoGsm) info).getCellSignalStrength();
// do what you need
} else if (info instanceof CellInfoCdma) {
final CellSignalStrengthCdma cdma = ((CellInfoCdma) info).getCellSignalStrength();
// do what you need
} else if (info instanceof CellInfoLte) {
final CellSignalStrengthLte lte = ((CellInfoLte) info).getCellSignalStrength();
// do what you need
} else {
throw new Exception("Unknown type of cell signal!");
}
}
} catch (Exception e) {
Log.e(TAG, "Unable to obtain cell signal information", e);
}
Previous versions of Android require you to call the listener, there is no other alternative (see this link).
Also ensure that your application contains the appropriate permissions.

you can access SignalStrength via reflection call. Please go through the link for implementation http://blog.ajhodges.com/2013/03/reading-lte-signal-strength-rssi-in.html

There is another API in Android called CellInfo. But I am not sure whether signal strength returned by OnSignalStrengthsChanged() and CellInfo is same or not.
https://developer.android.com/reference/android/telephony/CellSignalStrength.html

Based on Andre's answer above, in Kotlin you can use this one-liner (again API 17+):
fun getRadioSignalLevel(): Int {
return when (val info = telephonyManager.allCellInfo?.firstOrNull()) {
is CellInfoLte -> info.cellSignalStrength.level
is CellInfoGsm -> info.cellSignalStrength.level
is CellInfoCdma -> info.cellSignalStrength.level
is CellInfoWcdma -> info.cellSignalStrength.level
else -> 0
}
}

Related

How to program android application to switch default SIM for mobile/cellular Data automatically

I am developing an Android App to be used in Android OS mobile Point of Sale (POS) terminals (Android 7) that has two SIM Slots. I need the App, upon app start, to first test the signal strength in both SIMs and automatically select to work using the SIM with the best signal strength. Afterwards, to periodically (every 15/30/60 mins according to the chosen settings) check the signal strength again for both SIMS, and automatically switch default SIM for Data to the SIM with the best signal strength.
So far I am able to make the App measure the signal strength in both SIMs, and display them to the user, so as to select the SIM to work with. This is achieved using Cellinfo in telephonyManager function and the following code which I found here:
private static String getSignalStrength (Context context) throws SecurityException {
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String strength = "";
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// TODO: Consider calling
// ActivityCompat#requestPermissions
// here to request the missing permissions, and then overriding
// public void onRequestPermissionsResult(int requestCode, String[] permissions,
// int[] grantResults)
// to handle the case where the user grants the permission. See the documentation
// for ActivityCompat#requestPermissions for more details.
return "";
}
List<CellInfo> cellInfos = telephonyManager.getAllCellInfo(); //This will give info of all sims present inside your mobile
if(cellInfos != null) {
for (int i = 0 ; i < cellInfos.size() ; i++) {
if (cellInfos.get(i).isRegistered()) {
if (cellInfos.get(i) instanceof CellInfoWcdma) {
CellInfoWcdma cellInfoWcdma = (CellInfoWcdma) cellInfos.get(i);
CellSignalStrengthWcdma cellSignalStrengthWcdma = cellInfoWcdma.getCellSignalStrength();
strength += String.valueOf(cellSignalStrengthWcdma.getDbm());
} else if (cellInfos.get(i) instanceof CellInfoGsm) {
CellInfoGsm cellInfogsm = (CellInfoGsm) cellInfos.get(i);
CellSignalStrengthGsm cellSignalStrengthGsm = cellInfogsm.getCellSignalStrength();
strength += String.valueOf(cellSignalStrengthGsm.getDbm());
} else if (cellInfos.get(i) instanceof CellInfoLte) {
CellInfoLte cellInfoLte = (CellInfoLte) cellInfos.get(i);
CellSignalStrengthLte cellSignalStrengthLte = cellInfoLte.getCellSignalStrength();
strength += String.valueOf(cellSignalStrengthLte.getDbm());
} else if (cellInfos.get(i) instanceof CellInfoCdma) {
CellInfoCdma cellInfoCdma = (CellInfoCdma) cellInfos.get(i);
CellSignalStrengthCdma cellSignalStrengthCdma = cellInfoCdma.getCellSignalStrength();
strength += String.valueOf(cellSignalStrengthCdma.getDbm());
}
strength+=";";
}
}
}
return strength;
}
I am now stuck at how to switch the default SIM for data automatically, and without the need for user intervention.

In android, How to change the default Cell that the phone is using

I use getAllCellInfo api to get all the cell Information list , choose the biggest Signal Strength level from the list. And use reflect to set its isRegistered value is true. but the network signal level does not change in my phone.
the code:
List<CellInfo> infos = tel.getAllCellInfo();
if (infos != null) {
for (CellInfo info1 : infos) {
if (info1 instanceof CellInfoLte) {
CellSignalStrengthLte cellSignalStrengthLte = ((CellInfoLte) info1).getCellSignalStrength();
try {
Method setRegistered = ((CellInfoLte) info1).getClass().getMethod("setRegistered", Boolean.TYPE);
if (cellSignalStrengthLte.getLevel() == 4 && !isFirstTime) {
setRegistered.invoke(((CellInfoLte) info1), true);
isFirstTime = true;
} else {
setRegistered.invoke(((CellInfoLte) info1), false);
}
} catch (Exception e) {
}
}
}
}
Is there any way to let my phone use the cell that has biggest signal level ?

getCellSignalStrength() always reports same value: -51

I'm trying to read the actual cell signal strength from my Samsung S6, but getDbm() always returns -51b (type is WCDMA).
(I call that function in a loop and every time it is -51.)
TelephonyManager telephonyManager = (TelephonyManager) APIDispatcher.getActivity().getApplicationContext().getSystemService(Context.TELEPHONY_SERVICE);
for (final CellInfo info : telephonyManager.getAllCellInfo()) {
if (info instanceof CellInfoGsm) {
CellSignalStrengthGsm gsm = ((CellInfoGsm) info).getCellSignalStrength();
result = gsm.getDbm();
Log.i("CellSignalStrengthGsm", "strength:"+result);
} else if (info instanceof CellInfoCdma) {
CellSignalStrengthCdma cdma = ((CellInfoCdma) info).getCellSignalStrength();
result = cdma.getDbm();
Log.i("CellSignalStrengthCdma", "strength:"+result);
} else if (info instanceof CellInfoWcdma) {
CellSignalStrengthWcdma wcdma = ((CellInfoWcdma) info).getCellSignalStrength();
result = wcdma.getDbm();
Log.i("CellSignalStrengthWcdma", "strength:"+result);
} else if (info instanceof CellInfoLte) {
CellSignalStrengthLte lte = ((CellInfoLte) info).getCellSignalStrength();
result = lte.getDbm();
Log.i("CellSignalStrengthLte", "strength:"+result);
}
}
The "SIM Card Status" of my mobile reports -103 dBm (+/- 2 dBm).
I never get a different value other than -51.
I also tried to install a listener with:
telephonyManager.listen(new SignalStrengthListener(), PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);
but the callbak is never being called.
I have no idea anymore. Maybe you?

CellIdentityLte getCi() returning -1 in android

I have a method which returns cell id for LTE device, but on some devices it is returning -1. Here is the method:
public int getCellId() {
int cellId = Integer.MAX_VALUE;
CellInfo cellInfo = null;
List<CellInfo> allCellInfo = telephonyManager.getAllCellInfo();
if(allCellInfo!= null && allCellInfo.size()>0)
cellInfo = allCellInfo.get(0);
if (cellInfo instanceof CellInfoLte) {
CellInfoLte cellInfoLte = (CellInfoLte) cellInfo;
if (cellInfoLte != null) {
cellId = cellInfoLte.getCellIdentity().getCi();
}
}
return cellId;
}
You have it implemented correctly, unfortunately not all manufacturers implement all the Android APIs correctly, especially around the telephony area. Sometimes all the LTE values will be -1 also, sometimes just the CI.

onCellInfoChanged() callback is always null

i am trying to get a list of all available cells the device can find. But i am stuck, as my CellInfo is always null and i don't figure why. Can someone give me a hint? There is pretty few info on onCellInfoChanged() at google.
MainActivity:
CellListener cellListener = new CellListener(this);
cellListener.start();
CellListener:
public class CellListener extends PhoneStateListener {
private static final String TAG = "CellListener";
private TelephonyManager telephonyManager = null;
private PhoneStateListener listener = null;
private String newCell = null;
private int events = PhoneStateListener.LISTEN_CELL_LOCATION | PhoneStateListener.LISTEN_CELL_INFO;
private Context context = null;
public CellListener(Context context) {
this.context = context;
}
public void start() {
telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
CellLocation.requestLocationUpdate();
telephonyManager.listen(this, events);
}
#Override
public void onCellInfoChanged(List<CellInfo> cellInfo) {
Log.i("CellListener","onCellInfoChanged(List<CellInfo> cellInfo) ");
super.onCellInfoChanged(cellInfo);
if(cellInfo == null) return; // this always null here
for (CellInfo c : cellInfo) {
Log.i("CellListener"," c = "+c);
}
}
#Override
public void onCellLocationChanged(CellLocation location) {
if (!(location instanceof GsmCellLocation)) {
return;
}
GsmCellLocation gsmCell = (GsmCellLocation) location;
String operator = telephonyManager.getNetworkOperator();
if (operator == null || operator.length() < 4) {
return;
}
newCell = operator.substring(0, 3) + ':' + operator.substring(3) + ':'
+ gsmCell.getLac() + ':' + gsmCell.getCid();
Log.i(TAG,"newCell = "+newCell);
}
}
Logcat:
11-18 14:50:23.806: I/CellListener(4953): newCell = 262:02:4311:99031735
11-18 14:50:23.814: I/CellListener(4953): onCellInfoChanged(List<CellInfo> cellInfo)
As you can see both events (onCellInfoChanged & onCellLocationChanged) get triggered once and the latter is correctly returning the current cell the device is using.
The real reason you are only being called exactly once and with null as an argument is the following: there appears to be a rate-limiting setting in place by default, as can be observed in the "testing" app, which can be accessed by dialing *#*#INFO#*#* (i.e. *#*#4636#*#*).
In the testing app, choose "Phone Information" and scroll down to the button CELLINFOLISTRATE xxxx, in your case presumably CELLINFOLISTRATE 2147483647. As 2147483647 == MAX_INT, this probably means no calls at all
For me (stock android 6.0, nexus 6), there's the a choice between MAX_INT (one call with null), 0 and 1000.
I'm not 100% sure what these values mean, but presumably the 0 stands for instant (and thus very many) calls, and 1000 for something like at least a second between calls. Keep in mind though, this is pure speculation.
I will edit this answer as I find out more, for example by looking at the implementation of said testing app.
#bofredo: It is returning null because you haven't defined CellInfo yet.
Can't see from your question if you're using CDMA, GSM, or LTE. From memory, CDMA doesn't seem to return anything, but GSM (CellInfoGsm) and LTE (CellInfoLte) do. So doing something like for example:
CellInfoGsm cellInfoGsm = (CellInfoGsm) cellInfo;
CellInfoLte cellInfoLte = (CellInfoLte) cellInfo;
will return an instance of CellInfoGsm or CellInfoLte which will then allow you to retrieve more information about a cell like:
CellIdentityGsm cellIdentityGsm = cellInfoGsm.getCellIdentity();
CellIdentityLte cellIdentityLte = cellInfoLte.getCellIdentity();
or
CellSignalStrengthGsm cellSignalStrengthGsm = cellInfoGsm.getCellSignalStrength();
CellSignalStrengthLte cellSignalStrengthLte = cellInfoLte.getCellSignalStrength();
Then use cellIdentityGsm, cellIdentityLte, cellSignalStrengthGsm and cellSignalStrengthLte to do what you want in onCellInfoChanged.
In addition to #bimmlerd answer. If you are updating the Phone Information via dialing *#*#INFO#*#* (i.e. *#*#4636#*#*). There are chances that the hidden menu doesn't appear. In that case, use default dialer if you are using some 3rd party call management application (Worked for me as it was not showing any hidden menu for phone information).
https://www.reddit.com/r/GooglePixel/comments/6xc40q/4636_service_menu_not_available_in_oreo/
Note:
The following picture will help you with the latest Android OS. Just update the mobile info refresh rate in phone information 1/2 option (I hope multiple phone information because of multiple sim cards)

Categories

Resources