org.openbmap.unifiedNlp.Geocoder.OnlineProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.openbmap.unifiedNlp.Geocoder.OnlineProvider.java

Source

/*
   Radiobeacon - Openbmap Unified Network Location Provider
Copyright (C) 2013  wish7
    
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
    
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.
    
You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
package org.openbmap.unifiedNlp.Geocoder;

import android.content.Context;
import android.location.Location;
import android.net.wifi.ScanResult;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.openbmap.unifiedNlp.services.Cell;
import org.openbmap.unifiedNlp.services.JSONParser;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class OnlineProvider extends AbstractProvider implements ILocationProvider {

    private static final String TAG = OnlineProvider.class.getName();

    /**
     * Geolocation service
     */
    private static final String REQUEST_URL = "https://%s.radiocells.org/geolocate";

    /**
     * Query extra debug information from webservice
     */
    private final boolean mDebug;

    /**
     * Example wifi query JSON
     */
    // {"wifiAccessPoints":[{"macAddress":"000000000000","signalStrength":-54}]}

    /**
     * Example cell query JSON
     */
    // {"cellTowers": [{"cellId": 21532831, "locationAreaCode": 2862, "mobileCountryCode": 214, "mobileNetworkCode": 7}]}

    /**
     * Example JSON reply
     */
    // {"accuracy":30,"location":{"lng":10.088244781346,"lat":52.567062375353}}

    /**
     * Callback function on results available
     */
    private ILocationCallback mListener;

    private ArrayList<String> mWifiQuery;
    private ArrayList<String> mCellQuery;

    public OnlineProvider(final Context context, final ILocationCallback listener, boolean debug) {
        this.mListener = listener;
        mDebug = debug;
        setLastFix(System.currentTimeMillis());
    }

    /**
     * Queries location for list of wifis
     */
    @SuppressWarnings("unchecked")
    @Override
    public void getLocation(List<ScanResult> wifisList, List<Cell> cellsList) {
        ArrayList<String> wifis = new ArrayList<>();

        if (wifisList != null) {
            // Generates a list of wifis from scan results
            for (ScanResult r : wifisList) {
                if ((r.BSSID != null) & !(r.SSID.endsWith("_nomap"))) {
                    wifis.add(r.BSSID);
                }
            }
            Log.i(TAG, "Using " + wifis.size() + " wifis for geolocation");
        } else
            Log.i(TAG, "No wifis supplied for geolocation");

        new AsyncTask<Object, Void, JSONObject>() {

            @Override
            protected JSONObject doInBackground(Object... params) {
                if (params == null) {
                    throw new IllegalArgumentException("Wifi list was null");
                }
                mWifiQuery = (ArrayList<String>) params[0];
                mCellQuery = new ArrayList<>();
                for (Cell temp : (List<Cell>) params[1]) {
                    mCellQuery.add(temp.toString());
                }

                Random r = new Random();
                int idx = r.nextInt(3);

                final String balancer = String.format(REQUEST_URL, new String[] { "a", "b", "c" }[idx]);
                if (mDebug) {
                    Log.v(TAG, "Using balancer " + balancer);
                }
                return loadJSON(balancer, (ArrayList<String>) params[0], (List<Cell>) params[1]);
            }

            @Override
            protected void onPostExecute(JSONObject jsonData) {
                if (jsonData == null) {
                    Log.e(TAG, "JSON data was null");
                    return;
                }

                try {
                    Log.i(TAG, "JSON response: " + jsonData.toString());
                    String source = jsonData.getString("source");
                    JSONObject location = jsonData.getJSONObject("location");
                    Double lat = location.getDouble("lat");
                    Double lon = location.getDouble("lng");
                    Long acc = jsonData.getLong("accuracy");
                    Location result = new Location(TAG);
                    result.setLatitude(lat);
                    result.setLongitude(lon);
                    result.setAccuracy(acc);
                    result.setTime(System.currentTimeMillis());

                    Bundle b = new Bundle();
                    b.putString("source", source);
                    b.putStringArrayList("bssids", mWifiQuery);
                    b.putStringArrayList("cells", mCellQuery);
                    result.setExtras(b);

                    if (plausibleLocationUpdate(result)) {
                        setLastLocation(result);
                        setLastFix(System.currentTimeMillis());
                        mListener.onLocationReceived(result);
                    } else {
                        Log.i(TAG, "Strange location, ignoring");
                    }
                } catch (JSONException e) {
                    Log.e(TAG, "Error parsing JSON:" + e.getMessage());
                }
            }

            public JSONObject loadJSON(String url, ArrayList<String> wifiParams, List<Cell> cellParams) {
                // Creating JSON Parser instance
                JSONParser jParser = new JSONParser();
                JSONObject params = buildParams(wifiParams, cellParams);
                return jParser.getJSONFromUrl(url, params);
            }

            /**
             * Builds a JSON array with cell and wifi query
             * @param wifis ArrayList containing bssids
             * @param cells
             * @return JSON object
             */
            public JSONObject buildParams(ArrayList<String> wifis, List<Cell> cells) {
                JSONObject root = new JSONObject();
                try {
                    // add wifi objects
                    JSONArray jsonArray = new JSONArray();
                    if (mDebug) {
                        JSONObject object = new JSONObject();
                        object.put("debug", "1");
                        jsonArray.put(object);
                    }

                    for (String s : wifis) {
                        JSONObject object = new JSONObject();
                        object.put("macAddress", s);
                        object.put("signalStrength", "-54");
                        jsonArray.put(object);
                    }
                    if (jsonArray.length() > 0) {
                        root.put("wifiAccessPoints", jsonArray);
                    }

                    // add cell objects
                    jsonArray = new JSONArray();
                    for (Cell s : cells) {
                        JSONObject object = new JSONObject();
                        object.put("cellId", s.cellId);
                        object.put("locationAreaCode", s.area);
                        object.put("mobileCountryCode", s.mcc);
                        object.put("mobileNetworkCode", s.mnc);
                        jsonArray.put(object);
                    }
                    if (jsonArray.length() > 0) {
                        root.put("cellTowers", jsonArray);
                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                Log.v(TAG, "Query param: " + root.toString());
                return root;
            }
        }.execute(wifis, cellsList);
    }
}