CellIdentityLte getCi() returning -1 in android - 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.

Related

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?

How to identify dual sim carrier name in sdk level less than android.os.Build.VERSION_CODES.LOLLIPOP_MR1

I know from sdk level android.os.Build.VERSION_CODES.LOLLIPOP_MR1 we get subscriptionInfoList as subscriptionManager.getActiveSubscriptionInfoList();
and by using this we will identify all the supported sim information.
I need getting the same in android lower versions. Anybody can help me ?
Fortunately there are several native solutions.
For API >=17:
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
// Get information about all radio modules on device board
// and check what you need by calling #getCellIdentity.
final List<CellInfo> allCellInfo = manager.getAllCellInfo();
for (CellInfo cellInfo : allCellInfo) {
if (cellInfo instanceof CellInfoGsm) {
CellIdentityGsm cellIdentity = ((CellInfoGsm) cellInfo).getCellIdentity();
//TODO Use cellIdentity to check MCC/MNC code, for instance.
} else if (cellInfo instanceof CellInfoWcdma) {
CellIdentityWcdma cellIdentity = ((CellInfoWcdma) cellInfo).getCellIdentity();
} else if (cellInfo instanceof CellInfoLte) {
CellIdentityLte cellIdentity = ((CellInfoLte) cellInfo).getCellIdentity();
} else if (cellInfo instanceof CellInfoCdma) {
CellIdentityCdma cellIdentity = ((CellInfoCdma) cellInfo).getCellIdentity();
}
}
In AndroidManifest add permission:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
To get network operator you can check mcc and mnc codes:
https://en.wikipedia.org/wiki/Mobile_country_code (general information).
https://clients.txtnation.com/hc/en-us/articles/218719768-MCCMNC-mobile-country-code-and-mobile-network-code-list- (quite full and quite latest list of operators).
For newest devices you can use newest APIs.
For API >=22:
final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
final List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
final CharSequence carrierName = subscriptionInfo.getCarrierName();
final CharSequence displayName = subscriptionInfo.getDisplayName();
final int mcc = subscriptionInfo.getMcc();
final int mnc = subscriptionInfo.getMnc();
final String subscriptionInfoNumber = subscriptionInfo.getNumber();
}
For API >=23. To just check if phone is dual/triple/many sim:
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getPhoneCount() == 2) {
// Dual sim
}

Get whole list of Network operators programatically for Dual Sim Phones

I need to get the Network operator names if the phone is dual sim or the whole list of neighbouring Network operator names. when I googled what I found for Network Operator name is this
TelephonyManager tManager = (TelephonyManager) getBaseContext()
.getSystemService(Context.TELEPHONY_SERVICE);
// Get carrier name (Network Operator Name)
String carrierName = tManager.getNetworkOperatorName();
But this wont work for me. How can I achieve this. If not suggest me some solutions. thanks
Fortunately there are several native solutions.
For API >=17:
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
// Get information about all radio modules on device board
// and check what you need by calling #getCellIdentity.
final List<CellInfo> allCellInfo = manager.getAllCellInfo();
for (CellInfo cellInfo : allCellInfo) {
if (cellInfo instanceof CellInfoGsm) {
CellIdentityGsm cellIdentity = ((CellInfoGsm) cellInfo).getCellIdentity();
//TODO Use cellIdentity to check MCC/MNC code, for instance.
} else if (cellInfo instanceof CellInfoWcdma) {
CellIdentityWcdma cellIdentity = ((CellInfoWcdma) cellInfo).getCellIdentity();
} else if (cellInfo instanceof CellInfoLte) {
CellIdentityLte cellIdentity = ((CellInfoLte) cellInfo).getCellIdentity();
} else if (cellInfo instanceof CellInfoCdma) {
CellIdentityCdma cellIdentity = ((CellInfoCdma) cellInfo).getCellIdentity();
}
}
In AndroidManifest add permission:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
</manifest>
To get network operator you can check mcc and mnc codes:
https://en.wikipedia.org/wiki/Mobile_country_code (general information).
https://clients.txtnation.com/hc/en-us/articles/218719768-MCCMNC-mobile-country-code-and-mobile-network-code-list- (quite full and quite latest list of operators).
For API >=22:
final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
final List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
final CharSequence carrierName = subscriptionInfo.getCarrierName();
final CharSequence displayName = subscriptionInfo.getDisplayName();
final int mcc = subscriptionInfo.getMcc();
final int mnc = subscriptionInfo.getMnc();
final String subscriptionInfoNumber = subscriptionInfo.getNumber();
}
For API >=23. To just check if phone is dual/triple/many sim:
TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getPhoneCount() == 2) {
// Dual sim
}

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