Android Coarse Locationing without Google Play Services

Version 1

    Locationing in Android

     

    Android provides the ability to use a number of different sources for getting a devices location.  Most devices include a hardware GPS system that can provide a very accurate position however this is usually at the expense of time and battery life.  It also requires a clear view of the sky and will not work indoors.  Devices packaged with Google Play Services have an additional provider that uses information such as the cell tower the device is connected to in order to provide position information.  This can present a challenge for applications running on Android devices without Google Play Services that need access to coarse location data, especially in indoor scenarios.  I will explain how you can take advantage of the Google Geolocation API to request a coarse position based on provided cell tower information.

     

    Google Maps Geolocation API

     

    The Google Maps Geolocation API is a web service API provided by Google that provides a rough location based on cell tower or Wifi AP information.  More information and a description of the API can be found here: The Google Maps Geolocation API - Google Maps API for Work — Google Developers .  As of now the API is free to use for up to 100 requests per day but beyond that you will need to purchase an additional quota.  Even the free version requires you to request a Geolocation API key to use the API.

     

    Demo Application

     

    Setting API Key

     

    Before you can call the Geolocation API you must have an API Key from Google.  Instructions for retrieving an API key from Google can be found here: The Google Maps Geolocation API - Google Maps API for Work — Google Developers .  Set this API key in the application here:

     

    private static final String API_KEY = "";
    
    
    
    

     

    Getting Cell Tower Data From Android

     

    Cell tower data is easily retrieved from the TelephonyManager API.  This example is for GSM networks only.

     

    TelephonyManager tel = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
    
    
      if (tel != null) {
           CellLocation loc = tel.getCellLocation();
    
    
      if ((loc != null) && (loc instanceof GsmCellLocation)) {
           GsmCellLocation gsmLoc = (GsmCellLocation) loc;
           String op = tel.getNetworkOperator();
    
           String cid = "" + gsmLoc.getCid();
           String lac = "" + gsmLoc.getLac();
           String mcc = op.substring(0, 3);
           String mnc = op.substring(3);
           new HttpPostTask().execute(cid, lac, mcc, mnc);
           } else {
                Toast.makeText(context, "No valid GSM network found",
                Toast.LENGTH_LONG).show();
           }
      }
    
    
    
    
    
    

     

    Send HTTP Request to Geolocation API

     

    The next step is to build a JSON string with the cell tower information and send an HTTP POST request to the Google API

     

      String result = null;
    
      HttpClient httpclient =  new DefaultHttpClient();
      HttpPost httpost = new HttpPost("https://www.googleapis.com/geolocation/v1/geolocate?key=" + API_KEY);
    
      StringEntity se;
    
      JSONObject cellTower = new JSONObject();
      cellTower.put("cellId", params[0]);
      cellTower.put("locationAreaCode", params[1]);
      cellTower.put("mobileCountryCode", params[2]);
      cellTower.put("mobileNetworkCode", params[3]);
    
      JSONArray cellTowers = new JSONArray();
      cellTowers.put(cellTower);
    
      JSONObject rootObject = new JSONObject();
      rootObject.put("cellTowers", cellTowers);
    
      se = new StringEntity(rootObject.toString());
      se.setContentType("application/json");
    
      httpost.setEntity(se);
      httpost.setHeader("Accept", "application/json");
      httpost.setHeader("Content-type", "application/json");
    
      ResponseHandler<String> responseHandler = new BasicResponseHandler();
      String response = httpclient.execute(httpost, responseHandler);
    
      result = response;
    
    
    
    
    

     

    Showing the Result on Map

     

    The retrieved coordinates can be shown on a map in the browser by broadcasting an Intent

     

      JSONObject jsonResult = new JSONObject(result);
      JSONObject location = jsonResult.getJSONObject("location");
      String lat, lng;
      lat = location.getString("lat");
      lng = location.getString("lng");
    
      if ((lat != null) &&
         (!lat.isEmpty()) &&
         (lng != null) &&
         (!lng.isEmpty())) {
                context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://maps.google.com/maps?q=" + lat + "," + lng + "&iwloc=A")));
         }
    
    
    

     

    Alternatives to the Google Geolocation API

     

    There are similar services provided by others including Apple and even free, user sourced data like OpenCellID -  OpenCellID .  The Google API was used here as an example however these other providers provide a similar API that can be accessed in the same way.  OpenCellID is free however the data may not be as accurate and complete as you would find with other paid services.