Page Menu
Home
GitPull.it
Search
Configure Global Search
Log In
Files
F13679907
D255.1786208236.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Authored By
Unknown
Size
35 KB
Referenced Files
None
Subscribers
None
D255.1786208236.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D255: Download GTFS stops table from github. Show alerts in line. Fix DB update problem
Attached
Detach File
Event Timeline