Page Menu
Home
GitPull.it
Search
Configure Global Search
Log In
Files
F11275633
D56.1772605248.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
38 KB
Referenced Files
None
Subscribers
None
D56.1772605248.diff
View Options
diff --git a/build.gradle b/build.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -99,7 +99,7 @@
implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1'
implementation 'com.android.volley:volley:1.2.0'
- implementation 'org.osmdroid:osmdroid-android:6.1.8'
+ implementation 'org.osmdroid:osmdroid-android:6.1.10'
// ACRA
implementation "ch.acra:acra-mail:$acra_version"
implementation "ch.acra:acra-dialog:$acra_version"
diff --git a/src/it/reyboz/bustorino/ActivityMap.java b/src/it/reyboz/bustorino/ActivityMap.java
--- a/src/it/reyboz/bustorino/ActivityMap.java
+++ b/src/it/reyboz/bustorino/ActivityMap.java
@@ -32,6 +32,7 @@
import android.widget.ImageButton;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.preference.PreferenceManager;
@@ -87,6 +88,21 @@
protected ImageButton btCenterMap;
protected ImageButton btFollowMe;
+ private final CustomInfoWindow.TouchResponder touchResponder = new CustomInfoWindow.TouchResponder() {
+ @Override
+ public void onActionUp(@NonNull String stopID, @Nullable String stopName) {
+ Intent intent = new Intent(ctx, ActivityMain.class);
+ Bundle b = new Bundle();
+ b.putString("bus-stop-ID", stopID);
+ b.putString("bus-stop-display-name", stopName);
+ intent.putExtras(b);
+ intent.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+
+ // start ActivityMain with the previous intent
+ ctx.startActivity(intent);
+ }
+ };
+
//@RequiresApi(api = Build.VERSION_CODES.HONEYCOMB)
@Override
public void onCreate(Bundle savedInstanceState) {
@@ -268,7 +284,7 @@
Marker marker = new Marker(map);
// set custom info window as info window
- CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName);
+ CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName, touchResponder);
marker.setInfoWindow(popup);
// make the marker clickable
@@ -369,6 +385,12 @@
}
+ @Override
+ protected void onPostResume() {
+ super.onPostResume();
+ ctx = this;
+ }
+
protected boolean detachMapFromPosition(){
if (mLocationOverlay.isFollowLocationEnabled()) {
mLocationOverlay.disableFollowLocation();
diff --git a/src/it/reyboz/bustorino/ActivityPrincipal.java b/src/it/reyboz/bustorino/ActivityPrincipal.java
--- a/src/it/reyboz/bustorino/ActivityPrincipal.java
+++ b/src/it/reyboz/bustorino/ActivityPrincipal.java
@@ -32,12 +32,14 @@
import java.util.concurrent.TimeUnit;
+import it.reyboz.bustorino.backend.Stop;
import it.reyboz.bustorino.data.DBUpdateWorker;
import it.reyboz.bustorino.data.DatabaseUpdate;
import it.reyboz.bustorino.fragments.FavoritesFragment;
import it.reyboz.bustorino.fragments.FragmentKind;
import it.reyboz.bustorino.fragments.FragmentListenerMain;
import it.reyboz.bustorino.fragments.MainScreenFragment;
+import it.reyboz.bustorino.fragments.MapFragment;
import it.reyboz.bustorino.middleware.GeneralActivity;
import static it.reyboz.bustorino.backend.utils.getBusStopIDFromUri;
@@ -209,6 +211,10 @@
closeDrawerIfOpen();
showMainFragment();
return true;
+ } else if(menuItem.getItemId() == R.id.nav_map_item){
+ closeDrawerIfOpen();
+ createAndShowMapFragment(null);
+ return true;
}
//selectDrawerItem(menuItem);
Log.d(DEBUG_TAG, "pressed item "+menuItem.toString());
@@ -359,6 +365,21 @@
public void showFloatingActionButton(boolean yes) {
//TODO
}
+ /*
+ public void setDrawerSelectedItem(String fragmentTag){
+ switch (fragmentTag){
+ case MainScreenFragment.FRAGMENT_TAG:
+ mNavView.setCheckedItem(R.id.nav_arrivals);
+ break;
+ case MapFragment.FRAGMENT_TAG:
+
+ break;
+
+ case FavoritesFragment.FRAGMENT_TAG:
+ mNavView.setCheckedItem(R.id.nav_favorites_item);
+ break;
+ }
+ }*/
@Override
public void readyGUIfor(FragmentKind fragmentType) {
@@ -366,6 +387,21 @@
if (probableFragment!=null){
probableFragment.readyGUIfor(fragmentType);
}
+ switch (fragmentType){
+ case MAP:
+ mNavView.setCheckedItem(R.id.nav_map_item);
+ break;
+ case FAVORITES:
+ mNavView.setCheckedItem(R.id.nav_favorites_item);
+ break;
+ case ARRIVALS:
+ case NEARBY_STOPS:
+ case STOPS:
+ case MAIN_SCREEN_FRAGMENT:
+ case NEARBY_ARRIVALS:
+ mNavView.setCheckedItem(R.id.nav_arrivals);
+ break;
+ }
}
@Override
@@ -408,6 +444,17 @@
}
}
+ //Map Fragment stuff
+ void createAndShowMapFragment(@Nullable Stop stop){
+ FragmentManager fm = getSupportFragmentManager();
+ FragmentTransaction ft = fm.beginTransaction();
+ MapFragment fragment = stop == null? MapFragment.getInstance(): MapFragment.getInstance(stop);
+ ft.replace(R.id.mainActContentFrame, fragment, MapFragment.FRAGMENT_TAG);
+ ft.addToBackStack(null);
+ ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
+ ft.commit();
+ }
+
class ToolbarItemClickListener implements Toolbar.OnMenuItemClickListener{
@Override
diff --git a/src/it/reyboz/bustorino/data/NextGenDB.java b/src/it/reyboz/bustorino/data/NextGenDB.java
--- a/src/it/reyboz/bustorino/data/NextGenDB.java
+++ b/src/it/reyboz/bustorino/data/NextGenDB.java
@@ -157,7 +157,7 @@
Stop[] stops = new Stop[0];
SQLiteDatabase db = this.getReadableDatabase();
- Cursor result;
+ //Cursor result=null;
int count;
// coordinates must be strings in the where condition
@@ -172,20 +172,19 @@
}
try {
- result = db.query(StopsTable.TABLE_NAME, QUERY_COLUMN_stops_all, QUERY_WHERE_LAT_AND_LNG_IN_RANGE,
+ final Cursor result = db.query(StopsTable.TABLE_NAME, QUERY_COLUMN_stops_all, QUERY_WHERE_LAT_AND_LNG_IN_RANGE,
new String[] {minLatRaw, maxLatRaw, minLngRaw, maxLngRaw},
null, null, null);
stops = getStopsFromCursorAllFields(result);
-
+ result.close();
} catch(SQLiteException e) {
Log.e(DEBUG_TAG, "SQLiteException occurred");
e.printStackTrace();
return stops;
+ }finally {
+ db.close();
}
- result.close();
- db.close();
-
return stops;
}
diff --git a/src/it/reyboz/bustorino/fragments/CommonScrollListener.java b/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
--- a/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
+++ b/src/it/reyboz/bustorino/fragments/CommonScrollListener.java
@@ -51,11 +51,11 @@
}
if (firstVisibleItem>=0) {
if (lastvisibleitem < firstVisibleItem) {
- Log.i("Busto", "Scrolling DOWN");
+ //Log.i("Busto", "Scrolling DOWN");
listener.showFloatingActionButton(false);
//lastScrollUp = true;
} else if (lastvisibleitem > firstVisibleItem) {
- Log.i("Busto", "Scrolling UP");
+ //Log.i("Busto", "Scrolling UP");
listener.showFloatingActionButton(true);
//lastScrollUp = false;
}
diff --git a/src/it/reyboz/bustorino/fragments/FavoritesFragment.java b/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
--- a/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
+++ b/src/it/reyboz/bustorino/fragments/FavoritesFragment.java
@@ -45,6 +45,8 @@
@Nullable
private CommonFragmentListener mListener;
+ public static final String FRAGMENT_TAG = "BusTOFavFragment";
+
@@ -56,7 +58,7 @@
fragment.setArguments(args);
return fragment;
}
- private FavoritesFragment(){
+ public FavoritesFragment(){
}
@@ -123,6 +125,12 @@
}
}
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (mListener!=null) mListener.readyGUIfor(FragmentKind.FAVORITES);
+ }
+
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item
@@ -177,6 +185,7 @@
}
}
+
void showStops(List<Stop> busStops){
// If no data is found show a friendly message
diff --git a/src/it/reyboz/bustorino/fragments/FragmentKind.java b/src/it/reyboz/bustorino/fragments/FragmentKind.java
--- a/src/it/reyboz/bustorino/fragments/FragmentKind.java
+++ b/src/it/reyboz/bustorino/fragments/FragmentKind.java
@@ -18,5 +18,5 @@
package it.reyboz.bustorino.fragments;
public enum FragmentKind {
- STOPS,ARRIVALS,FAVORITES,NEARBY_STOPS,NEARBY_ARRIVALS
+ STOPS,ARRIVALS,FAVORITES,NEARBY_STOPS,NEARBY_ARRIVALS, MAP, MAIN_SCREEN_FRAGMENT
}
diff --git a/src/it/reyboz/bustorino/fragments/FragmentListenerMain.java b/src/it/reyboz/bustorino/fragments/FragmentListenerMain.java
--- a/src/it/reyboz/bustorino/fragments/FragmentListenerMain.java
+++ b/src/it/reyboz/bustorino/fragments/FragmentListenerMain.java
@@ -23,14 +23,7 @@
void toggleSpinner(boolean state);
-
- /*
- Unused method
- * Add the last successfully searched stop to the favorites
- */
-
- //void toggleLastStopToFavorites();
-
+ //TODO: implement void showStopOnMap()
/**
* Tell activity that we need to enable/disable the refreshLayout
diff --git a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
--- a/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
+++ b/src/it/reyboz/bustorino/fragments/MainScreenFragment.java
@@ -318,6 +318,7 @@
requestArrivalsForStopID(pendingStopID);
pendingStopID = null;
}
+ mListener.readyGUIfor(FragmentKind.MAIN_SCREEN_FRAGMENT);
}
@Override
@@ -326,6 +327,7 @@
locmgr = null;
super.onPause();
}
+
/*
GUI METHODS
*/
@@ -490,7 +492,7 @@
prepareGUIForBusStops();
break;
default:
- Log.e("BusTO Activity", "Called readyGUI with unsupported type of Fragment");
+ Log.d(DEBUG_TAG, "Fragment type is unknown");
return;
}
// Shows hints
diff --git a/src/it/reyboz/bustorino/fragments/MapFragment.java b/src/it/reyboz/bustorino/fragments/MapFragment.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/fragments/MapFragment.java
@@ -0,0 +1,532 @@
+package it.reyboz.bustorino.fragments;
+
+import android.Manifest;
+import android.content.Context;
+
+import android.content.pm.PackageManager;
+import android.location.Location;
+import android.location.LocationManager;
+import android.os.AsyncTask;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.core.app.ActivityCompat;
+import androidx.core.content.res.ResourcesCompat;
+import androidx.preference.PreferenceManager;
+
+import org.osmdroid.api.IGeoPoint;
+import org.osmdroid.api.IMapController;
+import org.osmdroid.config.Configuration;
+import org.osmdroid.events.DelayedMapListener;
+import org.osmdroid.events.MapListener;
+import org.osmdroid.events.ScrollEvent;
+import org.osmdroid.events.ZoomEvent;
+import org.osmdroid.tileprovider.tilesource.TileSourceFactory;
+import org.osmdroid.util.BoundingBox;
+import org.osmdroid.util.GeoPoint;
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.FolderOverlay;
+import org.osmdroid.views.overlay.Marker;
+import org.osmdroid.views.overlay.infowindow.InfoWindow;
+import org.osmdroid.views.overlay.mylocation.GpsMyLocationProvider;
+
+import java.lang.ref.WeakReference;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+
+import it.reyboz.bustorino.R;
+import it.reyboz.bustorino.backend.Stop;
+import it.reyboz.bustorino.data.NextGenDB;
+import it.reyboz.bustorino.map.CustomInfoWindow;
+import it.reyboz.bustorino.map.LocationOverlay;
+import it.reyboz.bustorino.middleware.GeneralActivity;
+
+import static it.reyboz.bustorino.util.Permissions.PERMISSION_REQUEST_POSITION;
+
+public class MapFragment extends BaseFragment {
+
+ private static final String TAG = "Busto-MapActivity";
+ private static final String MAP_CURRENT_ZOOM_KEY = "map-current-zoom";
+ private static final String MAP_CENTER_LAT_KEY = "map-center-lat";
+ private static final String MAP_CENTER_LON_KEY = "map-center-lon";
+ private static final String FOLLOWING_LOCAT_KEY ="following";
+
+ public static final String BUNDLE_LATIT = "lat";
+ public static final String BUNDLE_LONGIT = "lon";
+ public static final String BUNDLE_NAME = "name";
+ public static final String BUNDLE_ID = "ID";
+
+ public static final String FRAGMENT_TAG="BusTOMapFragment";
+
+
+ private static final double DEFAULT_CENTER_LAT = 45.0708;
+ private static final double DEFAULT_CENTER_LON = 7.6858;
+ private static final double POSITION_FOUND_ZOOM = 18.3;
+
+ private static final String DEBUG_TAG=FRAGMENT_TAG;
+
+ protected FragmentListenerMain listenerMain;
+
+ private HashSet<String> shownStops = null;
+
+
+ private MapView map = null;
+ public Context ctx;
+ private LocationOverlay mLocationOverlay = null;
+ private FolderOverlay stopsFolderOverlay = null;
+ private Bundle savedMapState = null;
+ protected ImageButton btCenterMap;
+ protected ImageButton btFollowMe;
+ private boolean followingLocation = false;
+
+ protected final CustomInfoWindow.TouchResponder responder = new CustomInfoWindow.TouchResponder() {
+ @Override
+ public void onActionUp(@NonNull String stopID, @Nullable String stopName) {
+ if (listenerMain!= null){
+ listenerMain.requestArrivalsForStopID(stopID);
+ }
+ }
+ };
+ protected final LocationOverlay.OverlayCallbacks locationCallbacks = new LocationOverlay.OverlayCallbacks() {
+ @Override
+ public void onDisableFollowMyLocation() {
+ updateGUIForLocationFollowing(false);
+ followingLocation=false;
+ }
+
+ @Override
+ public void onEnableFollowMyLocation() {
+ updateGUIForLocationFollowing(true);
+ followingLocation=true;
+ }
+ };
+
+ public MapFragment() {
+ }
+ public static MapFragment getInstance(){
+ return new MapFragment();
+ }
+ public static MapFragment getInstance(double stopLatit, double stopLong, String stopName, String stopID){
+ MapFragment fragment= new MapFragment();
+ Bundle args = new Bundle();
+ args.putDouble(BUNDLE_LATIT, stopLatit);
+ args.putDouble(BUNDLE_LONGIT, stopLong);
+ args.putString(BUNDLE_NAME, stopName);
+ args.putString(BUNDLE_ID, stopID);
+ fragment.setArguments(args);
+
+ return fragment;
+ }
+ public static MapFragment getInstance(Stop stop){
+ return getInstance(stop.getLatitude(), stop.getLongitude(), stop.getStopDisplayName(), stop.ID);
+ }
+
+
+ @Nullable
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
+ //use the same layout as the activity
+ View root = inflater.inflate(R.layout.activity_map, container, false);
+ if (getContext() == null){
+ throw new IllegalStateException();
+ }
+ ctx = getContext().getApplicationContext();
+ Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx));
+ map = root.findViewById(R.id.map);
+ map.setTileSource(TileSourceFactory.MAPNIK);
+ //map.setTilesScaledToDpi(true);
+ map.setFlingEnabled(true);
+
+ // add ability to zoom with 2 fingers
+ map.setMultiTouchControls(true);
+
+ btCenterMap = root.findViewById(R.id.ic_center_map);
+ btFollowMe = root.findViewById(R.id.ic_follow_me);
+
+ //setup FolderOverlay
+ stopsFolderOverlay = new FolderOverlay();
+
+
+ //Start map from bundle
+ if (savedInstanceState !=null)
+ startMap(getArguments(), savedInstanceState);
+ else startMap(getArguments(), savedMapState);
+ //set listeners
+ map.addMapListener(new DelayedMapListener(new MapListener() {
+
+ @Override
+ public boolean onScroll(ScrollEvent paramScrollEvent) {
+ requestStopsToShow();
+ //Log.d(DEBUG_TAG, "Scrolling");
+ //if (moveTriggeredByCode) moveTriggeredByCode =false;
+ //else setLocationFollowing(false);
+ return true;
+ }
+
+ @Override
+ public boolean onZoom(ZoomEvent event) {
+ requestStopsToShow();
+ return true;
+ }
+
+ }));
+
+
+ btCenterMap.setOnClickListener(v -> {
+ //Log.i(TAG, "centerMap clicked ");
+ final GeoPoint myPosition = mLocationOverlay.getMyLocation();
+ map.getController().animateTo(myPosition);
+ });
+
+ btFollowMe.setOnClickListener(v -> {
+ //Log.i(TAG, "btFollowMe clicked ");
+ switchLocationFollowing(!followingLocation);
+ });
+
+ return root;
+ }
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+
+ if (context instanceof FragmentListenerMain) {
+ listenerMain = (FragmentListenerMain) context;
+ } else {
+ throw new RuntimeException(context.toString()
+ + " must implement FragmentListenerMain");
+ }
+ }
+ @Override
+ public void onDetach() {
+ super.onDetach();
+ listenerMain = null;
+ // setupOnAttached = true;
+ Log.w(DEBUG_TAG, "Fragment detached");
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ saveMapState();
+ }
+
+ /**
+ * Save the map state inside the fragment
+ * (calls saveMapState(bundle))
+ */
+ private void saveMapState(){
+ savedMapState = new Bundle();
+ saveMapState(savedMapState);
+
+ }
+
+ /**
+ * Save the state of the map to restore it to a later time
+ * @param bundle the bundle in which to save the data
+ */
+ private void saveMapState(Bundle bundle){
+ final IGeoPoint loc = map.getMapCenter();
+ bundle.putDouble(MAP_CENTER_LAT_KEY, loc.getLatitude());
+ bundle.putDouble(MAP_CENTER_LON_KEY, loc.getLongitude());
+ bundle.putDouble(MAP_CURRENT_ZOOM_KEY, map.getZoomLevelDouble());
+ Log.d(DEBUG_TAG, "Saving state, location following: "+followingLocation);
+ bundle.putBoolean(FOLLOWING_LOCAT_KEY, followingLocation);
+
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if(listenerMain!=null) listenerMain.readyGUIfor(FragmentKind.MAP);
+ }
+
+ @Override
+ public void onSaveInstanceState(@NonNull Bundle outState) {
+ saveMapState(outState);
+
+ super.onSaveInstanceState(outState);
+ }
+
+ //own methods
+
+ /**
+ * Switch following the location on and off
+ * @param value true if we want to follow location
+ */
+ public void switchLocationFollowing(Boolean value){
+ followingLocation = value;
+ if (value){
+ mLocationOverlay.enableFollowLocation();
+ } else {
+ mLocationOverlay.disableFollowLocation();
+ }
+ }
+
+ /**
+ * Do all the stuff you need to do on the gui, when parameter is changed to value
+ * @param following value
+ */
+ protected void updateGUIForLocationFollowing(boolean following){
+ if (following)
+ btFollowMe.setImageResource(R.drawable.ic_follow_me_on);
+ else
+ btFollowMe.setImageResource(R.drawable.ic_follow_me);
+
+ }
+
+ public void startMap(Bundle incoming, Bundle savedInstanceState) {
+ //Check that we're attached
+ GeneralActivity activity = getActivity() instanceof GeneralActivity ? (GeneralActivity) getActivity() : null;
+ if(getContext()==null|| activity==null){
+ //we are not attached
+ Log.e(DEBUG_TAG, "Calling startMap when not attached");
+ return;
+ }else{
+ Log.d(DEBUG_TAG, "Starting map from scratch");
+ }
+
+
+ //parse incoming bundle
+ GeoPoint marker = null;
+ String name = null;
+ String ID = null;
+ if (incoming != null) {
+ double lat = incoming.getDouble(BUNDLE_LATIT);
+ double lon = incoming.getDouble(BUNDLE_LONGIT);
+ marker = new GeoPoint(lat, lon);
+ name = incoming.getString(BUNDLE_NAME);
+ ID = incoming.getString(BUNDLE_ID);
+ }
+
+ shownStops = new HashSet<>();
+ // move the map on the marker position or on a default view point: Turin, Piazza Castello
+ // and set the start zoom
+ IMapController mapController = map.getController();
+ GeoPoint startPoint = null;
+
+ boolean havePositionPermission = true;
+
+ if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
+ activity.askForPermissionIfNeeded(Manifest.permission.ACCESS_FINE_LOCATION, PERMISSION_REQUEST_POSITION);
+ havePositionPermission = false;
+ }
+ // Location Overlay
+ // from OpenBikeSharing (THANK GOD)
+ GpsMyLocationProvider imlp = new GpsMyLocationProvider(activity.getBaseContext());
+ imlp.setLocationUpdateMinDistance(5);
+ imlp.setLocationUpdateMinTime(2000);
+ this.mLocationOverlay = new LocationOverlay(imlp,map, locationCallbacks);
+ mLocationOverlay.enableMyLocation();
+ mLocationOverlay.setOptionsMenuEnabled(true);
+
+ if (marker != null) {
+ startPoint = marker;
+ mapController.setZoom(POSITION_FOUND_ZOOM);
+ switchLocationFollowing(false);
+ } else if (savedInstanceState != null) {
+ mapController.setZoom(savedInstanceState.getDouble(MAP_CURRENT_ZOOM_KEY));
+ mapController.setCenter(new GeoPoint(savedInstanceState.getDouble(MAP_CENTER_LAT_KEY),
+ savedInstanceState.getDouble(MAP_CENTER_LON_KEY)));
+ Log.d(DEBUG_TAG, "Location following from savedInstanceState: "+savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY));
+ switchLocationFollowing(savedInstanceState.getBoolean(FOLLOWING_LOCAT_KEY));
+ } else {
+ Log.d(DEBUG_TAG, "No position found from intent or saved state");
+ boolean found = false;
+ LocationManager locationManager =
+ (LocationManager) getContext().getSystemService(Context.LOCATION_SERVICE);
+ if (locationManager != null) {
+
+ Location userLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
+ if (userLocation != null) {
+ mapController.setZoom(POSITION_FOUND_ZOOM);
+ startPoint = new GeoPoint(userLocation);
+ found = true;
+ switchLocationFollowing(true);
+ }
+ }
+ if(!found){
+ startPoint = new GeoPoint(DEFAULT_CENTER_LAT, DEFAULT_CENTER_LON);
+ mapController.setZoom(16.0);
+ switchLocationFollowing(false);
+ }
+ }
+
+ // set the minimum zoom level
+ map.setMinZoomLevel(15.0);
+ //add contingency check (shouldn't happen..., but)
+ if (startPoint != null) {
+ mapController.setCenter(startPoint);
+ }
+
+
+
+ map.getOverlays().add(this.mLocationOverlay);
+
+ //add stops overlay
+ map.getOverlays().add(this.stopsFolderOverlay);
+
+ Log.d(DEBUG_TAG, "Requesting stops load");
+ // This is not necessary, by setting the center we already move
+ // the map and we trigger a stop request
+ //requestStopsToShow();
+ if (marker != null) {
+ // make a marker with the info window open for the searched marker
+ makeMarker(startPoint, name , ID, true);
+ }
+
+ }
+
+ /**
+ * Start a request to load the stops that are in the current view
+ * from the database
+ */
+ private void requestStopsToShow(){
+ // get the top, bottom, left and right screen's coordinate
+ BoundingBox bb = map.getBoundingBox();
+ double latFrom = bb.getLatSouth();
+ double latTo = bb.getLatNorth();
+ double lngFrom = bb.getLonWest();
+ double lngTo = bb.getLonEast();
+
+ new AsyncStopFetcher(this).execute(
+ new AsyncStopFetcher.BoundingBoxLimit(lngFrom,lngTo,latFrom, latTo));
+ }
+
+ /**
+ * Add stops as Markers on the map
+ * @param stops the list of stops that must be included
+ */
+ protected void showStopsMarkers(List<Stop> stops){
+
+ for (Stop stop : stops) {
+ if (shownStops.contains(stop.ID)){
+ continue;
+ }
+ if(stop.getLongitude()==null || stop.getLatitude()==null)
+ continue;
+
+ shownStops.add(stop.ID);
+ GeoPoint marker = new GeoPoint(stop.getLatitude(), stop.getLongitude());
+ Marker stopMarker = makeMarker(marker, stop.getStopDefaultName(), stop.ID, false);
+ stopsFolderOverlay.add(stopMarker);
+ if (!map.getOverlays().contains(stopsFolderOverlay)) {
+ Log.w(DEBUG_TAG, "Map doesn't have folder overlay");
+ }
+ }
+ //Log.d(DEBUG_TAG,"We have " +stopsFolderOverlay.getItems().size()+" stops in the folderOverlay");
+ //force redraw of markers
+ map.invalidate();
+ }
+
+ public Marker makeMarker(GeoPoint geoPoint, String stopName, String ID, boolean isStartMarker) {
+
+ // add a marker
+ Marker marker = new Marker(map);
+
+ // set custom info window as info window
+ CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName, responder);
+ marker.setInfoWindow(popup);
+
+ // make the marker clickable
+ marker.setOnMarkerClickListener((thisMarker, mapView) -> {
+ if (thisMarker.isInfoWindowOpen()) {
+ // on second click
+ //TODO: show the arrivals for the stop
+ Log.w(DEBUG_TAG, "Pressed on the click marker");
+ } else {
+ // on first click
+
+ // hide all opened info window
+ InfoWindow.closeAllInfoWindowsOn(map);
+ // show this particular info window
+ thisMarker.showInfoWindow();
+ // move the map to its position
+ map.getController().animateTo(thisMarker.getPosition());
+ }
+
+ return true;
+ });
+
+ // set its position
+ marker.setPosition(geoPoint);
+ marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM);
+ // add to it an icon
+ //marker.setIcon(getResources().getDrawable(R.drawable.bus_marker));
+
+ marker.setIcon(ResourcesCompat.getDrawable(getResources(), R.drawable.bus_marker, ctx.getTheme()));
+ // add to it a title
+ marker.setTitle(stopName);
+ // set the description as the ID
+ marker.setSnippet(ID);
+
+ // show popup info window of the searched marker
+ if (isStartMarker) {
+ marker.showInfoWindow();
+ }
+
+ return marker;
+ }
+
+ /**
+ * Simple asyncTask class to load the stops in the background
+ * Holds a weak reference to the fragment to do callbacks
+ */
+ static class AsyncStopFetcher extends AsyncTask<AsyncStopFetcher.BoundingBoxLimit,Void, List<Stop>>{
+
+ final WeakReference<MapFragment> fragmentWeakReference;
+
+ public AsyncStopFetcher(MapFragment fragment) {
+ this.fragmentWeakReference = new WeakReference<>(fragment);
+ }
+
+ @Override
+ protected List<Stop> doInBackground(BoundingBoxLimit... limits) {
+ if(fragmentWeakReference.get()==null || fragmentWeakReference.get().getContext() == null){
+ Log.w(DEBUG_TAG, "AsyncLoad fragmentWeakreference null");
+
+ return null;
+
+ }
+ final BoundingBoxLimit limit = limits[0];
+ //Log.d(DEBUG_TAG, "Async Stop Fetcher started working");
+
+ NextGenDB dbHelper = new NextGenDB(fragmentWeakReference.get().getContext());
+ Stop[] stops = dbHelper.queryAllInsideMapView(limit.latitFrom, limit.latitTo,
+ limit.longFrom, limit.latitTo);
+ dbHelper.close();
+ return Arrays.asList(stops);
+ }
+
+ @Override
+ protected void onPostExecute(List<Stop> stops) {
+ super.onPostExecute(stops);
+ //Log.d(DEBUG_TAG, "Async Stop Fetcher has finished working");
+ if(fragmentWeakReference.get()==null) {
+ Log.w(DEBUG_TAG, "AsyncLoad fragmentWeakreference null");
+ return;
+ }
+ Log.d(DEBUG_TAG, "AsyncLoad number of stops: "+stops.size());
+ fragmentWeakReference.get().showStopsMarkers(stops);
+ }
+
+ private static class BoundingBoxLimit{
+ final double longFrom, longTo, latitFrom, latitTo;
+
+ public BoundingBoxLimit(double longFrom, double longTo, double latitFrom, double latitTo) {
+ this.longFrom = longFrom;
+ this.longTo = longTo;
+ this.latitFrom = latitFrom;
+ this.latitTo = latitTo;
+ }
+ }
+
+ }
+}
diff --git a/src/it/reyboz/bustorino/map/CustomInfoWindow.java b/src/it/reyboz/bustorino/map/CustomInfoWindow.java
--- a/src/it/reyboz/bustorino/map/CustomInfoWindow.java
+++ b/src/it/reyboz/bustorino/map/CustomInfoWindow.java
@@ -1,27 +1,28 @@
package it.reyboz.bustorino.map;
import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Bundle;
-import android.util.Log;
+import android.os.Build;
import android.view.MotionEvent;
import android.view.View;
import android.widget.TextView;
-import org.osmdroid.api.IMapView;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
import org.osmdroid.views.MapView;
import org.osmdroid.views.overlay.infowindow.BasicInfoWindow;
-import it.reyboz.bustorino.ActivityMain;
import it.reyboz.bustorino.R;
public class CustomInfoWindow extends BasicInfoWindow {
+ //TODO: Make the action on the Click customizable
+ private final TouchResponder touchResponder;
+ private final String stopID, name;
@Override
public void onOpen(Object item) {
super.onOpen(item);
-
TextView descr_textView = (TextView) mView.findViewById(R.id.bubble_description);
CharSequence text = descr_textView.getText();
if (text==null || !text.toString().isEmpty()){
@@ -29,32 +30,35 @@
} else
descr_textView.setVisibility(View.GONE);
- mView.setElevation(3.2f);
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
+ mView.setElevation(3.2f);
+ }
}
@SuppressLint("ClickableViewAccessibility")
- public CustomInfoWindow(MapView mapView, String ID, String stopName) {
+ public CustomInfoWindow(MapView mapView, String stopID, String name, TouchResponder responder) {
// get the personalized layout
super(R.layout.map_popup, mapView);
+ touchResponder =responder;
+ this.stopID = stopID;
+ this.name = name;
// make clickable
mView.setOnTouchListener((View v, MotionEvent e) -> {
if (e.getAction() == MotionEvent.ACTION_UP) {
// on click
-
- // create an intent with these extras
- Intent intent = new Intent(mapView.getContext(), ActivityMain.class);
- Bundle b = new Bundle();
- b.putString("bus-stop-ID", ID);
- b.putString("bus-stop-display-name", stopName);
- intent.putExtras(b);
- intent.setFlags(Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
-
- // start ActivityMain with the previous intent
- mapView.getContext().startActivity(intent);
+ touchResponder.onActionUp(stopID, name);
}
return true;
});
}
+ public interface TouchResponder{
+ /**
+ * React to a click on the stop View
+ * @param stopID the stop id
+ * @param stopName the stop name
+ */
+ void onActionUp(@NonNull String stopID, @Nullable String stopName);
+ }
}
diff --git a/src/it/reyboz/bustorino/map/LocationOverlay.java b/src/it/reyboz/bustorino/map/LocationOverlay.java
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/map/LocationOverlay.java
@@ -0,0 +1,62 @@
+/*
+ BusTO (middleware)
+ Copyright (C) 2021 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 <http://www.gnu.org/licenses/>.
+ */
+package it.reyboz.bustorino.map;
+
+
+import org.osmdroid.views.MapView;
+import org.osmdroid.views.overlay.mylocation.IMyLocationProvider;
+import org.osmdroid.views.overlay.mylocation.MyLocationNewOverlay;
+
+public class LocationOverlay extends MyLocationNewOverlay {
+
+ final OverlayCallbacks callbacks;
+
+ public LocationOverlay(MapView mapView, OverlayCallbacks callbacks) {
+ super(mapView);
+ this.callbacks = callbacks;
+ }
+
+ public LocationOverlay(IMyLocationProvider myLocationProvider, MapView mapView, OverlayCallbacks callbacks) {
+ super(myLocationProvider, mapView);
+ this.callbacks = callbacks;
+ }
+
+ @Override
+ public void enableFollowLocation() {
+ super.enableFollowLocation();
+ callbacks.onEnableFollowMyLocation();
+ }
+
+ @Override
+ public void disableFollowLocation() {
+ super.disableFollowLocation();
+ callbacks.onDisableFollowMyLocation();
+ }
+
+ public interface OverlayCallbacks{
+ /**
+ * Called right after disableFollowMyLocation
+ */
+ void onDisableFollowMyLocation();
+
+ /**
+ * Called right after enableFollowMyLocation
+ */
+ void onEnableFollowMyLocation();
+ }
+}
diff --git a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
--- a/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
+++ b/src/it/reyboz/bustorino/middleware/AsyncDataDownload.java
@@ -45,6 +45,7 @@
public class AsyncDataDownload extends AsyncTask<String,Fetcher.result,Object>{
private static final String TAG = "BusTO-DataDownload";
+ private static final String DEBUG_TAG = TAG;
private boolean failedAll = false;
private final AtomicReference<Fetcher.result> res;
@@ -212,9 +213,24 @@
break;
case STOPS:
//this should never be a problem
- List<Stop> stopList = (List<Stop>) o;
+ if(!(o instanceof List<?>)){
+ throw new IllegalStateException();
+ }
+ List<?> list = (List<?>) o;
+ if (list.size() ==0) return;
+ Object firstItem = list.get(0);
+ if(!(firstItem instanceof Stop)) return;
+ ArrayList<Stop> stops = new ArrayList<>();
+ for(Object x: list){
+ if(x instanceof Stop) stops.add((Stop) x);
+ }
+ if(list.size() != stops.size()){
+ Log.w(DEBUG_TAG, "Wrong stop list size:\n incoming: "+
+ list.size()+" out: "+stops.size());
+ }
+ //List<Stop> stopList = (List<Stop>) list;
if(query!=null && !isCancelled()) {
- fh.createStopListFragment(stopList,query, replaceFragment);
+ fh.createStopListFragment(stops,query, replaceFragment);
} else Log.e(TAG,"QUERY NULL, COULD NOT CREATE FRAGMENT");
break;
case DBUPDATE:
@@ -239,20 +255,21 @@
ARRIVALS,STOPS,DBUPDATE
}
- public class BranchInserter implements Runnable{
+ public static class BranchInserter implements Runnable{
private final List<Route> routesToInsert;
private final Context context;
- private final NextGenDB nextGenDB;
+ //private final NextGenDB nextGenDB;
public BranchInserter(List<Route> routesToInsert,@NonNull Context con) {
this.routesToInsert = routesToInsert;
- this.context = con;
- nextGenDB = new NextGenDB(context);
+ this.context = con.getApplicationContext();
+ //nextGenDB = new NextGenDB(context);
}
@Override
public void run() {
+ final NextGenDB nextGenDB = new NextGenDB(context);
ContentValues[] values = new ContentValues[routesToInsert.size()];
ArrayList<ContentValues> connectionsVals = new ArrayList<>(routesToInsert.size()*4);
long starttime,endtime;
@@ -324,6 +341,7 @@
int rows = nextGenDB.insertBatchContent(valArr,ConnectionsTable.TABLE_NAME);
endtime = System.currentTimeMillis();
Log.d("DataDownload","Inserted connections found, took "+(endtime-starttime)+" ms, inserted "+rows+" rows");
+ nextGenDB.close();
}
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Mar 4, 07:20 (2 h, 38 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1710770
Default Alt Text
D56.1772605248.diff (38 KB)
Attached To
Mode
D56: Add map fragment and fix stuff
Attached
Detach File
Event Timeline
Log In to Comment