Changeset View
Changeset View
Standalone View
Standalone View
app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java
| Show First 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
| import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate; | import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate; | ||||
| import it.reyboz.bustorino.backend.mato.MQTTMatoClient; | import it.reyboz.bustorino.backend.mato.MQTTMatoClient; | ||||
| import it.reyboz.bustorino.backend.utils; | import it.reyboz.bustorino.backend.utils; | ||||
| import it.reyboz.bustorino.data.MatoTripsDownloadWorker; | import it.reyboz.bustorino.data.MatoTripsDownloadWorker; | ||||
| import it.reyboz.bustorino.data.gtfs.MatoPattern; | import it.reyboz.bustorino.data.gtfs.MatoPattern; | ||||
| import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops; | import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops; | ||||
| import it.reyboz.bustorino.map.*; | import it.reyboz.bustorino.map.*; | ||||
| import it.reyboz.bustorino.viewmodels.MQTTPositionsViewModel; | import it.reyboz.bustorino.viewmodels.GtfsPositionsViewModel; | ||||
| import it.reyboz.bustorino.viewmodels.LivePositionsViewModel; | |||||
| import it.reyboz.bustorino.viewmodels.StopsMapViewModel; | import it.reyboz.bustorino.viewmodels.StopsMapViewModel; | ||||
| import org.osmdroid.api.IGeoPoint; | import org.osmdroid.api.IGeoPoint; | ||||
| import org.osmdroid.api.IMapController; | import org.osmdroid.api.IMapController; | ||||
| import org.osmdroid.config.Configuration; | import org.osmdroid.config.Configuration; | ||||
| import org.osmdroid.events.DelayedMapListener; | import org.osmdroid.events.DelayedMapListener; | ||||
| import org.osmdroid.events.MapListener; | import org.osmdroid.events.MapListener; | ||||
| import org.osmdroid.events.ScrollEvent; | import org.osmdroid.events.ScrollEvent; | ||||
| import org.osmdroid.events.ZoomEvent; | import org.osmdroid.events.ZoomEvent; | ||||
| ▲ Show 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | public class MapFragment extends ScreenBaseFragment { | ||||
| protected CoordinatorLayout coordLayout; | protected CoordinatorLayout coordLayout; | ||||
| private boolean hasMapStartFinished = false; | private boolean hasMapStartFinished = false; | ||||
| private boolean followingLocation = false; | private boolean followingLocation = false; | ||||
| //the ViewModel from which we get the stop to display in the map | //the ViewModel from which we get the stop to display in the map | ||||
| private StopsMapViewModel stopsViewModel; | private StopsMapViewModel stopsViewModel; | ||||
| //private GTFSPositionsViewModel gtfsPosViewModel; //= new ViewModelProvider(this).get(MapViewModel.class); | //private GtfsPositionsViewModel gtfsPosViewModel; //= new ViewModelProvider(this).get(MapViewModel.class); | ||||
| private MQTTPositionsViewModel positionsViewModel; | private LivePositionsViewModel livePositionsViewModel; | ||||
| private Boolean useMQTTViewModel = true; | |||||
| private final HashMap<String,Marker> busPositionMarkersByTrip = new HashMap<>(); | private final HashMap<String,Marker> busPositionMarkersByTrip = new HashMap<>(); | ||||
| private FolderOverlay busPositionsOverlay = null; | private FolderOverlay busPositionsOverlay = null; | ||||
| private final HashMap<String, ObjectAnimator> tripMarkersAnimators = new HashMap<>(); | private final HashMap<String, ObjectAnimator> tripMarkersAnimators = new HashMap<>(); | ||||
| protected final CustomInfoWindow.TouchResponder responder = new CustomInfoWindow.TouchResponder() { | protected final CustomInfoWindow.TouchResponder responder = new CustomInfoWindow.TouchResponder() { | ||||
| @Override | @Override | ||||
| ▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
| //setup Bus Markers Overlay | //setup Bus Markers Overlay | ||||
| busPositionsOverlay = new FolderOverlay(); | busPositionsOverlay = new FolderOverlay(); | ||||
| //reset shown bus updates | //reset shown bus updates | ||||
| busPositionMarkersByTrip.clear(); | busPositionMarkersByTrip.clear(); | ||||
| tripMarkersAnimators.clear(); | tripMarkersAnimators.clear(); | ||||
| //set map not done | //set map not done | ||||
| hasMapStartFinished = false; | hasMapStartFinished = false; | ||||
| String keySourcePositions=getString(R.string.pref_positions_source); | |||||
| useMQTTViewModel = ( | |||||
| PreferenceManager.getDefaultSharedPreferences(requireContext()) | |||||
| .getString(keySourcePositions,"mqtt").contentEquals("mqtt")); | |||||
| //Start map from bundle | //Start map from bundle | ||||
| if (savedInstanceState !=null) | if (savedInstanceState !=null) | ||||
| startMap(getArguments(), savedInstanceState); | startMap(getArguments(), savedInstanceState); | ||||
| else startMap(getArguments(), savedMapState); | else startMap(getArguments(), savedMapState); | ||||
| //set listeners | //set listeners | ||||
| map.addMapListener(new DelayedMapListener(new MapListener() { | map.addMapListener(new DelayedMapListener(new MapListener() { | ||||
| Show All 37 Lines | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
| return root; | return root; | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void onAttach(@NonNull Context context) { | public void onAttach(@NonNull Context context) { | ||||
| super.onAttach(context); | super.onAttach(context); | ||||
| //gtfsPosViewModel = new ViewModelProvider(this).get(GTFSPositionsViewModel.class); | |||||
| //viewModel | |||||
| ViewModelProvider provider = new ViewModelProvider(this); | ViewModelProvider provider = new ViewModelProvider(this); | ||||
| positionsViewModel = provider.get(MQTTPositionsViewModel.class); | //gtfsPosViewModel = provider.get(GtfsPositionsViewModel.class); | ||||
| livePositionsViewModel = provider.get(LivePositionsViewModel.class); | |||||
| stopsViewModel = provider.get(StopsMapViewModel.class); | stopsViewModel = provider.get(StopsMapViewModel.class); | ||||
| if (context instanceof FragmentListenerMain) { | if (context instanceof FragmentListenerMain) { | ||||
| listenerMain = (FragmentListenerMain) context; | listenerMain = (FragmentListenerMain) context; | ||||
| } else { | } else { | ||||
| throw new RuntimeException(context.toString() | throw new RuntimeException(context.toString() | ||||
| + " must implement FragmentListenerMain"); | + " must implement FragmentListenerMain"); | ||||
| } | } | ||||
| } | } | ||||
| @Override | @Override | ||||
| Show All 12 Lines | public void onPause() { | ||||
| Log.w(DEBUG_TAG, "On pause called mapfrag"); | Log.w(DEBUG_TAG, "On pause called mapfrag"); | ||||
| saveMapState(); | saveMapState(); | ||||
| for (ObjectAnimator animator : tripMarkersAnimators.values()) { | for (ObjectAnimator animator : tripMarkersAnimators.values()) { | ||||
| if(animator!=null && animator.isRunning()){ | if(animator!=null && animator.isRunning()){ | ||||
| animator.cancel(); | animator.cancel(); | ||||
| } | } | ||||
| } | } | ||||
| tripMarkersAnimators.clear(); | tripMarkersAnimators.clear(); | ||||
| positionsViewModel.stopPositionsListening(); | if(useMQTTViewModel) livePositionsViewModel.stopMatoUpdates(); | ||||
| } | } | ||||
| /** | /** | ||||
| * Save the map state inside the fragment | * Save the map state inside the fragment | ||||
| * (calls saveMapState(bundle)) | * (calls saveMapState(bundle)) | ||||
| */ | */ | ||||
| private void saveMapState(){ | private void saveMapState(){ | ||||
| Show All 14 Lines | private void saveMapState(Bundle bundle){ | ||||
| return; | return; | ||||
| } | } | ||||
| final IGeoPoint loc = map.getMapCenter(); | final IGeoPoint loc = map.getMapCenter(); | ||||
| bundle.putDouble(MAP_CENTER_LAT_KEY, loc.getLatitude()); | bundle.putDouble(MAP_CENTER_LAT_KEY, loc.getLatitude()); | ||||
| bundle.putDouble(MAP_CENTER_LON_KEY, loc.getLongitude()); | bundle.putDouble(MAP_CENTER_LON_KEY, loc.getLongitude()); | ||||
| bundle.putDouble(MAP_CURRENT_ZOOM_KEY, map.getZoomLevelDouble()); | bundle.putDouble(MAP_CURRENT_ZOOM_KEY, map.getZoomLevelDouble()); | ||||
| } | } | ||||
| @Override | @Override | ||||
| public void onResume() { | public void onResume() { | ||||
| super.onResume(); | super.onResume(); | ||||
| //TODO: cleanup duplicate code (maybe merging the positions classes?) | |||||
| if(listenerMain!=null) listenerMain.readyGUIfor(FragmentKind.MAP); | if(listenerMain!=null) listenerMain.readyGUIfor(FragmentKind.MAP); | ||||
| if(positionsViewModel !=null) { | /// choose which to use | ||||
| String keySourcePositions=getString(R.string.pref_positions_source); | |||||
| useMQTTViewModel = PreferenceManager.getDefaultSharedPreferences(requireContext()) | |||||
| .getString(keySourcePositions,"mqtt").contentEquals("mqtt"); | |||||
| if(livePositionsViewModel !=null) { | |||||
| //gtfsPosViewModel.requestUpdates(); | //gtfsPosViewModel.requestUpdates(); | ||||
| positionsViewModel.requestPosUpdates(MQTTMatoClient.LINES_ALL); | if(useMQTTViewModel) | ||||
| livePositionsViewModel.requestMatoPosUpdates(MQTTMatoClient.LINES_ALL); | |||||
| else | |||||
| livePositionsViewModel.requestGTFSUpdates(); | |||||
| //mapViewModel.testCascade(); | //mapViewModel.testCascade(); | ||||
| positionsViewModel.getTripsGtfsIDsToQuery().observe(this, dat -> { | livePositionsViewModel.getTripsGtfsIDsToQuery().observe(this, dat -> { | ||||
| Log.i(DEBUG_TAG, "Have these trips IDs missing from the DB, to be queried: "+dat); | |||||
| //gtfsPosViewModel.downloadTripsFromMato(dat); | |||||
| MatoTripsDownloadWorker.Companion.downloadTripsFromMato(dat, | |||||
| requireContext().getApplicationContext(), | |||||
| "BusTO-MatoTripDownload"); | |||||
| }); | |||||
| } /*else if(gtfsPosViewModel!=null){ | |||||
| gtfsPosViewModel.requestUpdates(); | |||||
| gtfsPosViewModel.getTripsGtfsIDsToQuery().observe(this, dat -> { | |||||
| Log.i(DEBUG_TAG, "Have these trips IDs missing from the DB, to be queried: "+dat); | Log.i(DEBUG_TAG, "Have these trips IDs missing from the DB, to be queried: "+dat); | ||||
| //gtfsPosViewModel.downloadTripsFromMato(dat); | //gtfsPosViewModel.downloadTripsFromMato(dat); | ||||
| MatoTripsDownloadWorker.Companion.downloadTripsFromMato(dat,getContext().getApplicationContext(), | MatoTripsDownloadWorker.Companion.downloadTripsFromMato(dat,getContext().getApplicationContext(), | ||||
| "BusTO-MatoTripDownload"); | "BusTO-MatoTripDownload"); | ||||
| }); | }); | ||||
| } | } | ||||
| */ | |||||
| else Log.e(DEBUG_TAG, "livePositionsViewModel is null at onResume"); | |||||
| } | |||||
| private void startRequestsPositions(){ | |||||
| if (livePositionsViewModel != null) { | |||||
| //should always be the case | |||||
| livePositionsViewModel.getUpdatesWithTripAndPatterns().observe(getViewLifecycleOwner(), data -> { | |||||
| Log.d(DEBUG_TAG, "Have " + data.size() + " trip updates, has Map start finished: " + hasMapStartFinished); | |||||
| if (hasMapStartFinished) updateBusPositionsInMap(data); | |||||
| if(!isDetached() && !useMQTTViewModel) | |||||
| livePositionsViewModel.requestDelayedGTFSUpdates(3000); | |||||
| }); | |||||
| } else { | |||||
| Log.e(DEBUG_TAG, "PositionsViewModel is null"); | |||||
| } | |||||
| } | } | ||||
| @Override | @Override | ||||
| public void onSaveInstanceState(@NonNull Bundle outState) { | public void onSaveInstanceState(@NonNull Bundle outState) { | ||||
| saveMapState(outState); | saveMapState(outState); | ||||
| super.onSaveInstanceState(outState); | super.onSaveInstanceState(outState); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 165 Lines • ▼ Show 20 Lines | public void startMap(Bundle incoming, Bundle savedInstanceState) { | ||||
| Marker stopMarker = makeMarker(marker, ID , name, routesStopping,true); | Marker stopMarker = makeMarker(marker, ID , name, routesStopping,true); | ||||
| map.getController().animateTo(marker); | map.getController().animateTo(marker); | ||||
| } | } | ||||
| //add the overlays with the bus stops | //add the overlays with the bus stops | ||||
| if(busPositionsOverlay == null){ | if(busPositionsOverlay == null){ | ||||
| //Log.i(DEBUG_TAG, "Null bus positions overlay,redo"); | //Log.i(DEBUG_TAG, "Null bus positions overlay,redo"); | ||||
| busPositionsOverlay = new FolderOverlay(); | busPositionsOverlay = new FolderOverlay(); | ||||
| } | } | ||||
| startRequestsPositions(); | |||||
| if(positionsViewModel !=null){ | |||||
| //should always be the case | |||||
| positionsViewModel.getUpdatesWithTripAndPatterns().observe(getViewLifecycleOwner(), data->{ | |||||
| Log.d(DEBUG_TAG, "Have "+data.size()+" trip updates, has Map start finished: "+hasMapStartFinished); | |||||
| if (hasMapStartFinished) updateBusPositionsInMap(data); | |||||
| //if(!isDetached()) | |||||
| // gtfsPosViewModel.requestDelayedUpdates(4000); | |||||
| }); | |||||
| } else { | |||||
| Log.e(DEBUG_TAG, "PositionsViewModel is null"); | |||||
| } | |||||
| if(stopsViewModel !=null){ | if(stopsViewModel !=null){ | ||||
| stopsViewModel.getStopsInBoundingBox().observe(getViewLifecycleOwner(), | stopsViewModel.getStopsInBoundingBox().observe(getViewLifecycleOwner(), | ||||
| this::showStopsMarkers | this::showStopsMarkers | ||||
| ); | ); | ||||
| } else Log.d(DEBUG_TAG, "Cannot observe new stops in map, stopsViewModel is null"); | } else Log.d(DEBUG_TAG, "Cannot observe new stops in map, stopsViewModel is null"); | ||||
| map.getOverlays().add(this.busPositionsOverlay); | map.getOverlays().add(this.busPositionsOverlay); | ||||
| //set map as started | //set map as started | ||||
| ▲ Show 20 Lines • Show All 229 Lines • Show Last 20 Lines | |||||
Public contents are in Creative Commons Attribution-ShareAlike 4.0 (CC-BY-SA) or GNU Free Documentation License (at your option) unless otherwise noted. · Contact / Register