package org.microg.networklocation.backends.apple; import android.content.Context; import android.util.Log; import org.microg.networklocation.MainService; import org.microg.networklocation.data.LocationSpec; import org.microg.networklocation.data.MacAddress; import org.microg.networklocation.data.WifiSpec; import org.microg.networklocation.source.LocationSource; import org.microg.networklocation.source.OnlineDataSource; import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.Locale; public class AppleWifiLocationSource extends OnlineDataSource implements LocationSource<WifiSpec> { public static final float LATLON_WIRE = 1E8F; private static final String TAG = "nlp.AppleWifiLocationSource"; private static final String NAME = "Apple Location Service"; private static final String DESCRIPTION = "Retrieve Wifi locations from Apple"; private static final String COPYRIGHT = "© Apple\nLicense: proprietary or unknown"; private final LocationRetriever locationRetriever = new LocationRetriever(); public AppleWifiLocationSource(Context context) { super(context); } public static String niceMac(String mac) { mac = mac.toLowerCase(Locale.getDefault()); final StringBuilder builder = new StringBuilder(); final String[] arr = mac.split(":"); for (int i = 0; i < arr.length; i++) { if (arr[i].length() == 1) { builder.append("0"); } builder.append(arr[i]); if (i < arr.length - 1) { builder.append(":"); } } return builder.toString(); } @Override public String getCopyright() { return COPYRIGHT; } @Override public String getDescription() { return DESCRIPTION; } @Override public String getName() { return NAME; } @Override public Collection<LocationSpec<WifiSpec>> retrieveLocation(Collection<WifiSpec> specs) { Collection<LocationSpec<WifiSpec>> locationSpecs = new ArrayList<LocationSpec<WifiSpec>>(); Collection<String> macs = new ArrayList<String>(); for (WifiSpec spec : specs) { macs.add(niceMac(spec.getMac().toString())); } try { Response response = locationRetriever.retrieveLocations(macs); if ((response == null) || (response.wifis == null) || response.wifis.isEmpty()) { Log.d(TAG, "Got nothing usable from Apple's servers!"); return locationSpecs; } int locsGet = 0; for (Response.ResponseWifi responseWifi : response.wifis) { try { WifiSpec wifiSpec = new WifiSpec(MacAddress.parse(responseWifi.mac), responseWifi.channel); if ((responseWifi.location.altitude != null) && (responseWifi.location.altitude > -500)) { locationSpecs .add(new LocationSpec<WifiSpec>(wifiSpec, responseWifi.location.latitude / LATLON_WIRE, responseWifi.location.longitude / LATLON_WIRE, responseWifi.location.accuracy, responseWifi.location.altitude)); } else { locationSpecs .add(new LocationSpec<WifiSpec>(wifiSpec, responseWifi.location.latitude / LATLON_WIRE, responseWifi.location.longitude / LATLON_WIRE, responseWifi.location.accuracy)); } locsGet++; } catch (Exception e) { if (MainService.DEBUG) { Log.w(TAG, e); } } } if (MainService.DEBUG) { Log.d(TAG, "got " + locsGet + " usable locations from server"); } } catch (IOException e) { if (MainService.DEBUG) { Log.w(TAG, e); } } if (MainService.DEBUG) { Log.d(TAG, "got locationSpecs=" + locationSpecs); } return locationSpecs; } }