diff --git a/res/layout/activity_experiments.xml b/res/layout/activity_experiments.xml
--- a/res/layout/activity_experiments.xml
+++ b/res/layout/activity_experiments.xml
@@ -1,5 +1,5 @@
-
-
\ No newline at end of file
+ android:layout_height="match_parent"
+ />
+
\ No newline at end of file
diff --git a/res/layout/fragment_test_realtime_gtfs.xml b/res/layout/fragment_test_realtime_gtfs.xml
new file mode 100644
--- /dev/null
+++ b/res/layout/fragment_test_realtime_gtfs.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/map_popup.xml b/res/layout/map_popup.xml
--- a/res/layout/map_popup.xml
+++ b/res/layout/map_popup.xml
@@ -3,26 +3,37 @@
android:orientation="vertical" android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/cardview_light_background"
- android:padding="8dp">
+ android:padding="9dp"
+>
+ android:gravity="center"
+ android:textColor="@color/blue_700"
+ android:textSize="16sp"
+ android:maxWidth="400sp"
+ />
Yes
No
Install Barcode Scanner?
- This application requires an app to scan the QR codes. Would you like to install Barcode Scanner now?
+ This application requires an app to scan the QR codes. Would you like
+ to install Barcode Scanner now?
+
Bus stop number
Bus stop name
@@ -208,7 +210,7 @@
Capitalize directions
- - Do not change arrivals directions
+ - Do not change arrivals directions
- Capitalize everything
- Capitalize only first letter
@@ -222,7 +224,7 @@
Touch to change it
Show arrivals touching on stop
Enable experiments
-
+
Long press the stop for options
@@ -232,5 +234,7 @@
- @string/nav_map_text
- @string/lines
+
+ Hello blank fragment
diff --git a/src/it/reyboz/bustorino/ActivityExperiments.java b/src/it/reyboz/bustorino/ActivityExperiments.java
--- a/src/it/reyboz/bustorino/ActivityExperiments.java
+++ b/src/it/reyboz/bustorino/ActivityExperiments.java
@@ -18,7 +18,9 @@
package it.reyboz.bustorino;
import android.os.Bundle;
+import androidx.appcompat.app.ActionBar;
import it.reyboz.bustorino.fragments.LinesDetailFragment;
+import it.reyboz.bustorino.fragments.TestRealtimeGtfsFragment;
import it.reyboz.bustorino.middleware.GeneralActivity;
public class ActivityExperiments extends GeneralActivity {
@@ -29,12 +31,23 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_experiments);
+
+ ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ actionBar.setIcon(R.drawable.ic_launcher);
+ }
if (savedInstanceState==null) {
getSupportFragmentManager().beginTransaction()
.setReorderingAllowed(true)
+ /*
.add(R.id.fragment_container_view, LinesDetailFragment.class,
+
LinesDetailFragment.Companion.makeArgs("gtt:56U"))
.commit();
+ */
+ .add(R.id.fragment_container_view, TestRealtimeGtfsFragment.class, null)
+ .commit();
}
}
}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/backend/gtfs/GtfsRealtimeRequest.kt b/src/it/reyboz/bustorino/backend/gtfs/GtfsRealtimeRequest.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/backend/gtfs/GtfsRealtimeRequest.kt
@@ -0,0 +1,43 @@
+package it.reyboz.bustorino.backend.gtfs
+
+import com.android.volley.NetworkResponse
+import com.android.volley.Request
+import com.android.volley.Response
+import com.android.volley.VolleyError
+import com.android.volley.toolbox.HttpHeaderParser
+import com.google.transit.realtime.GtfsRealtime
+
+class GtfsRealtimeRequest(url: String?,
+ errorListener: Response.ErrorListener?,
+ val listener: RequestListener) :
+ Request(Method.GET, url, errorListener) {
+ override fun parseNetworkResponse(response: NetworkResponse?): Response {
+ if (response == null){
+ return Response.error(VolleyError("Null response"))
+ }
+
+ if (response.statusCode != 200)
+ return Response.error(VolleyError("Error code is ${response.statusCode}"))
+
+ val gtfsreq = GtfsRealtime.FeedMessage.parseFrom(response.data)
+
+ return Response.success(gtfsreq, HttpHeaderParser.parseCacheHeaders(response))
+ }
+
+ override fun deliverResponse(response: GtfsRealtime.FeedMessage?) {
+ listener.onResponse(response)
+ }
+
+ companion object{
+ const val URL_POSITION = "http://percorsieorari.gtt.to.it/das_gtfsrt/vehicle_position.aspx"
+
+ const val URL_TRIP_UPDATES ="http://percorsieorari.gtt.to.it/das_gtfsrt/trip_update.aspx"
+ const val URL_ALERTS = "http://percorsieorari.gtt.to.it/das_gtfsrt/alerts.aspx"
+
+ public interface RequestListener{
+ fun onResponse(response: GtfsRealtime.FeedMessage?)
+ }
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/it/reyboz/bustorino/fragments/LinesDetailFragment.kt b/src/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
--- a/src/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
+++ b/src/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
@@ -16,6 +16,7 @@
import it.reyboz.bustorino.data.gtfs.MatoPatternWithStops
import it.reyboz.bustorino.data.gtfs.PatternStop
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
+import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.Polyline
@@ -33,13 +34,11 @@
private lateinit var gtfsStopsForCurrentPattern: List
private lateinit var map: MapView
- private lateinit var polyLine: Polyline
-
private lateinit var viewingPattern: MatoPatternWithStops
private lateinit var viewModel: LinesViewModel
-
+ private var polyline = Polyline();
companion object {
private const val LINEID_KEY="lineID"
@@ -51,6 +50,8 @@
b.putString(LINEID_KEY, lineID)
return b
}
+ private const val DEFAULT_CENTER_LAT = 45.0708
+ private const val DEFAULT_CENTER_LON = 7.6858
}
@@ -73,9 +74,13 @@
// add ability to zoom with 2 fingers
map.setMultiTouchControls(true)
- map.minZoomLevel = 13.0
-
+ map.minZoomLevel = 14.0
+ //map controller setup
+ val mapController = map.controller
+ mapController.setZoom(14.0)
+ mapController.setCenter(GeoPoint(DEFAULT_CENTER_LAT, DEFAULT_CENTER_LON))
+ map.invalidate()
viewModel.patternsWithStopsByRouteLiveData.observe(viewLifecycleOwner){
patterns -> savePatternsToShow(patterns)
@@ -91,11 +96,16 @@
val pattern = viewingPattern.pattern
val pointsList = PolylineParser.decodePolyline(pattern.patternGeometryPoly, pattern.patternGeometryLength)
- val polyLine=Polyline(map)
- polyLine.setPoints(pointsList)
+ //val polyLine=Polyline(map)
+ //polyLine.setPoints(pointsList)
+ if(map.overlayManager.contains(polyline)){
+ map.overlayManager.remove(polyline)
+ }
+ polyline = Polyline(map)
+ polyline.setPoints(pointsList)
- map.overlayManager.add(polyLine)
- map.controller.animateTo(pointsList[0])
+ map.overlayManager.add(polyline)
+ //map.controller.animateTo(pointsList[0])
}
viewModel.setRouteIDQuery(lineID)
diff --git a/src/it/reyboz/bustorino/fragments/MapFragment.java b/src/it/reyboz/bustorino/fragments/MapFragment.java
--- a/src/it/reyboz/bustorino/fragments/MapFragment.java
+++ b/src/it/reyboz/bustorino/fragments/MapFragment.java
@@ -80,6 +80,7 @@
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 BUNDLE_ROUTES_STOPPING = "routesStopping";
public static final String FRAGMENT_TAG="BusTOMapFragment";
@@ -111,6 +112,7 @@
@Override
public void onActionUp(@NonNull String stopID, @Nullable String stopName) {
if (listenerMain!= null){
+ Log.d(DEBUG_TAG, "Asked to show arrivals for stop ID: "+stopID);
listenerMain.requestArrivalsForStopID(stopID);
}
}
@@ -131,7 +133,11 @@
private final ActivityResultLauncher positionRequestLauncher =
registerForActivityResult(new ActivityResultContracts.RequestMultiplePermissions(), result -> {
- if(result.get(Manifest.permission.ACCESS_COARSE_LOCATION) && result.get(Manifest.permission.ACCESS_FINE_LOCATION)){
+ if (result == null){
+ Log.w(DEBUG_TAG, "Got asked permission but request is null, doing nothing?");
+ }
+ else if(Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_COARSE_LOCATION)) &&
+ Boolean.TRUE.equals(result.get(Manifest.permission.ACCESS_FINE_LOCATION))){
map.getOverlays().remove(mLocationOverlay);
startLocationOverlay(true, map);
@@ -155,20 +161,21 @@
public static MapFragment getInstance(){
return new MapFragment();
}
- public static MapFragment getInstance(double stopLatit, double stopLong, String stopName, String stopID){
+ public static MapFragment getInstance(@NonNull Stop stop){
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);
+ args.putDouble(BUNDLE_LATIT, stop.getLatitude());
+ args.putDouble(BUNDLE_LONGIT, stop.getLongitude());
+ args.putString(BUNDLE_NAME, stop.getStopDisplayName());
+ args.putString(BUNDLE_ID, stop.ID);
+ args.putString(BUNDLE_ROUTES_STOPPING, stop.routesThatStopHereToString());
fragment.setArguments(args);
return fragment;
}
- public static MapFragment getInstance(@NonNull Stop stop){
- return getInstance(stop.getLatitude(), stop.getLongitude(), stop.getStopDisplayName(), stop.ID);
- }
+ //public static MapFragment getInstance(@NonNull Stop stop){
+ // return getInstance(stop.getLatitude(), stop.getLongitude(), stop.getStopDisplayName(), stop.ID);
+ //}
@Nullable
@@ -265,9 +272,8 @@
@Override
public void onPause() {
super.onPause();
+ Log.w(DEBUG_TAG, "On pause called mapfrag");
saveMapState();
- //cancel asynctask
- Log.w(DEBUG_TAG, "On pause called");
if (stopFetcher!= null)
stopFetcher.cancel(true);
}
@@ -279,7 +285,6 @@
private void saveMapState(){
savedMapState = new Bundle();
saveMapState(savedMapState);
-
}
/**
@@ -287,13 +292,17 @@
* @param bundle the bundle in which to save the data
*/
private void saveMapState(Bundle bundle){
+ Log.d(DEBUG_TAG, "Saving state, location following: "+followingLocation);
+ bundle.putBoolean(FOLLOWING_LOCAT_KEY, followingLocation);
+ if (map == null){
+ //The map is null, it can happen?
+ Log.e(DEBUG_TAG, "Cannot save map center, map is null");
+ return;
+ }
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
@@ -380,12 +389,14 @@
GeoPoint marker = null;
String name = null;
String ID = null;
+ String routesStopping = "";
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);
+ routesStopping = incoming.getString(BUNDLE_ROUTES_STOPPING, "");
}
@@ -465,7 +476,8 @@
//requestStopsToShow();
if (marker != null) {
// make a marker with the info window open for the searched marker
- Marker stopMarker = makeMarker(marker, name , ID, true);
+ //TODO: make Stop Bundle-able
+ Marker stopMarker = makeMarker(marker, ID , name, routesStopping,true);
map.getController().animateTo(marker);
}
@@ -518,7 +530,7 @@
}
GeoPoint marker = new GeoPoint(stop.getLatitude(), stop.getLongitude());
- Marker stopMarker = makeMarker(marker, stop.getStopDefaultName(), stop.ID, false);
+ Marker stopMarker = makeMarker(marker, stop, false);
stopsFolderOverlay.add(stopMarker);
if (!map.getOverlays().contains(stopsFolderOverlay)) {
Log.w(DEBUG_TAG, "Map doesn't have folder overlay");
@@ -530,13 +542,21 @@
map.invalidate();
}
- public Marker makeMarker(GeoPoint geoPoint, String stopName, String ID, boolean isStartMarker) {
+ public Marker makeMarker(GeoPoint geoPoint, Stop stop, boolean isStartMarker){
+ return makeMarker(geoPoint,stop.ID,
+ stop.getStopDefaultName(),
+ stop.routesThatStopHereToString(), isStartMarker);
+ }
+
+ public Marker makeMarker(GeoPoint geoPoint, String stopID, String stopName,
+ String routesStopping, boolean isStartMarker) {
// add a marker
final Marker marker = new Marker(map);
// set custom info window as info window
- CustomInfoWindow popup = new CustomInfoWindow(map, ID, stopName, responder);
+ CustomInfoWindow popup = new CustomInfoWindow(map, stopID, stopName, routesStopping,
+ responder);
marker.setInfoWindow(popup);
// make the marker clickable
@@ -568,7 +588,7 @@
// add to it a title
marker.setTitle(stopName);
// set the description as the ID
- marker.setSnippet(ID);
+ marker.setSnippet(stopID);
// show popup info window of the searched marker
if (isStartMarker) {
diff --git a/src/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt b/src/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt
new file mode 100644
--- /dev/null
+++ b/src/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt
@@ -0,0 +1,90 @@
+package it.reyboz.bustorino.fragments
+
+import android.os.Bundle
+import androidx.fragment.app.Fragment
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.TextView
+import android.widget.Toast
+import com.android.volley.Response
+import com.google.transit.realtime.GtfsRealtime
+import it.reyboz.bustorino.R
+import it.reyboz.bustorino.backend.NetworkVolleyManager
+import it.reyboz.bustorino.backend.gtfs.GtfsRealtimeRequest
+
+// TODO: Rename parameter arguments, choose names that match
+// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
+private const val ARG_PARAM1 = "param1"
+private const val ARG_PARAM2 = "param2"
+
+/**
+ * A simple [Fragment] subclass.
+ * Use the [TestRealtimeGtfsFragment.newInstance] factory method to
+ * create an instance of this fragment.
+ */
+class TestRealtimeGtfsFragment : Fragment() {
+
+ private lateinit var buttonLaunch: Button
+ private lateinit var messageTextView: TextView
+
+ private val requestListener = object: GtfsRealtimeRequest.Companion.RequestListener{
+ override fun onResponse(response: GtfsRealtime.FeedMessage?) {
+ if (response == null) return
+
+ if (response.entityCount == 0) {
+ messageTextView.text = "No entities in the message"
+ return
+ }
+ messageTextView.text = "Entity message 0: ${response.getEntity(0)}"
+ }
+
+ }
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ arguments?.let {
+ }
+
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+
+ // Inflate the layout for this fragment
+ val rootView= inflater.inflate(R.layout.fragment_test_realtime_gtfs, container, false)
+
+ buttonLaunch = rootView.findViewById(R.id.btn_download_data)
+ messageTextView = rootView.findViewById(R.id.gtfsMessageTextView)
+
+ buttonLaunch.setOnClickListener {
+
+ context?.let {cont->
+ val req = GtfsRealtimeRequest(GtfsRealtimeRequest.URL_POSITION,
+ Response.ErrorListener { Toast.makeText(cont, "Error: ${it.message}",Toast.LENGTH_SHORT) },
+ requestListener
+ )
+ NetworkVolleyManager.getInstance(cont).addToRequestQueue(req)
+ }
+
+
+
+ }
+ return rootView
+ }
+
+ companion object {
+ /**
+ * Use this factory method to create a new instance of
+ * this fragment using the provided parameters.
+ *
+ * @return A new instance of fragment TestRealtimeGtfsFragment.
+ */
+ @JvmStatic
+ fun newInstance() =
+ TestRealtimeGtfsFragment().apply {
+ }
+ }
+}
\ No newline at end of file
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
@@ -36,13 +36,17 @@
public class CustomInfoWindow extends BasicInfoWindow {
//TODO: Make the action on the Click customizable
private final TouchResponder touchResponder;
- private final String stopID, name;
+ private final String stopID, name, routesStopping;
+ //final DisplayMetrics metrics;
@Override
public void onOpen(Object item) {
super.onOpen(item);
- TextView descr_textView = (TextView) mView.findViewById(R.id.bubble_description);
+ TextView descr_textView = mView.findViewById(R.id.bubble_description);
CharSequence text = descr_textView.getText();
+ TextView titleTV = mView.findViewById(R.id.bubble_title);
+ //Log.d("BusTO-MapInfoWindow", "Descrip: "+text+", title "+(titleTV==null? "null": titleTV.getText()));
+
if (text==null || !text.toString().isEmpty()){
descr_textView.setVisibility(View.VISIBLE);
} else
@@ -51,21 +55,30 @@
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mView.setElevation(3.2f);
}
+ TextView subDescriptTextView = mView.findViewById(R.id.bubble_subdescription);
+ if (routesStopping!=null && !routesStopping.isEmpty()){
+ subDescriptTextView.setText(routesStopping);
+ subDescriptTextView.setVisibility(View.VISIBLE);
+ }
+
}
@SuppressLint("ClickableViewAccessibility")
- public CustomInfoWindow(MapView mapView, String stopID, String name, TouchResponder responder) {
+ public CustomInfoWindow(MapView mapView, String stopID, String name, String routesStopping, TouchResponder responder) {
// get the personalized layout
super(R.layout.map_popup, mapView);
touchResponder =responder;
this.stopID = stopID;
this.name = name;
+ this.routesStopping = routesStopping;
+
+ //metrics = Resources.getSystem().getDisplayMetrics();
// make clickable
mView.setOnTouchListener((View v, MotionEvent e) -> {
if (e.getAction() == MotionEvent.ACTION_UP) {
// on click
- touchResponder.onActionUp(stopID, name);
+ touchResponder.onActionUp(this.stopID, this.name);
}
return true;
});