package org.microg.networklocation; import android.app.Service; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.location.Location; import android.net.wifi.WifiManager; import android.os.Build; import android.os.IBinder; import android.provider.Settings; import android.util.Log; import org.microg.networklocation.backends.apple.AppleWifiLocationSource; import org.microg.networklocation.backends.file.NewFileCellLocationSource; import org.microg.networklocation.backends.file.OldFileCellLocationSource; import org.microg.networklocation.backends.mapquest.NominatimGeocodeSource; import org.microg.networklocation.backends.mozilla.IchnaeaCellLocationSource; import org.microg.networklocation.backends.opencellid.OpenCellIdLocationSource; import org.microg.networklocation.backends.cellapi.CellAPI; import org.microg.networklocation.data.CellSpec; import org.microg.networklocation.data.LocationCalculator; import org.microg.networklocation.data.LocationRetriever; import org.microg.networklocation.data.WifiSpec; import org.microg.networklocation.database.GeocodeDatabase; import org.microg.networklocation.database.LocationDatabase; import org.microg.networklocation.helper.Reflected; import org.microg.networklocation.platform.PlatformFactory; import org.microg.networklocation.provider.GeocodeProvider; import org.microg.networklocation.provider.NetworkLocationProvider; import org.microg.networklocation.retriever.CellSpecRetriever; import org.microg.networklocation.retriever.WifiSpecRetriever; import org.microg.networklocation.source.GeocodeSource; import org.microg.networklocation.source.LocationSource; import java.util.ArrayList; import java.util.List; public class MainService extends Service { public static final boolean DEBUG; static { DEBUG = Log.isLoggable("nlp", Log.DEBUG); } private static final String TAG = "nlp.NetworkLocationService"; private static Context context; private LocationCalculator locationCalculator; private LocationRetriever locationRetriever; private GeocodeProvider geoprovider; private NetworkLocationProvider nlprovider; private WifiManager wifiManager; private BroadcastReceiver airplaneModeReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { updateProviderStateOnAirplaneMode(); } }; public MainService() { if (DEBUG) { Log.d(TAG, "new Service-Object constructed"); } } public static Context getContext() { return context; } public Location getCurrentLocation() { return locationCalculator.getCurrentLocation(); } public boolean isActive() { return nlprovider.isActive(); } private boolean isAirplaneModeOn() { return ((Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) ? (Settings.System.getInt(getContentResolver(), Settings.System.AIRPLANE_MODE_ON, 0)) : (Reflected.androidProviderSettingsGlobalGetInt(getContentResolver(), "airplane_mode_on", 0))) != 0; } @Override public IBinder onBind(final Intent intent) { if (DEBUG) { Log.d(TAG, "Incoming Bind Intent: " + intent); } if (intent == null) { return null; } String action = intent.getAction(); if (action == null) { return null; } if (action.equalsIgnoreCase("com.google.android.location.NetworkLocationProvider") || action.equalsIgnoreCase("com.android.location.service.NetworkLocationProvider") || action.equalsIgnoreCase("com.android.location.service.v2.NetworkLocationProvider") || action.equalsIgnoreCase("com.android.location.service.v3.NetworkLocationProvider")) { return nlprovider.getBinder(); } else if (action.equalsIgnoreCase("com.google.android.location.GeocodeProvider") || action.equalsIgnoreCase("com.android.location.service.GeocodeProvider")) { return geoprovider.getBinder(); } else if (action.equalsIgnoreCase("com.google.android.location.internal.ANDROID_NLP")) { Log.w(TAG, "somebody wants internal stuff o.O"); return nlprovider.getBinder(); } return null; } @Override public void onCreate() { super.onCreate(); context = this; if (DEBUG) { Log.d(TAG, "Creating Service"); } wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); nlprovider = PlatformFactory.newNetworkLocationProvider(); geoprovider = PlatformFactory.newGeocodeProvider(); GeocodeDatabase geocodeDatabase = new GeocodeDatabase(); geoprovider.setGeocodeDatabase(geocodeDatabase); WifiSpecRetriever wifiSpecRetriever = PlatformFactory.newWifiSpecRetriever(context); CellSpecRetriever cellSpecRetriever = PlatformFactory.newCellSpecRetriever(context); LocationDatabase locationDatabase = new LocationDatabase(context); locationRetriever = new LocationRetriever(locationDatabase); locationCalculator = new LocationCalculator(locationDatabase, locationRetriever, cellSpecRetriever, wifiSpecRetriever); nlprovider.setCalculator(locationCalculator); List<LocationSource<WifiSpec>> wifiSources = new ArrayList<LocationSource<WifiSpec>>(); wifiSources.add(new AppleWifiLocationSource(context)); locationRetriever.setWifiLocationSources(wifiSources); List<LocationSource<CellSpec>> cellSources = new ArrayList<LocationSource<CellSpec>>(); cellSources.add(new NewFileCellLocationSource()); cellSources.add(new OldFileCellLocationSource()); cellSources.add(new OpenCellIdLocationSource(context)); cellSources.add(new CellAPI(context)); cellSources.add(new IchnaeaCellLocationSource(context)); locationRetriever.setCellLocationSources(cellSources); locationRetriever.start(); List<GeocodeSource> geocodeSources = new ArrayList<GeocodeSource>(); geocodeSources.add(new NominatimGeocodeSource(context)); geoprovider.setSources(geocodeSources); registerReceiver(airplaneModeReceiver, new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED)); updateProviderStateOnAirplaneMode(); } @Override public void onDestroy() { if (DEBUG) { Log.d(TAG, "Destroying service"); } unregisterReceiver(airplaneModeReceiver); geoprovider = null; nlprovider.disable(); locationCalculator = null; locationRetriever.stop(); locationRetriever = null; nlprovider = null; wifiManager = null; } public void updateProviderStateOnAirplaneMode() { boolean airplane = isAirplaneModeOn(); boolean wifi = wifiManager.isWifiEnabled(); if (DEBUG) { Log.d(TAG, "airplane:" + airplane + " | wifi:" + wifi); } if (airplane && !wifi) { if (DEBUG) { Log.d(TAG, "AirplaneMode is enabled and wifi is off, so no way to get location for us"); } nlprovider.disable(); } else { if (DEBUG) { Log.d(TAG, "AirplaneMode or wifi is enabled. make sure we're active!"); } nlprovider.enable(); } } }