/************************************************************************* * Copyright (c) 2015 Lemberg Solutions * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. **************************************************************************/ package com.ls.widgets.map.providers; import android.content.Context; import android.content.pm.PackageManager; import android.location.GpsStatus; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; import android.os.SystemClock; import android.util.Log; import com.ls.widgets.map.interfaces.MapLocationListener; public final class GPSLocationProvider implements LocationListener { private static final String TAG = "GPSLocationProvider"; private LocationManager locManager; private int refreshRate; private int minDistance; private MapLocationListener listener; private long mLastLocationMillis; private Location mLastLocation; private boolean isGpsFix; private boolean filterNonGPSFix; private boolean started; private boolean permGranted; private boolean passiveMode; private MyGPSListener gpsStatusListener; public GPSLocationProvider(Context context) { locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE); started = false; passiveMode = false; gpsStatusListener = new MyGPSListener(); PackageManager mgr = context.getPackageManager(); if (mgr.checkPermission(android.Manifest.permission.ACCESS_FINE_LOCATION, context.getPackageName()) == PackageManager.PERMISSION_GRANTED) { permGranted = true; } else { permGranted = false; } } public void setMinRefreshTime(int refreshRate) { this.refreshRate = refreshRate; } public void setMinRefreshDistance(int minDistance) { this.minDistance = minDistance; } public void setMapLocationListener(MapLocationListener listener) { this.listener = listener; } /** * Registers location update listeners. * @param passiveMode */ public void start(boolean passiveMode) { if (!permGranted) { Log.w(TAG,"Can't start receiving the location updates. You have no ACCESS_FINE_LOCATION permission enabled."); return; } if (started) { Log.w(TAG, "Can't start receiving the location updates. Already started."); return; } started = true; try { this.passiveMode = passiveMode; if (passiveMode) { locManager.requestLocationUpdates("passive", 0, 0, this); Log.d(TAG, "Registering for receiving updates from passive provider."); } else { locManager.addGpsStatusListener(gpsStatusListener); if (locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) { locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, refreshRate, minDistance, this); } locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, refreshRate, minDistance, this); } Location loc1 = locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); Location loc2 = locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (loc1 != null && loc2 != null) { if (loc1.getAccuracy() < loc2.getAccuracy()) { onLocationChanged(loc1); } else { onLocationChanged(loc2); } } else { Location loc = loc1 != null? loc1: loc2; if (loc != null) { onLocationChanged(loc); } } if (listener != null) { listener.onChangePinVisibility(true); } } catch (SecurityException e) { Log.w(TAG, "Can't get location provider due to " + e); } } public void stop() { locManager.removeGpsStatusListener(gpsStatusListener); if (listener != null) { listener.onChangePinVisibility(false); } started = false; locManager.removeUpdates(this); } @Override public void onLocationChanged(Location location) { if (location == null) return; if (!passiveMode) { mLastLocationMillis = SystemClock.elapsedRealtime(); if (location.getProvider().equals(LocationManager.NETWORK_PROVIDER)) { if (!filterNonGPSFix) { listener.onMovePinTo(location); } } else if (location.getProvider().equals(LocationManager.GPS_PROVIDER)){ listener.onMovePinTo(location); } mLastLocation = location; } else { listener.onMovePinTo(location); } } @Override public void onProviderDisabled(String name) { Log.d(TAG, "Provider disabled: " + name); } @Override public void onProviderEnabled(String name) { Log.d(TAG, "Provider enabled: " + name); if (started && !passiveMode) { if (name.equals(LocationManager.GPS_PROVIDER)) { locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, refreshRate, minDistance, this); } } } @Override public void onStatusChanged(String name, int status, Bundle arg2) { Log.d(TAG, "Status of "+ name + " changed for " + statusToString(status)); } private String statusToString(int status) { switch (status) { case LocationProvider.OUT_OF_SERVICE: return "OUT_OF_SERVICE"; case LocationProvider.TEMPORARILY_UNAVAILABLE: return "TEMPORARILY_UNAVAILABLE"; case LocationProvider.AVAILABLE: return "AVAILABLE:"; } return "UNKNOWN"; } private class MyGPSListener implements GpsStatus.Listener { public void onGpsStatusChanged(int event) { if (passiveMode) { return; } switch (event) { case GpsStatus.GPS_EVENT_SATELLITE_STATUS: if (mLastLocation != null) isGpsFix = (SystemClock.elapsedRealtime() - mLastLocationMillis) < 3000; if (isGpsFix) { // A fix has been acquired. filterNonGPSFix = true; // Do something. } else { // The fix has been lost. filterNonGPSFix = false; // Do something. } break; case GpsStatus.GPS_EVENT_FIRST_FIX: // Do something. isGpsFix = true; filterNonGPSFix = true; break; } } } }