diff --git a/AndroidManifest.xml b/AndroidManifest.xml --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -85,6 +85,17 @@ android:name="android.support.PARENT_ACTIVITY" android:value=".ActivityMain"/> + + + + + + + + \ No newline at end of file diff --git a/res/drawable/map.xml b/res/drawable/map.xml new file mode 100644 --- /dev/null +++ b/res/drawable/map.xml @@ -0,0 +1,8 @@ + + + + diff --git a/res/layout/activity_map.xml b/res/layout/activity_map.xml new file mode 100644 --- /dev/null +++ b/res/layout/activity_map.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/res/layout/map_popup.xml b/res/layout/map_popup.xml new file mode 100644 --- /dev/null +++ b/res/layout/map_popup.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/res/menu/main.xml b/res/menu/main.xml --- a/res/menu/main.xml +++ b/res/menu/main.xml @@ -2,7 +2,12 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" tools:context="it.reyboz.bustorino.ActivityMain"> - + Fermata aggiunta ai preferiti Impossibile aggiungere ai preferiti (memoria piena o database corrotto?)! Preferiti + Mappa Nessun preferito? Arghh! Schiaccia sulla stella di una fermata per aggiungere a questa lista! Rimuovi Rinomina @@ -55,8 +56,9 @@

Quest\'app ottiene i passaggi dei bus in tempo reale filtrando i dati forniti pubblicamente sul sito www.gtt.to.it o www.5t.torino.it "per uso personale".

Ingredienti:
- - Fabio Mazza attuale rockstar developer.
- - Ludovico Pavesi ex rockstar developer.
+ - Fabio Mazza attuale rockstar developer anziano.
+ - Andrea Ugo attuale rockstar developer in formazione.
+ - Ludovico Pavesi ex rockstar developer anziano.
- Valerio Bozzolan attuale manutentore.
- Marco Gagino apprezzato ex collaboratore, ideatore icona e grafica.
- JSoup libreria per "web scaping".
diff --git a/res/values/strings.xml b/res/values/strings.xml --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -35,6 +35,7 @@ Bus stop removed from your favorites Favorites Favorites + Map No favorites? Arghh! Press on a bus stop star to populate this list! Delete Rename @@ -65,10 +66,11 @@

This app will show you bus timetables gathering data from www.gtt.to.it or www.5t.torino.it "for personal use".

Who worked on BusTO:
- - Fabio Mazza current rockstar developer.
- - Ludovico Pavesi previous rockstar developer.
- - Valerio Bozzolan maintainer.
- - Marco Gagino ex contributor and icon creator.
+ - Fabio Mazza current senior rockstar developer.
+ - Andrea Ugo current junior rockstar developer.
+ - Ludovico Pavesi previous senior rockstar developer.
+ - Valerio Bozzolan maintainer and infrastructure sponsor.
+ - Marco Gagino contributor and icon creator.
- JSoup web scraper library.
- makovkastar floating buttons.
- Google Material Design icons.
diff --git a/res/values/theme.xml b/res/values/theme.xml --- a/res/values/theme.xml +++ b/res/values/theme.xml @@ -13,6 +13,12 @@ @color/blue_700 + + \ No newline at end of file diff --git a/src/it/reyboz/bustorino/ActivityFavorites.java b/src/it/reyboz/bustorino/ActivityFavorites.java --- a/src/it/reyboz/bustorino/ActivityFavorites.java +++ b/src/it/reyboz/bustorino/ActivityFavorites.java @@ -46,6 +46,8 @@ import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; +import org.osmdroid.util.GeoPoint; + import java.util.List; public class ActivityFavorites extends AppCompatActivity implements LoaderManager.LoaderCallbacks { @@ -130,13 +132,17 @@ Toast.makeText(getApplicationContext(),R.string.cannot_show_on_map_no_position,Toast.LENGTH_SHORT).show(); return true; } - Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(theGeoUrl)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - if(intent.resolveActivity(getPackageManager())!=null) - startActivity(intent); - else { - Toast.makeText(getApplicationContext(),R.string.cannot_show_on_map_no_activity,Toast.LENGTH_SHORT).show(); - } + + // start ActivityMap with these extras in intent + Intent intent = new Intent(ActivityFavorites.this, ActivityMap.class); + Bundle b = new Bundle(); + b.putDouble("lat", busStop.getLatitude()); + b.putDouble("lon", busStop.getLongitude()); + b.putString("name", busStop.getStopDefaultName()); + b.putString("ID", busStop.ID); + intent.putExtras(b); + + startActivity(intent); return true; default: return super.onContextItemSelected(item); diff --git a/src/it/reyboz/bustorino/ActivityMain.java b/src/it/reyboz/bustorino/ActivityMain.java --- a/src/it/reyboz/bustorino/ActivityMain.java +++ b/src/it/reyboz/bustorino/ActivityMain.java @@ -385,6 +385,9 @@ case R.id.action_favorites: startActivity(new Intent(ActivityMain.this, ActivityFavorites.class)); return true; + case R.id.action_map: + startActivity(new Intent(ActivityMain.this, ActivityMap.class)); + return true; case R.id.action_about: startActivity(new Intent(ActivityMain.this, ActivityAbout.class)); return true; diff --git a/src/it/reyboz/bustorino/ActivityMap.java b/src/it/reyboz/bustorino/ActivityMap.java new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/ActivityMap.java @@ -0,0 +1,212 @@ +package it.reyboz.bustorino; + +import android.content.Context; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.support.annotation.RequiresApi; +import android.support.v7.app.AppCompatActivity; +import android.support.v7.preference.PreferenceManager; + +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.Marker; +import org.osmdroid.views.overlay.infowindow.InfoWindow; + +import it.reyboz.bustorino.backend.Stop; +import it.reyboz.bustorino.map.CustomInfoWindow; +import it.reyboz.bustorino.middleware.StopsDB; + +public class ActivityMap extends AppCompatActivity { + + private static MapView map = null; + public Context ctx; + + @RequiresApi(api = Build.VERSION_CODES.HONEYCOMB) + @Override public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + //handle permissions first, before map is created. not depicted here + + //load/initialize the osmdroid configuration, this can be done + ctx = getApplicationContext(); + Configuration.getInstance().load(ctx, PreferenceManager.getDefaultSharedPreferences(ctx)); + //setting this before the layout is inflated is a good idea + //it 'should' ensure that the map has a writable location for the map cache, even without permissions + //if no tiles are displayed, you can try overriding the cache path using Configuration.getInstance().setCachePath + //see also StorageUtils + //note, the load method also sets the HTTP User Agent to your application's package name, abusing osm's tile servers will get you banned based on this string + + //inflate and create the map + setContentView(R.layout.activity_map); + + map = (MapView) findViewById(R.id.map); + map.setTileSource(TileSourceFactory.MAPNIK); + + // add ability to zoom with 2 fingers + map.setMultiTouchControls(true); + + // take the parameters if it's called from other Activities + Bundle b = getIntent().getExtras(); + GeoPoint marker = null; + String name = null; + String ID = null; + if(b != null) { + double lat = b.getDouble("lat"); + double lon = b.getDouble("lon"); + marker = new GeoPoint(lat, lon); + name = b.getString("name"); + ID = b.getString("ID"); + } + startMap(marker, name, ID); + + // on drag and zoom reload the markers + map.addMapListener(new DelayedMapListener(new MapListener() { + + @Override + public boolean onScroll(ScrollEvent paramScrollEvent) { + loadMarkers(); + return true; + } + + @Override + public boolean onZoom(ZoomEvent event) { + loadMarkers(); + return true; + } + + })); + } + + public void startMap(GeoPoint marker, String name, String ID) { + + // 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; + if (marker != null) { + startPoint = marker; + mapController.setZoom(20.0); + } else { + startPoint = new GeoPoint(45.0708, 7.6858); + mapController.setZoom(18.0); + } + // set the minimum zoom level + map.setMinZoomLevel(15.5); + mapController.setCenter(startPoint); + + loadMarkers(); + if (marker != null) { + // make a marker with the info window open for the searched marker + makeMarker(startPoint, name , ID, true); + } + + } + + public void 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); + marker.setInfoWindow(popup); + + // make the marker clickable + marker.setOnMarkerClickListener((thisMarker, mapView) -> { + if (thisMarker.isInfoWindowOpen()) { + // on second click + + // create an intent with these extras + Intent intent = new Intent(ActivityMap.this, 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 + startActivity(intent); + } 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); + // display the marker + map.getOverlays().add(marker); + // add to it an icon + marker.setIcon(getResources().getDrawable(R.drawable.bus_marker)); + // add to it a title + marker.setTitle(stopName); + + // show popup info window of the searched marker + if (isStartMarker) { + marker.showInfoWindow(); + } + + } + + public void loadMarkers() { + + // get rid of the previous markers + map.getOverlays().clear(); + + // 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(); + + // get the stops located in those coordinates + StopsDB stopsDB = new StopsDB(ctx); + stopsDB.openIfNeeded(); + Stop[] stops = stopsDB.queryAllInsideMapView(latFrom, latTo, lngFrom, lngTo); + stopsDB.closeIfNeeded(); + + // add new markers of those stops + for (Stop stop : stops) { + GeoPoint marker = new GeoPoint(stop.getLatitude(), stop.getLongitude()); + makeMarker(marker, stop.getStopDefaultName(), stop.ID, false); + } + + } + + public void onResume(){ + super.onResume(); + //this will refresh the osmdroid configuration on resuming. + //if you make changes to the configuration, use + //SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + //Configuration.getInstance().load(this, PreferenceManager.getDefaultSharedPreferences(this)); + map.onResume(); //needed for compass, my location overlays, v6.0.0 and up + } + + public void onPause(){ + super.onPause(); + //this will refresh the osmdroid configuration on resuming. + //if you make changes to the configuration, use + //SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); + //Configuration.getInstance().save(this, prefs); + map.onPause(); //needed for compass, my location overlays, v6.0.0 and up + } +} \ No newline at end of file diff --git a/src/it/reyboz/bustorino/map/CustomInfoWindow.java b/src/it/reyboz/bustorino/map/CustomInfoWindow.java new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/map/CustomInfoWindow.java @@ -0,0 +1,42 @@ +package it.reyboz.bustorino.map; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.os.Bundle; +import android.view.MotionEvent; +import android.view.View; + +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 { + + @SuppressLint("ClickableViewAccessibility") + public CustomInfoWindow(MapView mapView, String ID, String stopName) { + // get the personalized layout + super(R.layout.map_popup, mapView); + + // 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); + } + return true; + }); + } + +}