As user of mobile phones we are used to have an almost 100% coverage for phone calls (not for data though) and the user-experience is absolutely seamless in most urban and sub-urban areas in Europe and most other countries. Moving around in trains and cars we cant sense the hand-over in the background of the GSM (2G, GPRS, EDGE), UMTS (3G), LTE (4G) network passing on our connection between the BTS ( base transceiver station). As regular user we dont have an idea about the number and location of cell towers around us, some towers or antennas are mounted on very obvious structures (antennas on towers), some are almost hidden. Though the GSM antennas can have a range of up to 35km (flat plane vs less than 5km in hilly areas), we have much higher density of cells in the urban area with antennas almost every few 100 metres or less. There are a lot of parameters influencing the infrastructure and its layout at a certain place, I wont dive into the details of if, you can get some info on the reference sites listed at the end of the article.
Rather approaching this topic hands-on, I was curious about the information that I can retrieve with Android about the active cells, its location and ultimately about the information the network operator (or other interested parties) collects about one. We might disable the GPS function of a phone to stop apps to collect our whereabouts, giving apps access to the phone state still gives a coarse location profile.
Usually phones dont reveal any network information other than the network operator but with the help of some regular Android methods of the TelephonyManager and GsmCellLocation class we get the crucial information.
The key info we are looking for is
- MCC – Mobile Country Code
- MNC – Mobile Network Code
- LAC – Location Area Code
- CELLID – The ID of the cell
Only the combination of the above 4 values is unique and can identify the location. You can look at a directory of MCC codes at Wikipedia, but there is no list of of LAC and CELLID codes published by the provider. But in the era of the “crowd” there is a collaborative community collecting the measurements of cellphones and putting them into a DB (CC-BY-SA 3.0). At opencellid.org you can both retrieve information about cell towers as well download the complete DB.
Quite surprising, during one of the first tests, driving a 100km distance along the highway, both rural and suburban area, I passed through more than 80 cells !
Relevant Android methods
TelephonyManager telephonyManager = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); mcc = telephonyManager.getNetworkOperator().substring(0, 3); mnc = telephonyManager.getNetworkOperator().substring(3); operator = telephonyManager.getNetworkOperatorName(); GsmCellLocation location = (GsmCellLocation) telephonyManager.getCellLocation(); lac = location.getLac(); cellid = location.getCid();
Be aware of the permissions required
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
A extra note about Android 6.x+ development, Google changed massively the permission concept and apps require an additional confirmation of the required permissions (for so-called dangerous permissions) during runtime, this has to be implemented specifically, otherwise your application which runs on earlier Android versions will crash. I will share the relevant implementation in an upcoming entry.
Note for Samsung Phones: The function to get information about the nearby cells is not supported by Samsung phones
List<NeighboringCellInfo> neighborCells = telephonyManager.getNeighboringCellInfo();
This list will all be null on Samsung phones. You only can retrieve information about the currently connected cell.
I will try to make some more sense out of the collected data and see how fine-grain the collected data reveals my location.
Btw, there are dozens of similar apps in the Playstore and some even report back collected data to improve and build up the opencellid project database.