Page MenuHomeGitPull.it

D56.1772596090.diff
No OneTemporary

Size
38 KB
Referenced Files
None
Subscribers
None

D56.1772596090.diff

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

Mime Type
text/plain
Expires
Wed, Mar 4, 04:48 (5 m, 25 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1710770
Default Alt Text
D56.1772596090.diff (38 KB)

Event Timeline