Get country based on GSM/UMTS network - android

I need to detect the MCC of the country in which the GSM/UMTS wireless modem is currently now.

Based on GSM networks
You need to use getSimCountryIso() and getNetworkCountryIso() from the TelephonyManager
Returns the ISO country code equivalent for the SIM provider's country code.
Based on WIFI you use a Ip to Country database
You have also the option to use the Geocoder class based on the location

First get the MCC/MNC:
TelephonyManager tel = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String networkOperator = tel.getNetworkOperator();
if (networkOperator != null) {
int mcc = Integer.parseInt(networkOperator.substring(0, 3));
int mnc = Integer.parseInt(networkOperator.substring(3));
}
Then, based on that, you can get the number corresponding to the selected MCC. There are plenty of lists on the internet, for example this one on Wikipedia

Related

SubscriptionInfo.getMnc() drops leading zeros, cannot link MCC+MNC to SIM operator

I'm updating some code to use the Multi SIM support that was added to Android in 5.1. We examine the SIM operator (or the MCC+MNC combo) a lot in our app, so the code I'm writing involves migrating from reliance on TelephonyManager.getSimOperator() to getting SubscriptionInfos from the SubscriptionManager, each of which gives access to the MCC and MNC for a SIM.
//old way – can only access one SIM
TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
String simOperator = telephonyManager.getSimOperator();
//new way - gives access to all SIMs
SubscriptionManager subscriptionManager = (SubscriptionManager) context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
List<SubscriptionInfo> subInfoList = subscriptionManager.getActiveSubscriptionInfoList();
for(SubscriptionInfo info : subInfoList) {
int mcc = info.getMcc();
int mnc = info.getMnc();
//do some stuff...
}
I'm finding that because it's returning ints for MCC and MNC, you lose leading zeros that are in some of the MNCs. To see some examples, check out the table here. When you concat MCC+MNC you get the SIM operator, so it is important to keep the zeros that are often present. For example, NEXTEL in Mexico has a SIM operator value of "334090," but because the SubscriptionInfo returns ints for MCC and MNC, you get the values 334 and 90, respectively.
Given this issue, how can you reliably link a SubscriptionInfo's MCC+MNC pair to a particular SIM operator in a list of known SIM operators? Is this an oversight in the design of this API? Is there any other way to get the SIM operator for every SIM card that's in the multi-SIM phone?
MCC are always 3 digits, the rest is MNC, which as you correctly said, may have 2 or 3 digits.
If you parse the int to String, you can just get sub string of it and process the info as required.
Also it's a hidden method, but you can access it by reflection, to get the info you want in String format, this exists at least from Android 6 and Android 7
public String getSimOperator(int subId)
But I think SubscriptionManager way is safer since it's open API and for the moment you don't need to bother with Android versions handling it differently.
The best way to achieve this is to read IMSI from the SIM card. If you are reading the MNC+MNC directly and your user is on roaming or connected to another network then the values returned won't be reliable.
E.g. If your user is NEXTEL customer but is travelling or due to network connection issues connects to another network, lets say Telcel, then the value returned from MCC+MNC will be from Telcel.
In order to reliably match the operator of current SIM to predefined list, read IMSI value from SIM card using getSubscriptionId() from Telephony manager.
IMSI starts with MCC+MNC of the operator. You can easily check if MCC+MNC matches as follows
final String mccMncToCompare = "334090"; //You can also use Integer instead of string. You just have to perform type conversion
final TelephonyManager tm = (TelephonyManager) context
.getSystemService(Context.TELEPHONY_SERVICE);
final String imsi= tm.getSubscriberId();
final boolean mccMncMatched = imsi.startsWith(mccMncToCompare);

How can I get the phone number without getLine1Number() method

I'm having troubles getting the phone number in certain phones with EURO operators, I try with TelephonyManager using getLine1Number() for get the SIM number, that work fine but in order to get a GSM phone number the method return a empty string. So, the question is, how can I get that info without getLine1Number() method?
Any way is valid, just I need take that information and send SMS to user or register using a phone number as username.
In some countries, SIM does not store phone numbers. If you want an unique user number, you can use subscriber ID:
TelephonyManager telMan = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
String phoneNumber = "00";
try {
phoneNumber =telMan.getLine1Number();
} catch(NullPointerException ex) {
ex.printStackTrace();
}
if(phoneNumber.equals("")){
phoneNumber = telMan.getSubscriberId();
}

Not Able to Get Country Where User is Using My Android Application

I am not able to get Exact Country Where User is Using my Android Application.
I tried Many Ways but not Getting the exact answer.
Firstly i Used TelephonyManager Like this but not getting exact Answer
TelephonyManager tMgr = (TelephonyManager) CheckCountry.this
.getSystemService(Context.TELEPHONY_SERVICE);
phNo = tMgr.getLine1Number();
Then i used this But it return value by getting From My Mobile Settings
String locale = getApplicationContext().getResources()
.getConfiguration().locale.getCountry();
Have AnyOne Exact Solution by which I can get Country name then Let me Know
Well I found a better solution for this. By using This api I can get All the details about User Current Location And Country. Here is the API
API to Get Country
if connected to United State then "US"
TelephonyManager tm = (TelephonyManager)this.getSystemService(this.TELEPHONY_SERVICE);
String countryCodeValue = tm.getNetworkCountryIso();
or
TelephonyManager tm = (TelephonyManager)this.getSystemService(this.TELEPHONY_SERVICE);
String countryCode = tm.getSimCountryIso();

Differentiate between international roaming and roaming with the country.

Do we have any flag or value on the phone which can help decide this ?
I think it's not possible, you can just differenciate whether you're using roaming or not, but at least officially I can't find any info about this.
getRoaming() from ServiceState class.
isRoaming() from NetworkInfo class.
Roaming detection in StackOverflow.
---- EDIT ----
As probably there's not a built-int method for this, you could simply define and keep an internal list of national telephony companies and see whether the SIM's operator match one of them, in which case you'll be having a national roaming, an international roaming if the current operator is not the same as the SIM's and it's not in your list, or no-roaming if the current operator matches the SIM's operator. The negative thing is that you'd need to keep track of all national operators and add it to the list if there's some new, but that's something that doesn't happen too often (or at least here).
So basically it would be something like this:
TelephonyManager telephMan = ((TelephonyManager) Context.getSystemService(Context.TELEPHONY_SERVICE));
// This will be the current registered operator
String currentOperatorName = telephMan.getNetworkOperatorName();
// This will return the SIM operator
String simOperatorName = telephonyManager.getSimOperatorName();
// Additionally you'll have to keep a list of national operators
ArrayList<String> myCountryOperators = new ArrayList<String();
myCountryOperators.add("...");
myCountryOperators.add("...");
...
if (currentOperatorName.equals(simOperatorName)) {
// No roaming
}
else if (myCountryOperators.contains(currentOperatorName)) {
// National roaming
}
else {
// International roaming
}
if it's a GSM phone, in my opinion is easier to compare the country code set in the SIM card with the country code of network carrier with TelephonyManager.getNetworkCountryIso() and TelephonyManager.getSimCountryIso()
If they match you're in same country, otherwise don't. And you don't need to keep a list of names...

How to get correct cell id and location area code in Android?

I have found so much code that fetches cell-id and location area code and I use the code below to fetch cell-id and location area code.
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
GsmCellLocation cellLocation = (GsmCellLocation) telephonyManager.getCellLocation();
int cid = cellLocation.getCid();
int lac = cellLocation.getLac();
The problem is, when I use an airtel-sim card it works fine and give cell-id =4331 and loc =610. But when I use a relience-sim card then it give wrong result cell-id =11541 and loc=18823. How might I resolve this?
Solutions are highlighted in the following thread: Android: CellID not available on all carriers?
In short you need to mask the number you get from getCid() when in 3G network with 0xffff. Following is a snippet:
GsmCellLocation cellLocation = (GsmCellLocation)telm.getCellLocation();
new_cid = cellLocation.getCid() & 0xffff;
new_lac = cellLocation.getLac() & 0xffff;
Hope that helps
Cell IDs and LAC ids are different based on networks, as you have mentioned that you are using two different SIMs of different networks so you will get different cell and lac ids these will not be same. Because cell id of one operator will be different than other network as two different towers are used of different networks and they have assigned accordingly both ids.

Categories

Resources