Page MenuHomeGitPull.it

D255.1786208236.diff
No OneTemporary

Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None

D255.1786208236.diff

diff --git a/app/src/main/java/it/reyboz/bustorino/ActivityPrincipal.java b/app/src/main/java/it/reyboz/bustorino/ActivityPrincipal.java
--- a/app/src/main/java/it/reyboz/bustorino/ActivityPrincipal.java
+++ b/app/src/main/java/it/reyboz/bustorino/ActivityPrincipal.java
@@ -238,7 +238,8 @@
startedFromIntent = tryedFromIntent;
//period database check
- DBUpdateCheckWorker.Companion.schedulePeriodicCheck(this,false);
+ //DBUpdateCheckWorker.Companion.schedulePeriodicCheck(this,false);
+ DBUpdateCheckWorker.Companion.runDBUpdateCheckWorker(this);
//Watch for database update
DBUpdateWorker.getWorkInfoLiveData(this)
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/utils.java b/app/src/main/java/it/reyboz/bustorino/backend/utils.java
--- a/app/src/main/java/it/reyboz/bustorino/backend/utils.java
+++ b/app/src/main/java/it/reyboz/bustorino/backend/utils.java
@@ -35,6 +35,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
+import java.time.OffsetDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -411,4 +412,8 @@
return new BigDecimal(value).setScale(decimalPlace,
RoundingMode.HALF_UP).stripTrailingZeros().doubleValue();
}
+
+ public static long parseFullDateToEpochMilliseconds(String date){
+ return OffsetDateTime.parse(date).toInstant().toEpochMilli();
+ }
}
diff --git a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateCheckWorker.kt b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateCheckWorker.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateCheckWorker.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateCheckWorker.kt
@@ -20,9 +20,24 @@
import android.content.Context
import android.content.SharedPreferences
import android.util.Log
+import androidx.core.app.NotificationCompat
import androidx.work.*
+import com.android.volley.Response
+import com.android.volley.VolleyError
+import com.android.volley.toolbox.HttpHeaderParser
+import com.android.volley.toolbox.JsonRequest
+import com.android.volley.toolbox.RequestFuture
+import it.reyboz.bustorino.backend.NetworkVolleyManager
+import it.reyboz.bustorino.backend.utils
import it.reyboz.bustorino.data.gtfs.GtfsDatabase
+import it.reyboz.bustorino.data.gtfs.GtfsStop
+import it.reyboz.bustorino.data.gtfs.GtfsTableJsonInserter
+import org.json.JSONObject
import java.util.concurrent.TimeUnit
+import androidx.core.content.edit
+import androidx.work.WorkManager.Companion.getInstance
+import it.reyboz.bustorino.R
+import it.reyboz.bustorino.backend.Notifications
/**
* Lightweight periodic worker that checks local state and enqueues [DBUpdateWorker]
@@ -39,14 +54,15 @@
val lastDBUpdateTime = sharedPrefs.getLong(PreferencesHolder.DB_LAST_UPDATE_KEY, 0L)
val currentTime = System.currentTimeMillis() / 1000
- val neverUpdated = currentDBVersion < 0 || lastDBUpdateTime <= 0
+
+ val neverUpdated = lastDBUpdateTime <= 0
val timeElapsed = currentTime > lastDBUpdateTime + UPDATE_MIN_DELAY
val isSpecialCase = checkIfNeedSpecialUpgradeDB(con)
-
+ //Last launch the DB update from MaTO
if (neverUpdated || timeElapsed || isSpecialCase) {
- Log.d(DEBUG_TAG, "Scheduling DBUpdateWorker")
+ Log.d(DEBUG_TAG, "Scheduling DBUpdateWorker, never updated: $neverUpdated, timeElapsed : $timeElapsed")
DBUpdateWorker.requestDBUpdateUniqueWork(con, forced = true)
if(isSpecialCase){
val gtfsDBVer = getGtfsDBVersion(con)
@@ -58,15 +74,90 @@
Log.d(DEBUG_TAG, "No update needed")
}
+ //// FIRST, RUN CHECK FOR GTFS DATA
+ val lastGTFSDatabaseUpdateTime = sharedPrefs.getLong(PreferencesHolder.DB_GTFS_LAST_UPDATE_STOPS, 0L)
+ val newGtfsUpdateTime = checkGtfsVersion("stops")
+
+ if(newGtfsUpdateTime > lastGTFSDatabaseUpdateTime) {
+ Log.d(DEBUG_TAG, "Updating GTFS data, tables are more recent")
+ val downloader = GtfsTableJsonInserter(applicationContext, "stops", GtfsStop.Companion)
+
+ val done = downloader.downloadAndInsertStops()
+ if(done){
+ sharedPrefs.edit { putLong(PreferencesHolder.DB_GTFS_LAST_UPDATE_STOPS, newGtfsUpdateTime) }
+ }
+ Log.d(DEBUG_TAG, "Completed download, insert worked: $done")
+ }
+
return Result.success()
}
+ override suspend fun getForegroundInfo(): ForegroundInfo {
+ val context = applicationContext
+ Notifications.createDBNotificationChannelIfNeeded(context)
+
+ val builder = NotificationCompat.Builder(
+ context,
+ Notifications.DB_UPDATE_CHANNELS_ID
+ )
+ .setContentTitle(context.getString(it.reyboz.bustorino.R.string.database_update_msg_notif))
+ .setProgress(0, 0, true)
+ .setPriority(NotificationCompat.PRIORITY_LOW)
+ builder.setSmallIcon(R.drawable.refresh_line)
+
+ return ForegroundInfo(NOTIFICATION_ID, builder.build())
+ }
+
+
+ fun checkGtfsVersion(table: String): Long {
+ val volleyManager = NetworkVolleyManager.getInstance(applicationContext)
+ val errorListener = Response.ErrorListener { error ->
+ Log.w(DEBUG_TAG, "Error fetching gtfs version",error)
+ }
+ var version: Long = 0
+ val future = RequestFuture.newFuture<Long>()
+ //response ->
+ //}
+ val req = object : JsonRequest<Long>(Method.GET, URL_JSON_GTFS_VERSIONS, null, future, errorListener) {
+ override fun parseNetworkResponse(p0: com.android.volley.NetworkResponse): Response<Long> {
+ var response:Long = 0
+ try{
+ val data = JSONObject(String(p0.data))
+ val selobj = data.getJSONObject("$table.txt")
+ val lastDate = selobj.getString("last_modified")
+
+ response = utils.parseFullDateToEpochMilliseconds(lastDate)
+ } catch (e: Exception){
+ //Log.w(DEBUG_TAG, "Error parsing network response",e)
+ return Response.error(VolleyError(e))
+ }
+
+ return Response.success(response, HttpHeaderParser.parseCacheHeaders(p0))
+ }
+ }
+ volleyManager.requestQueue.add(req)
+
+ try {
+ version = future.get(120, TimeUnit.SECONDS)
+ }catch (e: Exception){
+ e.printStackTrace()
+ }
+ finally {
+ future.cancel(true)
+ }
+ return version
+ }
+
companion object {
const val DEBUG_TAG = "BusTO-DBUpdateScheduler"
const val WORK_NAME = "DBUpdateChecker"
+ const val URL_JSON_GTFS_VERSIONS = "https://github.com/fabmazz/gtfs_gtt_check/releases/latest/download/versions.json"
+
+ private const val NOTIFICATION_ID = 328918201
+
private const val UPDATE_MIN_DELAY = (3 * 24 * 3600L) //
fun schedulePeriodicCheck(context: Context, restart: Boolean = false) {
@@ -87,6 +178,20 @@
.enqueueUniquePeriodicWork(WORK_NAME, policy, workRequest)
}
+ fun runDBUpdateCheckWorker(context: Context) {
+ val workManager = getInstance(context)
+
+ val wr = OneTimeWorkRequest.Builder(DBUpdateCheckWorker::class.java)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.SECONDS)
+ .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
+ .setConstraints(
+ Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED)
+ .build()
+ )
+ .build()
+
+ workManager.enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.REPLACE, wr)
+ }
@JvmStatic
private fun getGtfsDBVersion(context: Context): Int {
val gtfsDB = GtfsDatabase.Companion.getGtfsDatabase(context)
@@ -103,10 +208,7 @@
//applicationContext.getMainSharedPreferences()
val old_version = PreferencesHolder.getGtfsDBVersion(theShPr)
- Log.d(
- DEBUG_TAG,
- "GTFS Database: old version is $old_version, new version is $db_version"
- )
+
if (old_version < db_version) {
//decide update conditions in the future
if (old_version < 2 && db_version >= 2) {
@@ -115,6 +217,7 @@
}
//PreferencesHolder.setGtfsDBVersion(theShPr, db_version)
}
+ Log.d(DEBUG_TAG,"Special update needed: $dataUpdateNeeded, old version: $old_version, new version: $db_version")
return dataUpdateNeeded
}
diff --git a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.kt b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.kt
@@ -30,6 +30,7 @@
import it.reyboz.bustorino.backend.Notifications
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicReference
+import androidx.core.content.edit
/**
* Worker class that runs the DB update, without checking if it is needed or not
@@ -89,11 +90,11 @@
}
Log.d(DEBUG_TAG, "Update finished successfully!")
//update the version in the shared preference
- val editor = sharedPrefs.edit()
- editor.putInt(PreferencesHolder.DB_GTT_VERSION_KEY, newDBVersion)
- val currentTime = System.currentTimeMillis() / 1000
- editor.putLong(PreferencesHolder.DB_LAST_UPDATE_KEY, currentTime)
- editor.apply()
+ sharedPrefs.edit {
+ putInt(PreferencesHolder.DB_GTT_VERSION_KEY, newDBVersion)
+ val currentTime = System.currentTimeMillis() / 1000
+ putLong(PreferencesHolder.DB_LAST_UPDATE_KEY, currentTime)
+ }
//cancelNotification(NOTIFICATION_ID)
return Result.success(Data.Builder().putInt(SUCCESS_REASON_KEY, SUCCESS_UPDATE_DONE).build())
diff --git a/app/src/main/java/it/reyboz/bustorino/data/FavoritesLiveData.java b/app/src/main/java/it/reyboz/bustorino/data/FavoritesLiveData.java
deleted file mode 100644
--- a/app/src/main/java/it/reyboz/bustorino/data/FavoritesLiveData.java
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- BusTO - Data components
- 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.data;
-
-
-import android.content.ContentResolver;
-import android.content.Context;
-import android.database.ContentObserver;
-import android.database.Cursor;
-import android.database.DatabaseErrorHandler;
-import android.net.Uri;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import androidx.lifecycle.LiveData;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import it.reyboz.bustorino.BuildConfig;
-import it.reyboz.bustorino.backend.Stop;
-
-public class FavoritesLiveData extends LiveData<List<Stop>> implements CustomAsyncQueryHandler.AsyncQueryListener {
- private static final String TAG = "BusTO-FavoritesLiveData";
- private final boolean notifyChangesDescendants;
-
-
- @NonNull
- private final Context mContext;
-
- @NonNull
- private final FavoritesLiveData.ForceLoadContentObserver mObserver;
- private final CustomAsyncQueryHandler queryHandler;
-
-
- private final Uri FAVORITES_URI = AppDataProvider.getUriBuilderToComplete().appendPath(
- AppDataProvider.FAVORITES).build();
-
-
- private final int FAV_TOKEN = 23, STOPS_TOKEN_BASE=220;
-
-
- @Nullable
- private List<Stop> stopsFromFavorites, stopsDone;
-
- private boolean isQueryRunning = false;
- private int stopNeededCount = 0;
-
- public FavoritesLiveData(@NonNull Context context, boolean notifyDescendantsChanges) {
- super();
- mContext = context.getApplicationContext();
- mObserver = new FavoritesLiveData.ForceLoadContentObserver();
- notifyChangesDescendants = notifyDescendantsChanges;
- queryHandler = new CustomAsyncQueryHandler(mContext.getContentResolver(),this);
-
- }
-
- public void loadData() {
- loadData(false);
- }
- private static Uri.Builder getStopsBuilder(){
- return AppDataProvider.getUriBuilderToComplete().appendPath("stop");
-
- }
-
- private void loadData(boolean forceQuery) {
- Log.d(TAG, "loadData() force: "+forceQuery);
-
- if (!forceQuery){
- if (getValue()!= null){
- //Data already loaded
- Log.d(TAG, "Data already loaded");
- return;
- }
- }
- if (isQueryRunning){
- //we are waiting for data, we will get an update soon
- Log.d(TAG, "Query is running, abort");
- return;
- }
-
- isQueryRunning = true;
- startQuery();
-
- }
-
- private void startQuery(){
- Log.d(TAG, "startQuery for token "+FAV_TOKEN);
- queryHandler.startQuery(FAV_TOKEN,null, FAVORITES_URI, UserDB.FAVORITES_COLUMNS_ARRAY, null, null, null);
-
- }
-
- public void stopQuery(){
- queryHandler.cancelOperation(FAV_TOKEN);
- isQueryRunning = false;
- }
-
- public void forceReload(){
- loadData(true);
- }
-
- @Override
- protected void onActive() {
- //Log.d(TAG, "onActive()");
- loadData(true);
- }
-
- /**
- * Clear the data for the cursor
- */
- public void onClear(){
-
- ContentResolver resolver = mContext.getContentResolver();
- resolver.unregisterContentObserver(mObserver);
-
- }
-
-
- @Override
- protected void setValue(List<Stop> stops) {
- //Log.d("BusTO-FavoritesLiveData","Setting the new values for the stops, have "+
- // stops.size()+" stops");
-
- ContentResolver resolver = mContext.getContentResolver();
- resolver.registerContentObserver(FAVORITES_URI, notifyChangesDescendants,mObserver);
-
- super.setValue(stops);
- }
-
- @Override
- public void onQueryComplete(int token, Object cookie, Cursor cursor) {
- if (cursor == null){
- Log.e(TAG, "Null cursor for token "+token);
- if(token == FAV_TOKEN){
- //restart query
- Log.d(TAG, "Restarting query");
- queryHandler.cancelOperation(FAV_TOKEN);
-
- isQueryRunning = false;
- loadData(true);
- }
- return;
- }
- if (token == FAV_TOKEN) {
- stopsFromFavorites = UserDB.getFavoritesFromCursor(cursor, UserDB.FAVORITES_COLUMNS_ARRAY);
- cursor.close();
- //reset counters
- stopNeededCount = stopsFromFavorites.size();
- stopsDone = new ArrayList<>();
- if(stopsFromFavorites.isEmpty()){
- //we don't need to call the other query
- setValue(stopsDone);
- isQueryRunning = false;
- } else
- for (int i = 0; i < stopsFromFavorites.size(); i++) {
- Stop s = stopsFromFavorites.get(i);
- queryHandler.startQuery(STOPS_TOKEN_BASE + i, null,
- getStopsBuilder().appendPath(s.ID).build(),
- NextGenDB.QUERY_COLUMN_stops_all, null, null, null);
- }
-
-
-
- } else if(token >= STOPS_TOKEN_BASE){
- final int index = token - STOPS_TOKEN_BASE;
- assert stopsFromFavorites != null;
- Stop stopUpdate = stopsFromFavorites.get(index);
- Stop finalStop;
-
- List<Stop> result = NextGenDB.getStopsFromCursorAllFields(cursor);
- cursor.close();
- if (result.isEmpty()){
- // stop is not in the DB
- finalStop = stopUpdate;
- } else {
- finalStop = result.get(0);
- if (BuildConfig.DEBUG && !(finalStop.ID.equals(stopUpdate.ID))) {
- throw new AssertionError("Assertion failed");
- }
- finalStop.setStopUserName(stopUpdate.getStopUserName());
- }
- if (stopsDone!=null)
- stopsDone.add(finalStop);
-
- stopNeededCount--;
- if (stopNeededCount == 0) {
- // we have finished the queries
- isQueryRunning = false;
- Collections.sort(stopsDone);
-
- setValue(stopsDone);
- }
-
- }
- }
-
-
- /**
- * Content Observer that forces reload of cursor when data changes
- * On different thread (new Handler)
- */
- public final class ForceLoadContentObserver
- extends ContentObserver {
-
- public ForceLoadContentObserver() {
- super(new Handler(Looper.myLooper()));
- }
-
- @Override
- public boolean deliverSelfNotifications() {
- return true;
- }
-
- @Override
- public void onChange(boolean selfChange) {
- Log.d(TAG, "ForceLoadContentObserver.onChange()");
- loadData(true);
- }
-
- }
-
-
-}
-
diff --git a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
--- a/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
+++ b/app/src/main/java/it/reyboz/bustorino/data/PreferencesHolder.java
@@ -42,6 +42,7 @@
public static final String PREF_INTRO_ACTIVITY_RUN ="pref_intro_activity_run";
public static final String DB_GTT_VERSION_KEY = "NextGenDB.GTTVersion";
public static final String DB_LAST_UPDATE_KEY = "NextGenDB.LastDBUpdate";
+ public static final String DB_GTFS_LAST_UPDATE_STOPS = "GtfsDatabase.LastUpdate.Stops";
public static final String PREF_FAVORITE_LINES = "pref_favorite_lines";
// match the one in preferences.xml
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsDBDao.kt
@@ -37,7 +37,10 @@
fun getAllStopsIDs() : List<Int>
@Query("SELECT * FROM "+GtfsStop.DB_TABLE+" WHERE "+GtfsStop.COL_STOP_CODE+" LIKE :queryID")
- fun getStopByStopID(queryID: String): LiveData<List<GtfsStop>>
+ fun getStopByStopCode(queryID: String): LiveData<GtfsStop>
+
+ //@Query("SELECT * FROM ${GtfsStop.DB_TABLE} WHERE ${GtfsStop.COL_STOP_ID} LIKE :stopID")
+ //fun getStopByGtfsID(stopID: Int) : LiveData<GtfsStop>
@Query("SELECT * FROM "+GtfsShape.DB_TABLE+
" WHERE "+GtfsShape.COL_SHAPE_ID+" LIKE :shapeID"+
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsStop.kt b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsStop.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsStop.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsStop.kt
@@ -17,9 +17,14 @@
*/
package it.reyboz.bustorino.data.gtfs
+import android.content.Context
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
+import de.siegmar.fastcsv.reader.CsvRecord
+import de.siegmar.fastcsv.reader.NamedCsvRecord
+import it.reyboz.bustorino.data.GtfsRepository
+import it.reyboz.bustorino.data.gtfs.GtfsStop
@Entity(tableName = GtfsStop.DB_TABLE)
data class GtfsStop(
@@ -27,7 +32,7 @@
@ColumnInfo(name= COL_STOP_ID)
val internalID: Int,
@ColumnInfo(name= COL_STOP_CODE)
- val gttStopID: String,
+ val stopCode: String,
@ColumnInfo(name= COL_STOP_NAME)
val stopName: String,
@ColumnInfo(name= COL_GTT_PLACE)
@@ -52,7 +57,8 @@
//valuesByColumn["zone_id"]?.toIntOrNull()!!,
Converters.wheelchairFromString(valuesByColumn[COL_WHEELCHAIR])
)
- companion object{
+
+ companion object : RecordInserter<GtfsStop> {
const val DB_TABLE="stops_gtfs"
const val COL_STOP_CODE="stop_code"
const val COL_STOP_ID = "stop_id"
@@ -71,6 +77,25 @@
//"zone_id",
COL_WHEELCHAIR
)
+
+ override fun fromRecord(record: NamedCsvRecord): GtfsStop {
+ return GtfsStop(record.getField(COL_STOP_ID).toInt(),
+ record.getField(COL_STOP_CODE),
+ record.getField(COL_STOP_NAME),
+ record.getField(COL_GTT_PLACE),
+ record.getField(COL_LATITUDE).toDouble(),
+ record.getField(COL_LONGITUDE).toDouble(),
+ Converters.wheelchairFromString(record.getField(COL_WHEELCHAIR))
+ )
+ }
+
+ override fun insertInDatabase(
+ elements: List<GtfsStop>,
+ context: Context
+ ): Boolean {
+ GtfsRepository(context).gtfsDao.insertStops(elements)
+ return true
+ }
}
override fun getColumns(): Array<String> {
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTable.java b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTable.java
--- a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTable.java
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTable.java
@@ -20,5 +20,4 @@
public interface GtfsTable {
String[] getColumns();
-
}
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTableJsonInserter.kt b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTableJsonInserter.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/GtfsTableJsonInserter.kt
@@ -0,0 +1,83 @@
+package it.reyboz.bustorino.data.gtfs
+
+import android.content.Context
+import android.util.Log
+import com.android.volley.NetworkResponse
+import com.android.volley.Request.Method
+import com.android.volley.Response
+import com.android.volley.VolleyError
+import com.android.volley.toolbox.HttpHeaderParser
+import com.android.volley.toolbox.JsonRequest
+import com.android.volley.toolbox.RequestFuture
+import de.siegmar.fastcsv.reader.CsvReader
+import it.reyboz.bustorino.backend.NetworkVolleyManager
+import it.reyboz.bustorino.backend.Result
+import it.reyboz.bustorino.backend.utils
+import it.reyboz.bustorino.data.DBUpdateCheckWorker.Companion.DEBUG_TAG
+import it.reyboz.bustorino.data.DBUpdateCheckWorker.Companion.URL_JSON_GTFS_VERSIONS
+import it.reyboz.bustorino.data.GtfsRepository
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import org.json.JSONObject
+import java.io.ByteArrayInputStream
+import java.util.concurrent.TimeUnit
+import java.util.zip.GZIPInputStream
+
+class GtfsTableJsonInserter<T>(
+ context: Context,
+ //callback: Result.Callback<Boolean>
+ val tableName: String,
+ val inserter: RecordInserter<T>
+) {
+ private val context = context.applicationContext
+
+ fun downloadAndInsertStops(): Boolean {
+ val volleyManager = NetworkVolleyManager.getInstance(context)
+ val url = "$BASE_URL/$tableName.txt.gz"
+ val errorListener = Response.ErrorListener { error ->
+ Log.w(DEBUG_TAG, "Error fetching table stops, url $url ",error)
+ }
+ val future = RequestFuture.newFuture<List<T>>()
+ //response ->
+ //}
+ val req = object : JsonRequest<List<T>>(Method.GET,url,null, future, errorListener) {
+ override fun parseNetworkResponse(p0: NetworkResponse): Response<List<T>> {
+ var stops: List<T>
+ try{
+ val input = GZIPInputStream(ByteArrayInputStream(p0.data))
+
+ val reader = CsvReader.builder().ofNamedCsvRecord(input)
+
+ stops = reader.map { record ->
+ inserter.fromRecord(record)
+ }
+
+ } catch (e: Exception){
+ //Log.w(DEBUG_TAG, "Error parsing network response",e)
+ return Response.error(VolleyError(e))
+ }
+
+ return Response.success(stops, HttpHeaderParser.parseCacheHeaders(p0))
+ }
+ }
+ volleyManager.requestQueue.add(req)
+
+ try {
+ val stops = future.get(120, TimeUnit.SECONDS)
+
+ inserter.insertInDatabase(stops, context)
+ }catch (e: Exception){
+ e.printStackTrace()
+ return false
+ }
+ finally {
+ future.cancel(true)
+ }
+ return true
+ }
+
+ companion object {
+ const val BASE_URL = "https://github.com/fabmazz/gtfs_gtt_check/releases/latest/download"
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/data/gtfs/RecordInserter.kt b/app/src/main/java/it/reyboz/bustorino/data/gtfs/RecordInserter.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/data/gtfs/RecordInserter.kt
@@ -0,0 +1,11 @@
+package it.reyboz.bustorino.data.gtfs
+
+import android.content.Context
+import de.siegmar.fastcsv.reader.NamedCsvRecord
+
+interface RecordInserter<T> {
+
+ fun fromRecord(record: NamedCsvRecord): T
+
+ fun insertInDatabase(elements: List<T>, context: Context): Boolean
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/ArrivalsFragment.kt
@@ -516,7 +516,7 @@
lastUpdatedPalina = p
//set the gtfsID for the alerts
if(isAdded){
- //alertsViewModel.setStopFilter(p)
+ alertsViewModel.setStopFilter(p)
} else{
Log.w(DEBUG_TAG, "Cannot filter alerts for palina $p, the fragment is not added")
}
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/ServiceAlertsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/ServiceAlertsViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/ServiceAlertsViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/ServiceAlertsViewModel.kt
@@ -31,11 +31,9 @@
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.google.transit.realtime.GtfsRealtime.Alert
-import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.Stop
import it.reyboz.bustorino.data.GtfsAlertDBDownloadWorker
import it.reyboz.bustorino.data.GtfsRepository
-import it.reyboz.bustorino.data.gtfs.GtfsDatabase
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -44,9 +42,7 @@
class ServiceAlertsViewModel(app: Application) : AndroidViewModel(app) {
private val gtfsRepo = GtfsRepository(app)
- private val volleyManager = NetworkVolleyManager.getInstance(app)
- private val alertsDao = GtfsDatabase.getGtfsDatabase(app).alertsDao()
private val workManager = WorkManager.getInstance(app)
@@ -68,8 +64,12 @@
gtfsRepo.getAlertsByRouteID(it).map{ l -> l.filter { al->al.isActive(unixTimestamp) }}
}
- val alertsByStopLiveData = stopGtfsIdToFilter.switchMap {
- if(it.gtfsID!=null) gtfsRepo.alertsDao.getAlertsForStopGtfsId(it.gtfsID!!) else MutableLiveData()
+ //intermediate pass: request stop from GTFS database
+ private val gtfsStopLiveData = stopGtfsIdToFilter.switchMap {
+ gtfsRepo.gtfsDao.getStopByStopCode(it.ID)
+ }
+ val alertsByStopLiveData = gtfsStopLiveData.switchMap {
+ gtfsRepo.alertsDao.getAlertsForStopGtfsId("gtt:${it.internalID}")
}
val allAlertsLiveData = gtfsRepo.alertsDao.getAllAlertsLiveData()
@@ -100,13 +100,11 @@
*/
/// WE DO NOT KNOW HOW TO GET THE GTFS STOP ID, the one given by MaTO is the same as the stop CODE
/// but we need the ID from the stops.txt table of GTT GTFS data
- /// DISABLING THIS FUNCTION
- /*fun setStopFilter(stop: Stop) {
+ fun setStopFilter(stop: Stop) {
Log.d(DEBUG_TAG, "Setting stop to filter: ${stop.ID} - ${stop.stopDisplayName}, gtfsID: ${stop.gtfsID}")
- stopGtfsIdToFilter.value = stop
+ if(stopGtfsIdToFilter.value?.ID != stop.ID)
+ stopGtfsIdToFilter.value = stop
}
-
- */
fun setGtfsLineFilter(routeId: String) {
routeToFilter.value = routeId
}
diff --git a/app/src/main/res/layout/fragment_arrivals.xml b/app/src/main/res/layout/fragment_arrivals.xml
--- a/app/src/main/res/layout/fragment_arrivals.xml
+++ b/app/src/main/res/layout/fragment_arrivals.xml
@@ -161,7 +161,7 @@
android:textSize="19sp"
android:visibility="gone" />
- <androidx.cardview.widget.CardView
+ <com.google.android.material.card.MaterialCardView
android:id="@+id/alertsCardView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -169,17 +169,20 @@
app:cardElevation="0dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
- android:layout_marginTop="5sp"
+ android:layout_marginTop="2sp"
android:layout_marginBottom="2sp"
- android:backgroundTint="@color/alerts_color_button"
android:foreground="?attr/selectableItemBackground"
android:visibility="gone"
+ app:strokeWidth="0dp"
+ app:cardBackgroundColor="@color/card_background"
>
<androidx.constraintlayout.widget.ConstraintLayout
- android:padding="5dp"
+ android:paddingTop="6dp"
+ android:paddingBottom="6dp"
+ android:paddingStart="8dp"
+ android:paddingEnd="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:paddingEnd="10dp"
>
<View android:layout_width="1dp"
android:layout_height="20dp"
@@ -190,18 +193,15 @@
app:layout_constraintEnd_toStartOf="@id/bubbleImageView"
/>
<ImageView
- android:layout_width="35dp"
- android:layout_height="35dp"
+ android:layout_width="40dp"
+ android:layout_height="40dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@id/uselessView"
app:layout_constraintEnd_toStartOf="@id/alertShowingTextView"
android:src="@drawable/chat_bubble_warning_solid"
android:id="@+id/bubbleImageView"
- android:layout_marginStart="10dp"
- android:layout_marginTop="5dp"
- android:layout_marginBottom="5dp"
- app:tint="@color/white"
+ app:tint="@color/alerts_color_button"
app:layout_constraintHorizontal_bias="0.0"
@@ -213,19 +213,19 @@
app:layout_constraintStart_toEndOf="@id/bubbleImageView"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:fontFamily="@font/lato_regular"
- android:text="Ci sono avvisi"
- android:textColor="@color/white"
+ android:fontFamily="@font/lato_bold"
+ android:text="@string/alerts_arrivals"
+ android:textColor="@color/alerts_color_button"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
- android:textSize="18sp"
+ android:textSize="19sp"
app:layout_constraintHorizontal_bias="0.0"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
- </androidx.cardview.widget.CardView>
+ </com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/arrivalsRecyclerView"
android:layout_width="match_parent"
diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml
--- a/app/src/main/res/values-it/strings.xml
+++ b/app/src/main/res/values-it/strings.xml
@@ -250,6 +250,8 @@
<string name="italian">Italiano</string>
<string name="english">Inglese</string>
<string name="alert_line_fill">Avvisi per la linea %1$s:</string>
+ <string name="alert_stop_fill">Avvisi per la fermata %1$s:</string>
+
<string name="checking_alerts_update">Controllo degli avvisi disponibili in corso</string>
<string name="no_gps_on_device">Servizio GPS non trovato sul dispositivo!</string>
<string name="downloading_alerts_message">Download dati avvisi in tempo reale</string>
@@ -264,4 +266,6 @@
<string name="day_night_theme_keep_system">Segui il sistema</string>
<string name="pref_theme_day_night_title">Imposta tema scuro o chiaro</string>
+
+ <string name="alerts_arrivals">Avvisi di servizio</string>
</resources>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -415,5 +415,6 @@
<string name="english">English</string>
<string name="checking_alerts_update">Checking new alerts now</string>
<string name="back_again_to_close">Press back again to close the app</string>
+ <string name="alerts_arrivals">Service alerts</string>
</resources>

File Metadata

Mime Type
text/plain
Expires
Sat, Aug 8, 18:57 (16 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2048999
Default Alt Text
D255.1786208236.diff (35 KB)

Event Timeline