diff --git a/src/it/reyboz/bustorino/middleware/AppLocationManager.java b/src/it/reyboz/bustorino/middleware/AppLocationManager.java index 8aa4573..7e89155 100644 --- a/src/it/reyboz/bustorino/middleware/AppLocationManager.java +++ b/src/it/reyboz/bustorino/middleware/AppLocationManager.java @@ -1,197 +1,219 @@ /* BusTO (middleware) Copyright (C) 2019 Fabio Mazza This program is free software: you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package it.reyboz.bustorino.middleware; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.location.LocationProvider; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import it.reyboz.bustorino.util.LocationCriteria; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.ListIterator; /** * Singleton class used to access location. Possibly extended with other location sources. */ public class AppLocationManager implements LocationListener { public static final int LOCATION_GPS_AVAILABLE = 22; public static final int LOCATION_UNAVAILABLE = -22; private Context con; private LocationManager locMan; public static final String DEBUG_TAG = "BUSTO LocAdapter"; private final String BUNDLE_LOCATION = "location"; private static AppLocationManager instance; private int oldGPSLocStatus = LOCATION_UNAVAILABLE; private int minimum_time_milli = -1; private ArrayList> requestersRef = new ArrayList<>(); private AppLocationManager(Context con) { this.con = con; locMan = (LocationManager) con.getSystemService(Context.LOCATION_SERVICE); } public static AppLocationManager getInstance(Context con) { if(instance==null) instance = new AppLocationManager(con.getApplicationContext()); return instance; } private void requestGPSPositionUpdates(){ final int timeinterval = (minimum_time_milli>0 && minimum_time_milli> iter = requestersRef.listIterator(); while(iter.hasNext()){ final LocationRequester cReq = iter.next().get(); if(cReq==null) iter.remove(); else { minimum_time_milli = Math.min(cReq.getLocationCriteria().getTimeInterval(),minimum_time_milli); } } Log.d(DEBUG_TAG,"Updated requesters, got "+requestersRef.size()+" listeners to update every "+minimum_time_milli+" ms at least"); } public void addLocationRequestFor(LocationRequester req){ boolean present = false; minimum_time_milli = Integer.MAX_VALUE; ListIterator> iter = requestersRef.listIterator(); while(iter.hasNext()){ final LocationRequester cReq = iter.next().get(); if(cReq==null) iter.remove(); else if(cReq.equals(req)){ present = true; minimum_time_milli = Math.min(cReq.getLocationCriteria().getTimeInterval(),minimum_time_milli); } } if(!present) { WeakReference newref = new WeakReference<>(req); requestersRef.add(newref); minimum_time_milli = Math.min(req.getLocationCriteria().getTimeInterval(),minimum_time_milli); Log.d(DEBUG_TAG,"Added new stop requester, instance of "+req.getClass().getSimpleName()); } if(requestersRef.size()>0){ requestGPSPositionUpdates(); } } public void removeLocationRequestFor(LocationRequester req){ minimum_time_milli = Integer.MAX_VALUE; ListIterator> iter = requestersRef.listIterator(); while(iter.hasNext()){ final LocationRequester cReq = iter.next().get(); if(cReq==null || cReq.equals(req)) iter.remove(); else { minimum_time_milli = Math.min(cReq.getLocationCriteria().getTimeInterval(),minimum_time_milli); } } if(requestersRef.size()<=0){ locMan.removeUpdates(this); } else { requestGPSPositionUpdates(); } } private void sendLocationStatusToAll(int status){ ListIterator> iter = requestersRef.listIterator(); while(iter.hasNext()){ final LocationRequester cReq = iter.next().get(); if(cReq==null) iter.remove(); else cReq.onLocationStatusChanged(status); } } @Override public void onLocationChanged(Location location) { Log.d("GPSLocationListener","found location:\nlat: "+location.getLatitude()+" lon: "+location.getLongitude()+"\naccuracy: "+location.getAccuracy()); ListIterator> iter = requestersRef.listIterator(); int new_min_interval = Integer.MAX_VALUE; while(iter.hasNext()){ final LocationRequester requester = iter.next().get(); if(requester==null) iter.remove(); else{ final long timeNow = System.currentTimeMillis(); final LocationCriteria criteria = requester.getLocationCriteria(); if(location.getAccuracy()criteria.getTimeInterval()){ requester.onLocationChanged(location); Log.d("AppLocationManager","Updating position for instance of requester "+requester.getClass().getSimpleName()); } //update minimum time interval new_min_interval = Math.min(requester.getLocationCriteria().getTimeInterval(),new_min_interval); } } minimum_time_milli = new_min_interval; if(requestersRef.size()==0){ //stop requesting the position locMan.removeUpdates(this); } } @Override public void onStatusChanged(String provider, int status, Bundle extras) { //IF ANOTHER LOCATION SOURCE IS READY, USE IT //OTHERWISE, SIGNAL THAT WE HAVE NO LOCATION if(oldGPSLocStatus !=status){ if(status == LocationProvider.OUT_OF_SERVICE || status == LocationProvider.TEMPORARILY_UNAVAILABLE) { sendLocationStatusToAll(LOCATION_UNAVAILABLE); }else if(status == LocationProvider.AVAILABLE){ sendLocationStatusToAll(LOCATION_GPS_AVAILABLE); } oldGPSLocStatus = status; } } @Override public void onProviderEnabled(String provider) { requestGPSPositionUpdates(); } @Override public void onProviderDisabled(String provider) { locMan.removeUpdates(this); } - + /** + * Interface to be implemented to get the location request + */ public interface LocationRequester{ + /** + * Do something with the newly obtained location + * @param loc the obtained location + */ void onLocationChanged(Location loc); + + /** + * Inform the requester that the GPS status has changed + * @param status new status + */ void onLocationStatusChanged(int status); + + /** + * Give the last time of update the requester has + * Set it to -1 in order to receive each new location + * @return the time for update in milliseconds since epoch + */ long getLastUpdateTimeMillis(); + + /** + * Get the specifications for the location + * @return fully parsed LocationCriteria + */ LocationCriteria getLocationCriteria(); } }