diff --git a/build.gradle b/build.gradle --- a/build.gradle +++ b/build.gradle @@ -51,7 +51,7 @@ defaultConfig { applicationId "it.reyboz.bustorino" - minSdkVersion 15 + minSdkVersion 16 targetSdkVersion 29 versionCode 35 versionName "1.15.4" @@ -103,12 +103,12 @@ implementation "androidx.work:work-runtime:$work_version" implementation "com.google.android.material:material:1.4.0" - implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.constraintlayout:constraintlayout:2.1.1' implementation 'org.jsoup:jsoup:1.13.1' implementation 'com.readystatesoftware.sqliteasset:sqliteassethelper:2.0.1' - implementation 'com.android.volley:volley:1.2.0' + implementation 'com.android.volley:volley:1.2.1' implementation 'org.osmdroid:osmdroid-android:6.1.10' // ACRA diff --git a/res/values-it/strings.xml b/res/values-it/strings.xml --- a/res/values-it/strings.xml +++ b/res/values-it/strings.xml @@ -131,6 +131,8 @@ App GTT Sito GTT Sito 5T Torino + App Muoversi a Torino + Cambiamento sorgente orari… Premi a lungo per cambiare la sorgente degli orari diff --git a/res/values/strings.xml b/res/values/strings.xml --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -144,6 +144,7 @@ GTT App GTT Website 5T Torino website + Muoversi a Torino app Changing arrival times source… Long press to change the source of arrivals @@ -173,5 +174,4 @@ Map Search by stop - diff --git a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java --- a/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java +++ b/src/it/reyboz/bustorino/backend/ArrivalsFetcher.java @@ -22,20 +22,10 @@ import java.util.concurrent.atomic.AtomicReference; +/** + * Fetcher interface to describe ways to get information on arrival times + */ public interface ArrivalsFetcher extends Fetcher { -// /** -// * Reads arrival times from a (hopefully) real-time source, e.g. the GTT website. -// * Don't call this in UI thread! -// * -// * @param stopID stop ID, in normalized form. -// * @param routeID route ID, in normalized form. -// * @param res result code (will be set by this method) -// * @return arrival times -// * @see it.reyboz.bustorino.backend.Fetcher.result -// * @see FiveTNormalizer -// */ -// Palina ReadArrivalTimesRoute(String stopID, String routeID, AtomicReference res); - /** * Reads arrival times from a (hopefully) real-time source, e.g. the GTT website. * Don't call this in UI thread! diff --git a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java --- a/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java +++ b/src/it/reyboz/bustorino/backend/FiveTAPIFetcher.java @@ -18,6 +18,7 @@ package it.reyboz.bustorino.backend; import androidx.annotation.Nullable; + import android.util.Log; import it.reyboz.bustorino.data.GTTInfoInject; import org.json.JSONArray; diff --git a/src/it/reyboz/bustorino/backend/Palina.java b/src/it/reyboz/bustorino/backend/Palina.java --- a/src/it/reyboz/bustorino/backend/Palina.java +++ b/src/it/reyboz/bustorino/backend/Palina.java @@ -21,6 +21,7 @@ import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.util.ArrayList; import java.util.Calendar; @@ -47,6 +48,15 @@ s.getRoutesThatStopHere(),s.getLatitude(),s.getLongitude()); } + public Palina(@NonNull String ID, @Nullable String name, @Nullable String userName, + @Nullable String location, + @Nullable Double lat, @Nullable Double lon) { + super(ID, name, userName, location, null, null, lat, lon); + } + + public Palina(@Nullable String name, @NonNull String ID, @Nullable String location, @Nullable Route.Type type, @Nullable List routesThatStopHere) { + super(name, ID, location, type, routesThatStopHere); + } /** * Adds a timetable entry to a route. @@ -373,5 +383,16 @@ if (found) mergeDuplicateRoutes(startidx); else mergeDuplicateRoutes(startidx+1); } + + public int getTotalNumberOfPassages(){ + + int tot = 0; + if(routes==null) + return tot; + for(Route r: routes){ + tot += r.numPassaggi(); + } + return tot; + } //private void mergeRoute } \ No newline at end of file diff --git a/src/it/reyboz/bustorino/backend/Passaggio.java b/src/it/reyboz/bustorino/backend/Passaggio.java --- a/src/it/reyboz/bustorino/backend/Passaggio.java +++ b/src/it/reyboz/bustorino/backend/Passaggio.java @@ -19,8 +19,12 @@ package it.reyboz.bustorino.backend; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + import android.util.Log; +import java.util.Locale; + public final class Passaggio implements Comparable { private static final int UNKNOWN_TIME = -3; @@ -28,6 +32,7 @@ private final String passaggioGTT; public final int hh,mm; + private @Nullable Integer realtimeDifference; public final boolean isInRealTime; public final Source source; @@ -88,6 +93,7 @@ this.hh = hour; this.mm = min; this.isInRealTime = realtime; + } } @@ -95,6 +101,7 @@ this.hh = hour; this.mm = minutes; this.isInRealTime = realtime; + if (!realtime) realtimeDifference = 0; this.source = sorgente; //Build the passaggio string StringBuilder sb = new StringBuilder(); @@ -113,6 +120,23 @@ else return time; } } + public Passaggio(int numSeconds, boolean realtime, int timeDiff, Source source){ + int minutes = numSeconds / 60; + int hours = minutes / 60; + this.hh = hours; + this.mm = minutes - hours*60; + this.realtimeDifference = timeDiff/60; + this.isInRealTime = realtime; + this.source = source; + this.passaggioGTT = makePassaggioGTT(this.hh, this.mm, this.isInRealTime); + } + + private static String makePassaggioGTT(int hour, int minutes, boolean realtime){ + StringBuilder sb = new StringBuilder(); + sb.append(String.format(Locale.ITALIAN,"%02d", hour)).append(":").append(String.format(Locale.ITALIAN,"%02d", minutes)); + if(realtime) sb.append("*"); + return sb.toString(); + } @Override public int compareTo(@NonNull Passaggio other) { @@ -143,6 +167,8 @@ return diff; } } + + // // @Override // public String toString() { @@ -154,6 +180,6 @@ // } // } public enum Source{ - FiveTAPI,GTTJSON,FiveTScraper, UNDETERMINED + FiveTAPI,GTTJSON,FiveTScraper,MatoAPI, UNDETERMINED } } \ No newline at end of file diff --git a/src/it/reyboz/bustorino/backend/Route.java b/src/it/reyboz/bustorino/backend/Route.java --- a/src/it/reyboz/bustorino/backend/Route.java +++ b/src/it/reyboz/bustorino/backend/Route.java @@ -45,6 +45,7 @@ public int[] serviceDays ={}; //0=>feriale, 1=>festivo -2=>unknown public FestiveInfo festivo = FestiveInfo.UNKNOWN; + private @Nullable String gtfsId; public enum Type { // "long distance" sono gli extraurbani. @@ -242,6 +243,12 @@ return sb.toString(); } + public int numPassaggi(){ + if (passaggi==null) + return 0; + return passaggi.size(); + } + @Override public int compareTo(@NonNull Route other) { @@ -267,6 +274,12 @@ if (res != 0) { return res; } + // compare gtfsID + if (this.gtfsId != null && other.gtfsId!=null){ + res = this.gtfsId.compareTo(other.gtfsId); + if (res!=0) return 0; + } + } // try comparing their destination @@ -293,6 +306,15 @@ return 0; } + @Nullable + public String getGtfsId() { + return gtfsId; + } + + public void setGtfsId(@Nullable String gtfsId) { + this.gtfsId = gtfsId; + } + public boolean isBranchIdValid(){ return branchid!=BRANCHID_MISSING; } @@ -306,11 +328,14 @@ if(description!=null && r.description!=null) if(!description.trim().equals(r.description.trim())) return false; + if(destinazione!=null && r.destinazione!=null){ if(!this.destinazione.trim().equals(r.destinazione.trim())) // they are not the same return false; } + if(gtfsId!=null && r.gtfsId!=null && !(gtfsId.trim().equals(r.gtfsId.trim()))) + return false; //check stops list if(this.stopsList!=null && r.stopsList!=null){ int sizeDiff = this.stopsList.size()-r.stopsList.size(); diff --git a/src/it/reyboz/bustorino/backend/Stop.java b/src/it/reyboz/bustorino/backend/Stop.java --- a/src/it/reyboz/bustorino/backend/Stop.java +++ b/src/it/reyboz/bustorino/backend/Stop.java @@ -46,6 +46,9 @@ private @Nullable String routesThatStopHereString = null; private @Nullable String absurdGTTPlaceName = null; + // + public @Nullable String gtfsID = null; + /** * Hey, look, method overloading! */ diff --git a/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java b/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/backend/mato/MapiArrivalRequest.java @@ -0,0 +1,111 @@ +package it.reyboz.bustorino.backend.mato; + +import android.util.Log; + +import androidx.annotation.Nullable; + +import com.android.volley.AuthFailureError; +import com.android.volley.NetworkResponse; +import com.android.volley.Response; +import com.android.volley.VolleyError; +import com.android.volley.toolbox.HttpHeaderParser; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.nio.charset.StandardCharsets; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import it.reyboz.bustorino.backend.Palina; + +public class MapiArrivalRequest extends MapiVolleyRequest { + + private final String stopName; + private final Date startingTime; + private final int timeRange, numberOfDepartures; + + public MapiArrivalRequest(String stopName, Date startingTime, int timeRange, + int numberOfDepartures, + Response.Listener listener, + @Nullable Response.ErrorListener errorListener) { + super(MatoAPIFetcher.QueryType.ARRIVALS, listener, errorListener); + this.stopName = stopName; + this.startingTime = startingTime; + this.timeRange = timeRange; + this.numberOfDepartures = numberOfDepartures; + } + + @Nullable + @Override + public byte[] getBody() throws AuthFailureError { + JSONObject variables = new JSONObject(); + JSONObject data = new JSONObject(); + try { + data.put("operationName","AllStopsDirect"); + variables.put("name", stopName); + variables.put("startTime", (long) startingTime.getTime()/1000); + variables.put("timeRange", timeRange); + variables.put("numberOfDepartures", numberOfDepartures); + + + data.put("variables", variables); + data.put("query", MatoAPIFetcher.QUERY_ARRIVALS); + } catch (JSONException e) { + e.printStackTrace(); + throw new AuthFailureError("Error with JSON enconding",e); + } + Map paramsMap = new HashMap<>(); + //paramsMap.put("data", data.toString()); + String requestBody = data.toString(); + Log.d("MapiArrivalBusTO", "Request params: "+ requestBody); + return requestBody.getBytes(); + } + + + @Override + protected Response parseNetworkResponse(NetworkResponse response) { + if(response.statusCode != 200) + return Response.error(new VolleyError("Response Error Code "+response.statusCode)); + final String stringResponse = new String(response.data); + Palina p = null; + + try { + JSONObject data = new JSONObject(stringResponse).getJSONObject("data"); + + JSONArray allStopsFound = data.getJSONArray("stops"); + + boolean haveManyResults = allStopsFound.length() > 1; + for (int i=0; i getParams() throws AuthFailureError { + return new HashMap<>(); + } +} diff --git a/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java b/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/backend/mato/MapiVolleyRequest.java @@ -0,0 +1,40 @@ +package it.reyboz.bustorino.backend.mato; + +import androidx.annotation.Nullable; + +import com.android.volley.AuthFailureError; +import com.android.volley.Request; +import com.android.volley.Response; + +import java.util.Map; + +public abstract class MapiVolleyRequest extends Request { + private static final String API_URL="https://mapi.5t.torino.it/routing/v1/routers/mat/index/graphql"; + + protected final Response.Listener listener; + private final MatoAPIFetcher.QueryType type; + public MapiVolleyRequest( + MatoAPIFetcher.QueryType type, + Response.Listener listener, + @Nullable Response.ErrorListener errorListener) { + super(Method.POST, API_URL, errorListener); + this.type = type; + this.listener = listener; + + } + + + @Nullable + @Override + abstract protected Map getParams() throws AuthFailureError; + + @Override + protected void deliverResponse(T response) { + listener.onResponse(response); + } + + @Override + public Map getHeaders() throws AuthFailureError { + return MatoAPIFetcher.Companion.getREQ_PARAMETERS(); + } +} diff --git a/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt b/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt new file mode 100644 --- /dev/null +++ b/src/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt @@ -0,0 +1,218 @@ +package it.reyboz.bustorino.backend.mato + +import android.content.Context +import android.util.Log +import com.android.volley.toolbox.RequestFuture +import it.reyboz.bustorino.backend.* +import org.json.JSONObject +import java.util.* +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference +import java.util.concurrent.TimeoutException + +import java.util.concurrent.ExecutionException + + + + +open class MatoAPIFetcher : ArrivalsFetcher { + var appContext: Context? = null + set(value) { + field = value!!.applicationContext + } + + override fun ReadArrivalTimesAll(stopID: String?, res: AtomicReference?): Palina { + stopID!! + val future = RequestFuture.newFuture() + val now = Calendar.getInstance().time; + var numMinutes = 20; + var palina = Palina(stopID) + var numPassaggi = 0 + var trials = 0 + while (numPassaggi < 2 && trials < 5) { + + numMinutes += 10 + val request = MapiArrivalRequest(stopID, now, numMinutes * 60, 5, future, future) + if (appContext == null || res == null) { + Log.e("BusTO:MatoAPIFetcher", "ERROR: Given null context or null result ref") + return Palina(stopID) + } + val requestQueue = NetworkVolleyManager.getInstance(appContext).requestQueue + request.setTag(VOLLEY_TAG) + requestQueue.add(request) + + + try { + palina = future.get(5, TimeUnit.SECONDS) + if (palina.totalNumberOfPassages > 0) { + res.set(Fetcher.Result.OK) + } else res.set(Fetcher.Result.EMPTY_RESULT_SET) + numPassaggi = palina.totalNumberOfPassages + } catch (e: InterruptedException) { + e.printStackTrace() + res.set(Fetcher.Result.PARSER_ERROR) + } catch (e: ExecutionException) { + e.printStackTrace() + res.set(Fetcher.Result.SERVER_ERROR) + } catch (e: TimeoutException) { + res.set(Fetcher.Result.CONNECTION_ERROR) + e.printStackTrace() + } + trials++ + + } + + return palina + } + + override fun getSourceForFetcher(): Passaggio.Source { + return Passaggio.Source.MatoAPI + } + + companion object{ + const val VOLLEY_TAG = "MatoAPIFetcher" + + const val DEBUG_TAG = "BusTO:MatoAPIFetcher" + + val REQ_PARAMETERS = mapOf( + "Content-Type" to "application/json; charset=utf-8", + "DNT" to "1", + "Host" to "mapi.5t.torino.it") + + fun makeRequest(type: QueryType?, variables: JSONObject) : String{ + type.let { + val requestData = JSONObject() + when (it){ + QueryType.ARRIVALS ->{ + requestData.put("operationName","AllStopsDirect") + requestData.put("variables", variables) + requestData.put("query", QUERY_ARRIVALS) + } + else -> { + //TODO all other cases + } + } + + + //todo make the request... + //https://pablobaxter.github.io/volley-docs/com/android/volley/toolbox/RequestFuture.html + //https://stackoverflow.com/questions/16904741/can-i-do-a-synchronous-request-with-volley + + } + return "" + } + fun parseStopJSON(jsonStop: JSONObject): Palina{ + val latitude = jsonStop.getDouble("lat") + val longitude = jsonStop.getDouble("lon") + val palina = Palina( + jsonStop.getString("code"), + jsonStop.getString("name"), + null, null, latitude, longitude + ) + palina.gtfsID = jsonStop.getString("gtfsId") + + val routesStopTimes = jsonStop.getJSONArray("stoptimesForPatterns") + + for (i in 0 until routesStopTimes.length()){ + val patternJSON = routesStopTimes.getJSONObject(i) + val mRoute = parseRouteStoptimesJSON(patternJSON) + //if (mRoute.passaggiToString !=null) + // Log.d(DEBUG_TAG, "Found route with passaggi "+mRoute.passaggiToString) + palina.addRoute(mRoute) + } + + + return palina + } + fun parseRouteStoptimesJSON(jsonPatternWithStops: JSONObject): Route{ + val patternJSON = jsonPatternWithStops.getJSONObject("pattern") + val routeJSON = patternJSON.getJSONObject("route"); + + val passaggiJSON = jsonPatternWithStops.getJSONArray("stoptimes") + val gtfsId = routeJSON.getString("gtfsId") + val passages = mutableListOf() + for( i in 0 until passaggiJSON.length()){ + val stoptime = passaggiJSON.getJSONObject(i) + val scheduledTime = stoptime.getInt("scheduledArrival") + val realtimeTime = stoptime.getInt("realtimeArrival") + val realtime = stoptime.getBoolean("realtime") + passages.add( + Passaggio(realtimeTime,realtime, realtimeTime-scheduledTime, + Passaggio.Source.MatoAPI) + ) + } + var routeType = Route.Type.UNKNOWN + if (gtfsId[gtfsId.length-1] == 'E') + routeType = Route.Type.LONG_DISTANCE_BUS + else when( routeJSON.getString("mode").trim()){ + "BUS" -> routeType = Route.Type.BUS + "TRAM" -> routeType = Route.Type.TRAM + } + val route = Route( + routeJSON.getString("shortName"), + patternJSON.getString("headsign"), + routeType, + passages, + ) + return route + } + + const val QUERY_ARRIVALS="""query AllStopsDirect( + ${'$'}name: String + ${'$'}startTime: Long + ${'$'}timeRange: Int + ${'$'}numberOfDepartures: Int + ) { + stops(name: ${'$'}name) { + __typename + lat + lon + gtfsId + code + name + desc + wheelchairBoarding + routes { + __typename + gtfsId + } + stoptimesForPatterns( + startTime: ${'$'}startTime + timeRange: ${'$'}timeRange + numberOfDepartures: ${'$'}numberOfDepartures + ) { + __typename + pattern { + __typename + headsign + directionId + route { + __typename + gtfsId + shortName + mode + } + } + stoptimes { + __typename + scheduledArrival + realtimeArrival + realtime + realtimeState + } + } + } + } + """ + } + + data class Query( + val queryName: String, + val queryToDo:String, + ) + + enum class QueryType { + ARRIVALS, + } + +} \ No newline at end of file diff --git a/src/it/reyboz/bustorino/backend/networkTools.java b/src/it/reyboz/bustorino/backend/networkTools.java --- a/src/it/reyboz/bustorino/backend/networkTools.java +++ b/src/it/reyboz/bustorino/backend/networkTools.java @@ -247,6 +247,11 @@ } + /** + * Parses string into int, return 0 if it fails + * @param str the string to parse + * @return the value as int, 0 if it fails + */ static int failsafeParseInt(String str) { try { return Integer.parseInt(str); diff --git a/src/it/reyboz/bustorino/backend/utils.java b/src/it/reyboz/bustorino/backend/utils.java --- a/src/it/reyboz/bustorino/backend/utils.java +++ b/src/it/reyboz/bustorino/backend/utils.java @@ -15,6 +15,8 @@ import java.util.Arrays; import java.util.List; +import it.reyboz.bustorino.backend.mato.MatoAPIFetcher; + public abstract class utils { private static final double EarthRadius = 6371e3; public static Double measuredistanceBetween(double lat1,double long1,double lat2,double long2){ @@ -132,6 +134,10 @@ } } + public static ArrivalsFetcher[] getDefaultArrivalsFetchers(){ + return new ArrivalsFetcher[]{ new MatoAPIFetcher(), + new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()}; + } /** * Print the first i lines of the the trace of an exception * https://stackoverflow.com/questions/21706722/fetch-only-first-n-lines-of-a-stack-trace diff --git a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java --- a/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java +++ b/src/it/reyboz/bustorino/fragments/ArrivalsFragment.java @@ -56,6 +56,7 @@ import it.reyboz.bustorino.backend.Passaggio; import it.reyboz.bustorino.backend.Route; import it.reyboz.bustorino.backend.Stop; +import it.reyboz.bustorino.backend.utils; import it.reyboz.bustorino.data.AppDataProvider; import it.reyboz.bustorino.data.NextGenDB; import it.reyboz.bustorino.data.UserDB; @@ -69,7 +70,6 @@ private String DEBUG_TAG = DEBUG_TAG_ALL; private final static int loaderFavId = 2; private final static int loaderStopId = 1; - private final static ArrivalsFetcher[] defaultFetchers = new ArrivalsFetcher[]{new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()}; static final String STOP_TITLE = "messageExtra"; private @Nullable String stopID,stopName; @@ -85,7 +85,7 @@ protected ImageButton addToFavorites; protected TextView timesSourceTextView; - private List fetchers = new ArrayList<>(Arrays.asList(defaultFetchers)); + private List fetchers = new ArrayList<>(Arrays.asList(utils.getDefaultArrivalsFetchers())); private boolean reloadOnResume = true; @@ -324,14 +324,18 @@ case FiveTScraper: source_txt = getString(R.string.fivetscraper); break; + case MatoAPI: + source_txt = getString(R.string.source_mato); + break; case UNDETERMINED: //Don't show the view - timesSourceTextView.setVisibility(View.GONE); - return; + source_txt = ""; + break; default: throw new IllegalStateException("Unexpected value: " + source); } int count = 0; + if (source!= Passaggio.Source.UNDETERMINED) while (source != fetchers.get(0).getSourceForFetcher() && count < 100){ //we need to update the fetcher that is requested rotateFetchers(); 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 @@ -90,7 +90,7 @@ private static final int SEARCH_BY_ROUTE = 2; // TODO: implement this -- https://gitpull.it/T12 private int searchMode; //private ImageButton addToFavorites; - private final ArrivalsFetcher[] arrivalsFetchers = new ArrivalsFetcher[]{new FiveTAPIFetcher(), new GTTJSONFetcher(), new FiveTScraperFetcher()}; + private final ArrivalsFetcher[] arrivalsFetchers = utils.getDefaultArrivalsFetchers(); //// HIDDEN BUT IMPORTANT ELEMENTS //// FragmentManager fragMan; Handler mainHandler; @@ -334,6 +334,7 @@ @Override public void onAttach(@NonNull Context context) { super.onAttach(context); + Log.d(DEBUG_TAG, "OnAttach called, setupOnAttach: "+setupOnAttached); mainHandler = new Handler(); if (context instanceof CommonFragmentListener) { 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 @@ -17,6 +17,7 @@ */ package it.reyboz.bustorino.middleware; +import android.annotation.SuppressLint; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; @@ -32,6 +33,7 @@ import it.reyboz.bustorino.R; import it.reyboz.bustorino.backend.*; +import it.reyboz.bustorino.backend.mato.MatoAPIFetcher; import it.reyboz.bustorino.data.AppDataProvider; import it.reyboz.bustorino.data.NextGenDB; import it.reyboz.bustorino.fragments.FragmentHelper; @@ -59,7 +61,8 @@ WeakReference helperRef; private final ArrayList otherActivities = new ArrayList<>(); private final Fetcher[] theFetchers; - private Context context; + @SuppressLint("StaticFieldLeak") + private final Context context; private final boolean replaceFragment; @@ -107,6 +110,9 @@ switch (t){ case ARRIVALS: ArrivalsFetcher f = (ArrivalsFetcher) r.getAndMoveForward(); + if (f instanceof MatoAPIFetcher){ + ((MatoAPIFetcher)f).setAppContext(context); + } Log.d(TAG,"Using the ArrivalsFetcher: "+f.getClass()); Stop lastSearchedBusStop = fh.getLastSuccessfullySearchedBusStop(); @@ -128,6 +134,8 @@ Log.e(DEBUG_TAG, "The stop number is not a valid integer, expect failures"); } p= f.ReadArrivalTimesAll(stopID,res); + if (p.getTotalNumberOfPassages() == 0) + res.set(Fetcher.Result.EMPTY_RESULT_SET); publishProgress(res.get()); //if (res.get()!= Fetcher.Result.OK) Log.d(DEBUG_TAG, "Arrivals fetcher: "+f+"\n\tProgress: "+res.get());