Page MenuHomeGitPull.it

D232.1779763974.diff
No OneTemporary

Authored By
Unknown
Size
14 KB
Referenced Files
None
Subscribers
None

D232.1779763974.diff

diff --git a/app/src/main/java/it/reyboz/bustorino/backend/ArrivalsFetcherContext.java b/app/src/main/java/it/reyboz/bustorino/backend/ArrivalsFetcherContext.java
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/backend/ArrivalsFetcherContext.java
@@ -0,0 +1,14 @@
+package it.reyboz.bustorino.backend;
+
+import android.content.Context;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+public abstract class ArrivalsFetcherContext implements ArrivalsFetcher{
+
+ protected @Nullable Context appContext;
+
+ public void setContext(@NonNull Context appContext) {
+ this.appContext = appContext.getApplicationContext();
+ }
+}
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/GTTJSONFetcher.java b/app/src/main/java/it/reyboz/bustorino/backend/GTTJSONFetcher.java
--- a/app/src/main/java/it/reyboz/bustorino/backend/GTTJSONFetcher.java
+++ b/app/src/main/java/it/reyboz/bustorino/backend/GTTJSONFetcher.java
@@ -1,6 +1,7 @@
/*
BusTO (backend components)
Copyright (C) 2016 Ludovico Pavesi
+ Copyright (C) 2026 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
@@ -22,6 +23,10 @@
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import com.android.volley.*;
+import com.android.volley.toolbox.HttpHeaderParser;
+import com.android.volley.toolbox.RequestFuture;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -29,21 +34,19 @@
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
-public class GTTJSONFetcher implements ArrivalsFetcher {
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+public class GTTJSONFetcher extends ArrivalsFetcherContext {
private final String DEBUG_TAG = "GTTJSONFetcher-BusTO";
@Override @NonNull
public Palina ReadArrivalTimesAll(String stopID, AtomicReference<Result> res) {
URL url;
Palina p = new Palina(stopID);
- String routename;
- String bacino;
- String content;
- JSONArray json;
- int howManyRoutes, howManyPassaggi, i, j, pos; // il misto inglese-italiano è un po' ridicolo ma tanto vale...
- JSONObject thisroute;
- JSONArray passaggi;
try {
url = new URL("https://www.gtt.to.it/cms/index.php?option=com_gtt&task=palina.getTransitiOld&palina=" + URLEncoder.encode(stopID, "utf-8") + "&bacino=U&realtime=true&get_param=value");
@@ -51,11 +54,9 @@
res.set(Result.PARSER_ERROR);
return p;
}
- HashMap<String, String> headers = new HashMap<>();
- //headers.put("Referer","https://www.gtt.to.it/cms/percorari/urbano?view=percorsi&bacino=U&linea=15&Regol=GE");
- headers.put("Host", "www.gtt.to.it");
- content = networkTools.queryURL(url, res, headers);
+
+ /*content = networkTools.queryURL(url, res, headers);
if(content == null) {
Log.w("GTTJSONFetcher", "NULL CONTENT");
return p;
@@ -71,66 +72,154 @@
return p;
}
- try {
- // returns [{"PassaggiRT":[],"Passaggi":[]}] for non existing stops!
- json.getJSONObject(0).getString("Linea"); // if we can get this, then there's something useful in the array.
- } catch(JSONException e) {
- Log.w(DEBUG_TAG, "No existing lines");
- res.set(Result.NOT_FOUND);
- return p;
- }
-
- howManyRoutes = json.length();
- if(howManyRoutes == 0) {
- res.set(Result.EMPTY_RESULT_SET);
+ */
+ if (appContext == null) {
+ Log.w(DEBUG_TAG, "appContext is null");
+ res.set(Result.PARSER_ERROR);
return p;
}
- try {
- for(i = 0; i < howManyRoutes; i++) {
- thisroute = json.getJSONObject(i);
- routename = thisroute.getString("Linea");
- try {
- bacino = thisroute.getString("Bacino");
- } catch (JSONException ignored) { // if "Bacino" gets removed...
- bacino = "U";
- }
- final Route r = new Route(routename, thisroute.getString("Direzione"),
- "",
- FiveTNormalizer.decodeType(routename, bacino));
-
- passaggi = thisroute.getJSONArray("PassaggiRT");
- howManyPassaggi = passaggi.length();
- for(j = 0; j < howManyPassaggi; j++) {
- String mPassaggio = passaggi.getString(j);
- if (mPassaggio.contains("__")){
- mPassaggio = mPassaggio.replace("_", "");
- }
- r.addPassaggio(mPassaggio.concat("*"), Passaggio.Source.GTTJSON);
- }
-
+ boolean retry = true;
+ RequestQueue queue = NetworkVolleyManager.getInstance(appContext).getRequestQueue();
+ //use the volley class, max 5 tries
+ RequestFuture<Palina> future;
+ Request<Palina> request;
+ Response.ErrorListener responder = error -> {
+ //Log.w(DEBUG_TAG, "onErrorResponse: " + volleyError.getMessage());
+ if(error instanceof VolleyFetcherError){
+ Log.w(DEBUG_TAG, "Actual error: " + ((VolleyFetcherError) error).getReason());
+ }
+ };
+
+ for (int i = 0; i < 2; i++) {
+ future = RequestFuture.newFuture();
+ request = new GTTRequest(stopID, url.toString(), responder, future, res);
+
+ queue.add(request);
+
+ try {
+ p = future.get(10, SECONDS);
+ retry = false;
+ } catch (TimeoutException e) {
+ Log.d(DEBUG_TAG, "Request timed out: " + res.get());
+ retry = false;
+ res.set(Result.CONNECTION_ERROR);
+ } catch (InterruptedException | ExecutionException e) {
+ Log.w(DEBUG_TAG, "Error: " + e + " status: " + res.get());
+ res.set(Result.PARSER_ERROR);
+ }
- passaggi = thisroute.getJSONArray("PassaggiPR"); // now the non-real-time ones
- howManyPassaggi = passaggi.length();
- for(j = 0; j < howManyPassaggi; j++) {
- r.addPassaggio(passaggi.getString(j), Passaggio.Source.GTTJSON);
- }
- p.addRoute(r);
+ if(!retry){
+ break;
}
- } catch (JSONException e) {
- res.set(Result.PARSER_ERROR);
- e.printStackTrace();
- return p;
}
- p.sortRoutes();
- res.set(Result.OK);
return p;
}
+
@Override
public Passaggio.Source getSourceForFetcher() {
return Passaggio.Source.GTTJSON;
}
+
+ private final class GTTRequest extends Request<Palina> {
+ private final String stopID;
+ private final AtomicReference<Result> res;
+ private final Response.Listener<Palina> responder;
+
+ public GTTRequest(String stopID, String URL,
+ @Nullable Response.ErrorListener errorListener,
+ Response.Listener<Palina> resp,
+ AtomicReference<Result> resu) {
+ super(Method.GET, URL, errorListener);
+ this.stopID = stopID;
+ this.res = resu;
+ responder = resp;
+ }
+ @Override
+ protected Response<Palina> parseNetworkResponse(NetworkResponse networkResponse) {
+ if (networkResponse == null) {
+ return Response.error(new VolleyFetcherError(Result.PARSER_ERROR));
+ }
+
+ String data = new String(networkResponse.data);
+ JSONArray json;
+ try {
+ json = new JSONArray(data);
+ // returns [{"PassaggiRT":[],"Passaggi":[]}] for non existing stops!
+ json.getJSONObject(0).getString("Linea"); // if we can get this, then there's something useful in the array.
+ } catch(JSONException e) {
+ Log.w(DEBUG_TAG, "No existing lines");
+ res.set(Result.NOT_FOUND);
+ return Response.error(new VolleyFetcherError(Result.NOT_FOUND));
+ }
+
+ int howManyRoutes = json.length();
+ if(howManyRoutes == 0) {
+ res.set(Result.EMPTY_RESULT_SET);
+ return Response.error(new VolleyFetcherError(Result.EMPTY_RESULT_SET));
+ }
+
+ try {
+ JSONObject thisroute;
+ String routename, bacino;
+ JSONArray passaggi;
+ int howManyPassaggi;
+ Palina p = new Palina(stopID);
+ for(int i = 0; i < howManyRoutes; i++) {
+ thisroute = json.getJSONObject(i);
+ routename = thisroute.getString("Linea");
+ try {
+ bacino = thisroute.getString("Bacino");
+ } catch (JSONException ignored) { // if "Bacino" gets removed...
+ bacino = "U";
+ }
+ final Route r = new Route(routename, thisroute.getString("Direzione"),
+ "",
+ FiveTNormalizer.decodeType(routename, bacino));
+
+ passaggi = thisroute.getJSONArray("PassaggiRT");
+ howManyPassaggi = passaggi.length();
+ for(int j = 0; j < howManyPassaggi; j++) {
+ String mPassaggio = passaggi.getString(j);
+ if (mPassaggio.contains("__")){
+ mPassaggio = mPassaggio.replace("_", "");
+ }
+ r.addPassaggio(mPassaggio.concat("*"), Passaggio.Source.GTTJSON);
+ }
+
+
+ passaggi = thisroute.getJSONArray("PassaggiPR"); // now the non-real-time ones
+ howManyPassaggi = passaggi.length();
+ for(int j = 0; j < howManyPassaggi; j++) {
+ r.addPassaggio(passaggi.getString(j), Passaggio.Source.GTTJSON);
+ }
+ p.addRoute(r);
+ }
+ p.sortRoutes();
+ res.set(Result.OK);
+
+ return Response.success(p, HttpHeaderParser.parseCacheHeaders(networkResponse));
+ } catch (JSONException e) {
+ res.set(Result.PARSER_ERROR);
+ Log.d(DEBUG_TAG, "Failed to parse response into JSON: " + e.getMessage());
+ return Response.error(new VolleyFetcherError(Result.PARSER_ERROR));
+ }
+ }
+
+ @Override
+ public Map<String, String> getHeaders() {
+ HashMap<String, String> headers = new HashMap<>();
+ //headers.put("Referer","https://www.gtt.to.it/cms/percorari/urbano?view=percorsi&bacino=U&linea=15&Regol=GE");
+ headers.put("Host", "www.gtt.to.it");
+ return headers;
+ }
+
+ @Override
+ protected void deliverResponse(Palina palina) {
+ responder.onResponse(palina);
+ }
+ }
}
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherError.kt b/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherError.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherError.kt
@@ -0,0 +1,7 @@
+package it.reyboz.bustorino.backend
+
+import com.android.volley.VolleyError
+
+class VolleyFetcherError(
+ val reason: Fetcher.Result
+) : VolleyError()
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherErrorResponder.kt b/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherErrorResponder.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/backend/VolleyFetcherErrorResponder.kt
@@ -0,0 +1,23 @@
+package it.reyboz.bustorino.backend
+
+import android.util.Log
+import com.android.volley.Response
+import com.android.volley.VolleyError
+
+interface VolleyFetcherErrorResponder: Response.ErrorListener {
+
+ fun onErrorResponse(error: VolleyFetcherError){
+
+ }
+
+ override fun onErrorResponse(p0: VolleyError?) {
+ p0.let {
+ if(p0 is VolleyFetcherError){
+ onErrorResponse(p0 as VolleyFetcherError)
+ }
+ else{
+ Log.e("VolleyFetcherError", "Error is not instance of VolleyFetcherError, ignoring")
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt b/app/src/main/java/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
--- a/app/src/main/java/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
+++ b/app/src/main/java/it/reyboz/bustorino/backend/mato/MatoAPIFetcher.kt
@@ -39,11 +39,8 @@
open class MatoAPIFetcher(
private val minNumPassaggi: Int
-) : ArrivalsFetcher {
- var appContext: Context? = null
- set(value) {
- field = value!!.applicationContext
- }
+) : ArrivalsFetcherContext() {
+
constructor(): this(DEF_MIN_NUMPASSAGGI)
diff --git a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java b/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
--- a/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
+++ b/app/src/main/java/it/reyboz/bustorino/middleware/AsyncArrivalsSearcher.java
@@ -101,8 +101,8 @@
//get the data from the fetcher
ArrivalsFetcher f = r.getAndMoveForward();
AtomicReference<Fetcher.Result> resRef = new AtomicReference<>();
- if (f instanceof MatoAPIFetcher){
- ((MatoAPIFetcher)f).setAppContext(context);
+ if (f instanceof ArrivalsFetcherContext){
+ ((ArrivalsFetcherContext)f).setContext(context);
}
Log.d(TAG,"Using the ArrivalsFetcher: "+f.getClass());
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/ArrivalsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/ArrivalsViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/ArrivalsViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/ArrivalsViewModel.kt
@@ -125,8 +125,8 @@
sourcesLiveData.postValue(fetcher.sourceForFetcher)
- if (fetcher is MatoAPIFetcher) {
- fetcher.appContext = appContext
+ if (fetcher is ArrivalsFetcherContext) {
+ fetcher.setContext(appContext)
}
Log.d(DEBUG_TAG, "Using the ArrivalsFetcher: ${fetcher.javaClass}")

File Metadata

Mime Type
text/plain
Expires
Tue, May 26, 04:52 (1 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1918847
Default Alt Text
D232.1779763974.diff (14 KB)

Event Timeline