Changeset View
Changeset View
Standalone View
Standalone View
src/it/reyboz/bustorino/fragments/MapFragment.java
Show First 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | public class MapFragment extends BaseFragment { | ||||
private static final double DEFAULT_CENTER_LON = 7.6858; | private static final double DEFAULT_CENTER_LON = 7.6858; | ||||
private static final double POSITION_FOUND_ZOOM = 18.3; | private static final double POSITION_FOUND_ZOOM = 18.3; | ||||
private static final String DEBUG_TAG=FRAGMENT_TAG; | private static final String DEBUG_TAG=FRAGMENT_TAG; | ||||
protected FragmentListenerMain listenerMain; | protected FragmentListenerMain listenerMain; | ||||
private HashSet<String> shownStops = null; | private HashSet<String> shownStops = null; | ||||
//the asynctask used to get the stops from the database | |||||
private AsyncStopFetcher stopFetcher = null; | |||||
private MapView map = null; | private MapView map = null; | ||||
public Context ctx; | public Context ctx; | ||||
private LocationOverlay mLocationOverlay = null; | private LocationOverlay mLocationOverlay = null; | ||||
private FolderOverlay stopsFolderOverlay = null; | private FolderOverlay stopsFolderOverlay = null; | ||||
private Bundle savedMapState = null; | private Bundle savedMapState = null; | ||||
protected ImageButton btCenterMap; | protected ImageButton btCenterMap; | ||||
Show All 25 Lines | public class MapFragment extends BaseFragment { | ||||
private final ActivityResultLauncher<String[]> positionRequestLauncher = | private final ActivityResultLauncher<String[]> positionRequestLauncher = | ||||
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() { | registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), new ActivityResultCallback<Map<String, Boolean>>() { | ||||
@Override | @Override | ||||
@SuppressLint("MissingPermission") | @SuppressLint("MissingPermission") | ||||
public void onActivityResult(Map<String, Boolean> result) { | public void onActivityResult(Map<String, Boolean> result) { | ||||
if(result.get(Manifest.permission.ACCESS_COARSE_LOCATION) && result.get(Manifest.permission.ACCESS_FINE_LOCATION)){ | if(result.get(Manifest.permission.ACCESS_COARSE_LOCATION) && result.get(Manifest.permission.ACCESS_FINE_LOCATION)){ | ||||
map.getOverlays().remove(mLocationOverlay); | map.getOverlays().remove(mLocationOverlay); | ||||
startLocationOverlay(true); | startLocationOverlay(true, map); | ||||
if(getContext()==null || getContext().getSystemService(Context.LOCATION_SERVICE)==null) | if(getContext()==null || getContext().getSystemService(Context.LOCATION_SERVICE)==null) | ||||
return; | return; | ||||
LocationManager locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); | LocationManager locationManager = (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); | ||||
Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); | Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); | ||||
if (userLocation != null) { | if (userLocation != null) { | ||||
map.getController().setZoom(POSITION_FOUND_ZOOM); | map.getController().setZoom(POSITION_FOUND_ZOOM); | ||||
GeoPoint startPoint = new GeoPoint(userLocation); | GeoPoint startPoint = new GeoPoint(userLocation); | ||||
setLocationFollowing(true); | setLocationFollowing(true); | ||||
Show All 15 Lines | public static MapFragment getInstance(double stopLatit, double stopLong, String stopName, String stopID){ | ||||
args.putDouble(BUNDLE_LATIT, stopLatit); | args.putDouble(BUNDLE_LATIT, stopLatit); | ||||
args.putDouble(BUNDLE_LONGIT, stopLong); | args.putDouble(BUNDLE_LONGIT, stopLong); | ||||
args.putString(BUNDLE_NAME, stopName); | args.putString(BUNDLE_NAME, stopName); | ||||
args.putString(BUNDLE_ID, stopID); | args.putString(BUNDLE_ID, stopID); | ||||
fragment.setArguments(args); | fragment.setArguments(args); | ||||
return fragment; | return fragment; | ||||
} | } | ||||
public static MapFragment getInstance(Stop stop){ | public static MapFragment getInstance(@NonNull Stop stop){ | ||||
return getInstance(stop.getLatitude(), stop.getLongitude(), stop.getStopDisplayName(), stop.ID); | return getInstance(stop.getLatitude(), stop.getLongitude(), stop.getStopDisplayName(), stop.ID); | ||||
} | } | ||||
@Nullable | @Nullable | ||||
@Override | @Override | ||||
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { | ||||
//use the same layout as the activity | //use the same layout as the activity | ||||
▲ Show 20 Lines • Show All 83 Lines • ▼ Show 20 Lines | public void onDetach() { | ||||
// setupOnAttached = true; | // setupOnAttached = true; | ||||
Log.w(DEBUG_TAG, "Fragment detached"); | Log.w(DEBUG_TAG, "Fragment detached"); | ||||
} | } | ||||
@Override | @Override | ||||
public void onPause() { | public void onPause() { | ||||
super.onPause(); | super.onPause(); | ||||
saveMapState(); | saveMapState(); | ||||
//cancel asynctask | |||||
Log.w(DEBUG_TAG, "On pause called"); | |||||
if (stopFetcher!= null) | |||||
stopFetcher.cancel(true); | |||||
} | } | ||||
/** | /** | ||||
* 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(){ | ||||
savedMapState = new Bundle(); | savedMapState = new Bundle(); | ||||
Show All 31 Lines | public class MapFragment extends BaseFragment { | ||||
//own methods | //own methods | ||||
/** | /** | ||||
* Switch following the location on and off | * Switch following the location on and off | ||||
* @param value true if we want to follow location | * @param value true if we want to follow location | ||||
*/ | */ | ||||
public void setLocationFollowing(Boolean value){ | public void setLocationFollowing(Boolean value){ | ||||
followingLocation = value; | followingLocation = value; | ||||
if(mLocationOverlay==null || getContext() == null) | if(mLocationOverlay==null || getContext() == null || map ==null) | ||||
//nothing else to do | //nothing else to do | ||||
return; | return; | ||||
if (value){ | if (value){ | ||||
mLocationOverlay.enableFollowLocation(); | mLocationOverlay.enableFollowLocation(); | ||||
} else { | } else { | ||||
mLocationOverlay.disableFollowLocation(); | mLocationOverlay.disableFollowLocation(); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Do all the stuff you need to do on the gui, when parameter is changed to value | * Do all the stuff you need to do on the gui, when parameter is changed to value | ||||
* @param following value | * @param following value | ||||
*/ | */ | ||||
protected void updateGUIForLocationFollowing(boolean following){ | protected void updateGUIForLocationFollowing(boolean following){ | ||||
if (following) | if (following) | ||||
btFollowMe.setImageResource(R.drawable.ic_follow_me_on); | btFollowMe.setImageResource(R.drawable.ic_follow_me_on); | ||||
else | else | ||||
btFollowMe.setImageResource(R.drawable.ic_follow_me); | btFollowMe.setImageResource(R.drawable.ic_follow_me); | ||||
} | } | ||||
/** | /** | ||||
* Start the location overlay. Enable only when | * Build the location overlay. Enable only when | ||||
* a) we know we have the permission | * a) we know we have the permission | ||||
* b) the location map is set | * b) the location map is set | ||||
*/ | */ | ||||
private void startLocationOverlay(boolean enableLocation){ | private void startLocationOverlay(boolean enableLocation, MapView map){ | ||||
if(getActivity()== null) throw new IllegalStateException("Cannot enable LocationOverlay now"); | if(getActivity()== null) throw new IllegalStateException("Cannot enable LocationOverlay now"); | ||||
// Location Overlay | // Location Overlay | ||||
// from OpenBikeSharing (THANK GOD) | // from OpenBikeSharing (THANK GOD) | ||||
Log.d(DEBUG_TAG, "Starting position overlay"); | Log.d(DEBUG_TAG, "Starting position overlay"); | ||||
GpsMyLocationProvider imlp = new GpsMyLocationProvider(getActivity().getBaseContext()); | GpsMyLocationProvider imlp = new GpsMyLocationProvider(getActivity().getBaseContext()); | ||||
imlp.setLocationUpdateMinDistance(5); | imlp.setLocationUpdateMinDistance(5); | ||||
imlp.setLocationUpdateMinTime(2000); | imlp.setLocationUpdateMinTime(2000); | ||||
this.mLocationOverlay = new LocationOverlay(imlp,map, locationCallbacks); | |||||
if (enableLocation) mLocationOverlay.enableMyLocation(); | |||||
mLocationOverlay.setOptionsMenuEnabled(true); | |||||
map.getOverlays().add(this.mLocationOverlay); | final LocationOverlay overlay = new LocationOverlay(imlp,map, locationCallbacks); | ||||
if (enableLocation) overlay.enableMyLocation(); | |||||
overlay.setOptionsMenuEnabled(true); | |||||
//map.getOverlays().add(this.mLocationOverlay); | |||||
this.mLocationOverlay = overlay; | |||||
map.getOverlays().add(mLocationOverlay); | |||||
} | } | ||||
public void startMap(Bundle incoming, Bundle savedInstanceState) { | public void startMap(Bundle incoming, Bundle savedInstanceState) { | ||||
//Check that we're attached | //Check that we're attached | ||||
GeneralActivity activity = getActivity() instanceof GeneralActivity ? (GeneralActivity) getActivity() : null; | GeneralActivity activity = getActivity() instanceof GeneralActivity ? (GeneralActivity) getActivity() : null; | ||||
if(getContext()==null|| activity==null){ | if(getContext()==null|| activity==null){ | ||||
//we are not attached | //we are not attached | ||||
Log.e(DEBUG_TAG, "Calling startMap when not attached"); | Log.e(DEBUG_TAG, "Calling startMap when not attached"); | ||||
return; | return; | ||||
}else{ | }else{ | ||||
Log.d(DEBUG_TAG, "Starting map from scratch"); | Log.d(DEBUG_TAG, "Starting map from scratch"); | ||||
} | } | ||||
//clear previous overlays | |||||
map.getOverlays().clear(); | |||||
//parse incoming bundle | //parse incoming bundle | ||||
GeoPoint marker = null; | GeoPoint marker = null; | ||||
String name = null; | String name = null; | ||||
String ID = null; | String ID = null; | ||||
if (incoming != null) { | if (incoming != null) { | ||||
double lat = incoming.getDouble(BUNDLE_LATIT); | double lat = incoming.getDouble(BUNDLE_LATIT); | ||||
double lon = incoming.getDouble(BUNDLE_LONGIT); | double lon = incoming.getDouble(BUNDLE_LONGIT); | ||||
marker = new GeoPoint(lat, lon); | marker = new GeoPoint(lat, lon); | ||||
name = incoming.getString(BUNDLE_NAME); | name = incoming.getString(BUNDLE_NAME); | ||||
ID = incoming.getString(BUNDLE_ID); | ID = incoming.getString(BUNDLE_ID); | ||||
} | } | ||||
//ask for location permission | |||||
if(!Permissions.locationPermissionGranted(activity)){ | |||||
if(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)){ | |||||
//TODO: show dialog for permission rationale | |||||
Toast.makeText(activity, R.string.enable_position_message_map, Toast.LENGTH_SHORT).show(); | |||||
} | |||||
positionRequestLauncher.launch(Permissions.LOCATION_PERMISSIONS); | |||||
} | |||||
shownStops = new HashSet<>(); | shownStops = new HashSet<>(); | ||||
// move the map on the marker position or on a default view point: Turin, Piazza Castello | // move the map on the marker position or on a default view point: Turin, Piazza Castello | ||||
// and set the start zoom | // and set the start zoom | ||||
IMapController mapController = map.getController(); | IMapController mapController = map.getController(); | ||||
GeoPoint startPoint = null; | GeoPoint startPoint = null; | ||||
startLocationOverlay(Permissions.locationPermissionGranted(activity), | |||||
map); | |||||
// set the center point | // set the center point | ||||
if (marker != null) { | if (marker != null) { | ||||
startPoint = marker; | startPoint = marker; | ||||
mapController.setZoom(POSITION_FOUND_ZOOM); | mapController.setZoom(POSITION_FOUND_ZOOM); | ||||
setLocationFollowing(false); | setLocationFollowing(false); | ||||
} else if (savedInstanceState != null) { | } else if (savedInstanceState != null && savedInstanceState.containsKey(MAP_CURRENT_ZOOM_KEY)) { | ||||
mapController.setZoom(savedInstanceState.getDouble(MAP_CURRENT_ZOOM_KEY)); | mapController.setZoom(savedInstanceState.getDouble(MAP_CURRENT_ZOOM_KEY)); | ||||
mapController.setCenter(new GeoPoint(savedInstanceState.getDouble(MAP_CENTER_LAT_KEY), | mapController.setCenter(new GeoPoint(savedInstanceState.getDouble(MAP_CENTER_LAT_KEY), | ||||
savedInstanceState.getDouble(MAP_CENTER_LON_KEY))); | savedInstanceState.getDouble(MAP_CENTER_LON_KEY))); | ||||
Log.d(DEBUG_TAG, "Location following from savedInstanceState: "+savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY)); | Log.d(DEBUG_TAG, "Location following from savedInstanceState: "+savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY)); | ||||
setLocationFollowing(savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY)); | setLocationFollowing(savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY)); | ||||
} else { | } else { | ||||
Log.d(DEBUG_TAG, "No position found from intent or saved state"); | Log.d(DEBUG_TAG, "No position found from intent or saved state"); | ||||
boolean found = false; | boolean found = false; | ||||
LocationManager locationManager = | LocationManager locationManager = | ||||
(LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); | (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE); | ||||
//check for permission | //check for permission | ||||
if (locationManager != null && Permissions.locationPermissionGranted(activity)) { | if (locationManager != null && Permissions.locationPermissionGranted(activity)) { | ||||
@SuppressLint("MissingPermission") | @SuppressLint("MissingPermission") | ||||
Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); | Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); | ||||
if (userLocation != null) { | if (userLocation != null) { | ||||
mapController.setZoom(POSITION_FOUND_ZOOM); | mapController.setZoom(POSITION_FOUND_ZOOM); | ||||
startPoint = new GeoPoint(userLocation); | startPoint = new GeoPoint(userLocation); | ||||
found = true; | found = true; | ||||
setLocationFollowing(true); | setLocationFollowing(true); | ||||
} | } | ||||
} else if(!Permissions.locationPermissionGranted(activity)){ | |||||
if(shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)){ | |||||
//TODO: show dialog for permission rationale | |||||
Toast.makeText(activity, R.string.enable_position_message_map, Toast.LENGTH_SHORT).show(); | |||||
} | |||||
positionRequestLauncher.launch(Permissions.LOCATION_PERMISSIONS); | |||||
} | } | ||||
if(!found){ | if(!found){ | ||||
startPoint = new GeoPoint(DEFAULT_CENTER_LAT, DEFAULT_CENTER_LON); | startPoint = new GeoPoint(DEFAULT_CENTER_LAT, DEFAULT_CENTER_LON); | ||||
mapController.setZoom(17.0); | mapController.setZoom(17.0); | ||||
setLocationFollowing(false); | setLocationFollowing(false); | ||||
} | } | ||||
} | } | ||||
startLocationOverlay(Permissions.locationPermissionGranted(activity)); | |||||
// set the minimum zoom level | // set the minimum zoom level | ||||
map.setMinZoomLevel(15.0); | map.setMinZoomLevel(15.0); | ||||
//add contingency check (shouldn't happen..., but) | //add contingency check (shouldn't happen..., but) | ||||
if (startPoint != null) { | if (startPoint != null) { | ||||
mapController.setCenter(startPoint); | mapController.setCenter(startPoint); | ||||
} | } | ||||
//add stops overlay | //add stops overlay | ||||
//map.getOverlays().add(mLocationOverlay); | |||||
map.getOverlays().add(this.stopsFolderOverlay); | map.getOverlays().add(this.stopsFolderOverlay); | ||||
Log.d(DEBUG_TAG, "Requesting stops load"); | Log.d(DEBUG_TAG, "Requesting stops load"); | ||||
// This is not necessary, by setting the center we already move | // This is not necessary, by setting the center we already move | ||||
// the map and we trigger a stop request | // the map and we trigger a stop request | ||||
//requestStopsToShow(); | //requestStopsToShow(); | ||||
if (marker != null) { | if (marker != null) { | ||||
// make a marker with the info window open for the searched marker | // make a marker with the info window open for the searched marker | ||||
makeMarker(startPoint, name , ID, true); | makeMarker(startPoint, name , ID, true); | ||||
} | } | ||||
} | } | ||||
/** | /** | ||||
* Start a request to load the stops that are in the current view | * Start a request to load the stops that are in the current view | ||||
* from the database | * from the database | ||||
*/ | */ | ||||
private void requestStopsToShow(){ | private void requestStopsToShow(){ | ||||
// get the top, bottom, left and right screen's coordinate | // get the top, bottom, left and right screen's coordinate | ||||
BoundingBox bb = map.getBoundingBox(); | BoundingBox bb = map.getBoundingBox(); | ||||
double latFrom = bb.getLatSouth(); | double latFrom = bb.getLatSouth(); | ||||
double latTo = bb.getLatNorth(); | double latTo = bb.getLatNorth(); | ||||
double lngFrom = bb.getLonWest(); | double lngFrom = bb.getLonWest(); | ||||
double lngTo = bb.getLonEast(); | double lngTo = bb.getLonEast(); | ||||
if (stopFetcher!= null && stopFetcher.getStatus()!= AsyncTask.Status.FINISHED) | |||||
new AsyncStopFetcher(this).execute( | stopFetcher.cancel(true); | ||||
stopFetcher = new AsyncStopFetcher(this); | |||||
stopFetcher.execute( | |||||
new AsyncStopFetcher.BoundingBoxLimit(lngFrom,lngTo,latFrom, latTo)); | new AsyncStopFetcher.BoundingBoxLimit(lngFrom,lngTo,latFrom, latTo)); | ||||
} | } | ||||
/** | /** | ||||
* Add stops as Markers on the map | * Add stops as Markers on the map | ||||
* @param stops the list of stops that must be included | * @param stops the list of stops that must be included | ||||
*/ | */ | ||||
protected void showStopsMarkers(List<Stop> stops){ | protected void showStopsMarkers(List<Stop> stops){ | ||||
if (getContext() == null){ | |||||
//we are not attached | |||||
return; | |||||
} | |||||
boolean good = true; | |||||
for (Stop stop : stops) { | for (Stop stop : stops) { | ||||
if (shownStops.contains(stop.ID)){ | if (shownStops.contains(stop.ID)){ | ||||
continue; | continue; | ||||
} | } | ||||
if(stop.getLongitude()==null || stop.getLatitude()==null) | if(stop.getLongitude()==null || stop.getLatitude()==null) | ||||
continue; | continue; | ||||
shownStops.add(stop.ID); | shownStops.add(stop.ID); | ||||
if(!map.isShown()){ | |||||
if(good) | |||||
Log.d(DEBUG_TAG, "Need to show stop but map is not shown, probably detached already"); | |||||
good = false; | |||||
continue; | |||||
} else if(map.getRepository() == null){ | |||||
Log.e(DEBUG_TAG, "Map view repository is null"); | |||||
} | |||||
GeoPoint marker = new GeoPoint(stop.getLatitude(), stop.getLongitude()); | GeoPoint marker = new GeoPoint(stop.getLatitude(), stop.getLongitude()); | ||||
Marker stopMarker = makeMarker(marker, stop.getStopDefaultName(), stop.ID, false); | Marker stopMarker = makeMarker(marker, stop.getStopDefaultName(), stop.ID, false); | ||||
stopsFolderOverlay.add(stopMarker); | stopsFolderOverlay.add(stopMarker); | ||||
if (!map.getOverlays().contains(stopsFolderOverlay)) { | if (!map.getOverlays().contains(stopsFolderOverlay)) { | ||||
Log.w(DEBUG_TAG, "Map doesn't have folder overlay"); | Log.w(DEBUG_TAG, "Map doesn't have folder overlay"); | ||||
} | } | ||||
good=true; | |||||
} | } | ||||
//Log.d(DEBUG_TAG,"We have " +stopsFolderOverlay.getItems().size()+" stops in the folderOverlay"); | //Log.d(DEBUG_TAG,"We have " +stopsFolderOverlay.getItems().size()+" stops in the folderOverlay"); | ||||
//force redraw of markers | //force redraw of markers | ||||
map.invalidate(); | map.invalidate(); | ||||
} | } | ||||
public Marker makeMarker(GeoPoint geoPoint, String stopName, String ID, boolean isStartMarker) { | public Marker makeMarker(GeoPoint geoPoint, String stopName, String ID, boolean isStartMarker) { | ||||
// add a marker | // add a marker | ||||
Marker marker = new Marker(map); | final Marker marker = new Marker(map); | ||||
// set custom info window as info window | // set custom info window as info window | ||||
CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName, responder); | CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName, responder); | ||||
marker.setInfoWindow(popup); | marker.setInfoWindow(popup); | ||||
// make the marker clickable | // make the marker clickable | ||||
marker.setOnMarkerClickListener((thisMarker, mapView) -> { | marker.setOnMarkerClickListener((thisMarker, mapView) -> { | ||||
if (thisMarker.isInfoWindowOpen()) { | if (thisMarker.isInfoWindowOpen()) { | ||||
▲ Show 20 Lines • Show All 92 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