Page Menu
Home
GitPull.it
Search
Configure Global Search
Log In
Files
F13281167
D161.1777596062.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Size
22 KB
Referenced Files
None
Subscribers
None
D161.1777596062.diff
View Options
diff --git a/app/build.gradle b/app/build.gradle
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -12,8 +12,8 @@
minSdkVersion 21
targetSdkVersion 34
buildToolsVersion = '34.0.0'
- versionCode 57
- versionName "2.2.0"
+ versionCode 58
+ versionName "2.2.1"
vectorDrawables.useSupportLibrary = true
multiDexEnabled true
javaCompileOptions {
@@ -70,6 +70,9 @@
api "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
api "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
+
+ // Guava implementation for DBUpdateWorker
+ implementation 'com.google.guava:guava:29.0-android'
implementation "androidx.fragment:fragment-ktx:$fragment_version"
implementation "androidx.activity:activity:$activity_version"
@@ -83,7 +86,7 @@
implementation "androidx.work:work-runtime-ktx:$work_version"
- implementation "com.google.android.material:material:1.9.0"
+ implementation "com.google.android.material:material:1.11.0"
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation "androidx.coordinatorlayout:coordinatorlayout:1.2.0"
@@ -102,11 +105,9 @@
implementation 'com.google.protobuf:protobuf-java:3.19.6'
// mqtt library
implementation 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.2.5'
- implementation 'com.github.hannesa2:paho.mqtt.android:4.2'
+ implementation 'com.github.hannesa2:paho.mqtt.android:4.2.4'
//implementation 'com.github.fabmazz:paho.mqtt.android:v0.0.1'
-
-
// ViewModel
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
// LiveData
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -12,9 +12,10 @@
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission
android:name="android.permission.POST_NOTIFICATIONS"/> <!-- this is to REMOVE the permission from MQTT service -->
- <uses-permission
+ <!--<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"
tools:node="remove"/>
+ -->
<queries>
<intent>
@@ -133,6 +134,8 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="it.reyboz.bustorino.ActivityPrincipal"/>
</activity>
+
+ <!--<service tools:node="replace" android:name="info.mqtt.android.service.MqttService"/>-->
</application>
</manifest>
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/BustoApp.java b/app/src/main/java/it/reyboz/bustorino/BustoApp.java
--- a/app/src/main/java/it/reyboz/bustorino/BustoApp.java
+++ b/app/src/main/java/it/reyboz/bustorino/BustoApp.java
@@ -28,29 +28,44 @@
import org.acra.config.MailSenderConfigurationBuilder;
import org.acra.data.StringFormat;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.List;
+
import static org.acra.ReportField.*;
public class BustoApp extends MultiDexApplication {
- private static final ReportField[] REPORT_FIELDS = {REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME,
+ private static final List<ReportField> REPORT_FIELDS = List.of(REPORT_ID, APP_VERSION_CODE, APP_VERSION_NAME,
PACKAGE_NAME, PHONE_MODEL, BRAND, PRODUCT, ANDROID_VERSION, BUILD_CONFIG, CUSTOM_DATA,
IS_SILENT, STACK_TRACE, INITIAL_CONFIGURATION, CRASH_CONFIGURATION, DISPLAY, USER_COMMENT,
- USER_APP_START_DATE, USER_CRASH_DATE, LOGCAT, SHARED_PREFERENCES};
+ USER_APP_START_DATE, USER_CRASH_DATE, LOGCAT, SHARED_PREFERENCES);
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
- CoreConfigurationBuilder builder = new CoreConfigurationBuilder(this);
- builder.setBuildConfigClass(BuildConfig.class).setReportFormat(StringFormat.JSON)
- .setDeleteUnapprovedReportsOnApplicationStart(true);
- builder.getPluginConfigurationBuilder(MailSenderConfigurationBuilder.class).setMailTo("gtt@succhia.cz")
- .setReportFileName(it.reyboz.bustorino.BuildConfig.VERSION_NAME +"_report.json")
- .setResBody(R.string.acra_email_message)
- .setEnabled(true);
- builder.getPluginConfigurationBuilder(DialogConfigurationBuilder.class).setResText(R.string.message_crash)
- .setResTheme(R.style.AppTheme)
+ CoreConfigurationBuilder builder = new CoreConfigurationBuilder();
+ // mail stuff
+ MailSenderConfigurationBuilder mailConfig = new MailSenderConfigurationBuilder();
+ mailConfig.withMailTo("gtt@succhia.cz")
+ .withReportFileName(it.reyboz.bustorino.BuildConfig.VERSION_NAME +"_report.json")
+ .withBody(getString(R.string.acra_email_message))
.setEnabled(true);
+ //dialog stuff
+ DialogConfigurationBuilder dialogBuild = new DialogConfigurationBuilder();
+ dialogBuild.withText(getString(R.string.message_crash))
+ .withResTheme(R.style.AppTheme).setEnabled(true);
+ //Set options
+ builder.withBuildConfigClass(BuildConfig.class)
+ .withReportFormat(StringFormat.JSON)
+ .withDeleteUnapprovedReportsOnApplicationStart(true);
+ //Add plugins
+ builder.withPluginConfigurations(
+ mailConfig.build(), dialogBuild.build()
+ );
+
+
builder.setReportContent(REPORT_FIELDS);
if (!it.reyboz.bustorino.BuildConfig.DEBUG)
ACRA.init(this, builder);
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/Notifications.java b/app/src/main/java/it/reyboz/bustorino/backend/Notifications.java
--- a/app/src/main/java/it/reyboz/bustorino/backend/Notifications.java
+++ b/app/src/main/java/it/reyboz/bustorino/backend/Notifications.java
@@ -11,6 +11,7 @@
public class Notifications {
public static final String DEFAULT_CHANNEL_ID ="Default";
public static final String DB_UPDATE_CHANNELS_ID ="Database Update";
+ public static final String MATO_LIVE_POSITIONS_CHANNEL="Live Positions";
//match this value to the one used by the MQTTAndroidClient MANUALLY
@@ -64,12 +65,27 @@
.setContentText(title)
.build();
}
+
+ public static Notification makeLivePositionsNotification(Context context,String title){
+ return new NotificationCompat.Builder(context, Notifications.MATO_LIVE_POSITIONS_CHANNEL)
+ //.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), Constants.PENDING_INTENT_FLAG_IMMUTABLE))
+ .setSmallIcon(R.drawable.ic_bus_stilized_transparent)
+ .setOngoing(true)
+ .setAutoCancel(true)
+ .setOnlyAlertOnce(true)
+ .setPriority(NotificationCompat.PRIORITY_MIN)
+ .setContentTitle(context.getString(R.string.app_name))
+ .setLocalOnly(true)
+ .setVisibility(NotificationCompat.VISIBILITY_SECRET)
+ .setContentText(title)
+ .build();
+ }
public static Notification makeMatoDownloadNotification(Context context){
return makeMatoDownloadNotification(context, context.getString(R.string.downloading_data_mato));
}
public static Notification makeMQTTServiceNotification(Context context){
- return makeMatoDownloadNotification(context, context.getString(R.string.mqtt_notification_text));
+ return makeLivePositionsNotification(context, context.getString(R.string.mqtt_notification_text));
}
public static void cancelNotification(Context context, int notificationID){
@@ -88,4 +104,18 @@
notificationManager.createNotificationChannel(channel);
}
}
+
+ public static void createLivePositionsChannel(Context context){
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ NotificationChannel channel = new NotificationChannel(
+ Notifications.MATO_LIVE_POSITIONS_CHANNEL,
+ context.getString(R.string.live_positions_notification_channel),
+ NotificationManager.IMPORTANCE_MIN
+ );
+ channel.setDescription(context.getString(R.string.live_positions_notification_channel_desc));
+
+ NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
+ notificationManager.createNotificationChannel(channel);
+ }
+ }
}
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt b/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
--- a/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
+++ b/app/src/main/java/it/reyboz/bustorino/backend/mato/MQTTMatoClient.kt
@@ -48,12 +48,15 @@
client = MqttAndroidClient(context,SERVER_ADDR,clientID,Ack.AUTO_ACK)
// WE DO NOT WANT A FOREGROUND SERVICE -> it's only more mayhem
// (and the positions need to be downloaded only when the app is shown)
- /*if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
+ // update, 2024-04: Google Play doesn't understand our needs, so we put back the notification
+ // and add a video of it working as Google wants
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
//we need a notification
+ Notifications.createLivePositionsChannel(context)
val notific = Notifications.makeMQTTServiceNotification(context)
- client.setForegroundService(notific)
+ client!!.setForegroundService(notific)
notification=notific
- }*/
+ }
val options = MqttConnectOptions()
diff --git a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.java b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.java
--- a/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.java
+++ b/app/src/main/java/it/reyboz/bustorino/data/DBUpdateWorker.java
@@ -34,6 +34,7 @@
import static android.content.Context.MODE_PRIVATE;
+//TODO: Move to code to Kotlin
public class DBUpdateWorker extends Worker{
diff --git a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/MatoTripsDownloadWorker.kt
@@ -82,15 +82,20 @@
}
requestCountDown.await()
val tripsIDsCompleted = downloadedMatoTrips.map { trip-> trip.tripID }
- val doInsert = (queriedMatoTrips subtract failedMatoTripsDownload).containsAll(tripsIDsCompleted)
- Log.i(DEBUG_TAG, "Inserting missing GtfsTrips in the database, should insert $doInsert")
- if(doInsert){
+ if (tripsIDsCompleted.isEmpty()){
+ Log.d(DEBUG_TAG, "No trips have been downloaded, set work to fail")
+ return Result.failure()
+ } else {
+ val doInsert = (queriedMatoTrips subtract failedMatoTripsDownload).containsAll(tripsIDsCompleted)
+ Log.i(DEBUG_TAG, "Inserting missing GtfsTrips in the database, should insert $doInsert")
+ if (doInsert) {
- gtfsRepository.gtfsDao.insertTrips(downloadedMatoTrips)
+ gtfsRepository.gtfsDao.insertTrips(downloadedMatoTrips)
- }
+ }
- return Result.success()
+ return Result.success()
+ }
}
override suspend fun getForegroundInfo(): ForegroundInfo {
val notificationManager =
@@ -109,8 +114,8 @@
const val TAG_TRIPS ="gtfsTripsDownload"
- fun downloadTripsFromMato(trips: List<String>, context: Context, debugTag: String): Boolean{
- if (trips.isEmpty()) return false
+ fun requestMatoTripsDownload(trips: List<String>, context: Context, debugTag: String): OneTimeWorkRequest? {
+ if (trips.isEmpty()) return null
val workManager = WorkManager.getInstance(context)
val info = workManager.getWorkInfosForUniqueWork(TAG_TRIPS).get()
@@ -128,8 +133,8 @@
.addTag(TAG_TRIPS)
.build()
workManager.enqueueUniqueWork(TAG_TRIPS, ExistingWorkPolicy.KEEP, requ)
- }
- return true
+ return requ
+ } else return null;
}
}
}
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LinesDetailFragment.kt
@@ -366,7 +366,7 @@
//download missing tripIDs
liveBusViewModel.tripsGtfsIDsToQuery.observe(viewLifecycleOwner){
//gtfsPosViewModel.downloadTripsFromMato(dat);
- MatoTripsDownloadWorker.downloadTripsFromMato(
+ MatoTripsDownloadWorker.requestMatoTripsDownload(
it, requireContext().applicationContext,
"BusTO-MatoTripDownload"
)
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java b/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java
--- a/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/MapFragment.java
@@ -46,7 +46,6 @@
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate;
import it.reyboz.bustorino.backend.mato.MQTTMatoClient;
import it.reyboz.bustorino.backend.utils;
-import it.reyboz.bustorino.data.MatoTripsDownloadWorker;
import it.reyboz.bustorino.data.gtfs.MatoPattern;
import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops;
import it.reyboz.bustorino.map.*;
@@ -374,12 +373,16 @@
else
livePositionsViewModel.requestGTFSUpdates();
//mapViewModel.testCascade();
+ livePositionsViewModel.isLastWorkResultGood().observe(this, d ->
+ Log.d(DEBUG_TAG, "Last trip download result is "+d));
livePositionsViewModel.getTripsGtfsIDsToQuery().observe(this, dat -> {
Log.i(DEBUG_TAG, "Have these trips IDs missing from the DB, to be queried: "+dat);
- //gtfsPosViewModel.downloadTripsFromMato(dat);
- MatoTripsDownloadWorker.Companion.downloadTripsFromMato(dat,
+ livePositionsViewModel.downloadTripsFromMato(dat);
+ /*MatoTripsDownloadWorker.Companion.requestMatoTripsDownload(dat,
requireContext().getApplicationContext(),
"BusTO-MatoTripDownload");
+
+ */
});
} /*else if(gtfsPosViewModel!=null){
gtfsPosViewModel.requestUpdates();
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/GtfsPositionsViewModel.kt
@@ -20,6 +20,7 @@
import android.app.Application
import android.util.Log
import androidx.lifecycle.*
+import androidx.work.OneTimeWorkRequest
import com.android.volley.Response
import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
@@ -166,8 +167,8 @@
Keep in mind that trips DO CHANGE often, and so do the Patterns
*/
- fun downloadTripsFromMato(trips: List<String>): Boolean{
- return MatoTripsDownloadWorker.downloadTripsFromMato(trips,getApplication(), DEBUG_TI)
+ fun downloadTripsFromMato(trips: List<String>): OneTimeWorkRequest?{
+ return MatoTripsDownloadWorker.requestMatoTripsDownload(trips,getApplication(), "BusTO-MatoTripsDown")
}
private fun downloadMissingPatterns(routeIds: List<String>): Boolean{
return MatoPatternsDownloadWorker.downloadPatternsForRoutes(routeIds, getApplication())
diff --git a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
--- a/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
+++ b/app/src/main/java/it/reyboz/bustorino/viewmodels/LivePositionsViewModel.kt
@@ -20,6 +20,8 @@
import android.app.Application
import android.util.Log
import androidx.lifecycle.*
+import androidx.work.WorkInfo
+import androidx.work.WorkManager
import com.android.volley.DefaultRetryPolicy
import com.android.volley.Response
import it.reyboz.bustorino.backend.NetworkVolleyManager
@@ -28,9 +30,14 @@
import it.reyboz.bustorino.backend.mato.MQTTMatoClient
import it.reyboz.bustorino.data.GtfsRepository
import it.reyboz.bustorino.data.MatoPatternsDownloadWorker
+import it.reyboz.bustorino.data.MatoTripsDownloadWorker
import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
+import java.util.*
+import kotlin.collections.ArrayList
+import kotlin.collections.HashMap
+import kotlin.collections.HashSet
class LivePositionsViewModel(application: Application): AndroidViewModel(application) {
@@ -49,6 +56,27 @@
private val gtfsRtRequestRunning = MutableLiveData<Boolean>(false)
+ private val lastFailedTripsRequest = HashMap<String, Date>()
+ private val workManager = WorkManager.getInstance(application)
+
+ private var lastRequestedDownloadTrips = MutableLiveData<List<String>>()
+
+ var isLastWorkResultGood = workManager
+ .getWorkInfosForUniqueWorkLiveData(MatoTripsDownloadWorker.TAG_TRIPS).map { it ->
+ if (it.isEmpty()) return@map false
+ var res = true
+ if(it[0].state == WorkInfo.State.FAILED){
+ val currDate = Date()
+ res = false
+ lastRequestedDownloadTrips.value?.let { trips->
+ for(tr in trips){
+ lastFailedTripsRequest[tr] = currDate
+ }
+ }
+
+ }
+ return@map res
+ }
/**
* Responder to the MQTT Client
*/
@@ -218,8 +246,42 @@
mqttClient.disconnect()
super.onCleared()
}
+ //Request trips download
+ fun downloadTripsFromMato(trips: List<String>): Boolean{
+ if(trips.isEmpty())
+ return false
+ var shouldContinue = false
+ val currentDateTime = Date().time
+
+ for (tr in trips){
+ if (!lastFailedTripsRequest.containsKey(tr)){
+ shouldContinue = true
+ break
+ } else{
+ //Log.i(DEBUG_TI, "Last time the trip has failed is ${lastFailedTripsRequest[tr]}")
+ if ((lastFailedTripsRequest[tr]!!.time - currentDateTime) > MAX_TIME_RETRY){
+ shouldContinue =true
+ break
+ }
+ }
+ }
+ if (shouldContinue) {
+ //if one trip
+ val workRequ =MatoTripsDownloadWorker.requestMatoTripsDownload(trips, getApplication(), "BusTO-MatoTripsDown")
+ workRequ?.let { req ->
+ Log.d(DEBUG_TI, "Enqueueing new work, saving work info")
+ lastRequestedDownloadTrips.postValue(trips)
+ //isLastWorkResultGood =
+ }
+ } else{
+ Log.w(DEBUG_TI, "Requested to fetch data for ${trips.size} trips but they all have failed before in the last $MAX_MINUTES_RETRY mins")
+ }
+ return shouldContinue
+ }
companion object{
private const val DEBUG_TI = "BusTO-LivePosViewModel"
+ private const val MAX_MINUTES_RETRY = 3
+ private const val MAX_TIME_RETRY = MAX_MINUTES_RETRY*60*1000 //3 minutes (in milliseconds)
}
}
\ No newline at end of file
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
@@ -177,7 +177,12 @@
<string name="default_notification_channel_description">Canale default delle notifiche</string>
<string name="database_notification_channel">Operazioni sul database</string>
<string name="database_notification_channel_desc">Informazioni sul database (aggiornamento)</string>
- <string name="mqtt_notification_text">Servizio posizioni in tempo reale attivo</string>
+ <string name="live_position_service_name">BusTO - posizioni in tempo reale</string>
+
+ <string name="live_positions_notification_channel">Posizioni in tempo reale</string>
+ <string name="live_positions_notification_channel_desc">Attività del servizio delle posizioni in tempo reale</string>
+
+ <string name="mqtt_notification_text">Servizio posizioni MaTO in tempo reale attivo</string>
<string name="db_trips_download_message">Downloading trips from MaTO server</string>
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
@@ -203,7 +203,10 @@
<string name="default_notification_channel_description">Default channel for notifications</string>
<string name="database_notification_channel">Database operations</string>
<string name="database_notification_channel_desc">Updates of the app database</string>
- <string name="mqtt_notification_text">Bus live positions service is running</string>
+ <string name="live_position_service_name">BusTO - live position service</string>
+ <string name="live_positions_notification_channel">Live positions</string>
+ <string name="live_positions_notification_channel_desc">Showing activity related to the live positions service</string>
+ <string name="mqtt_notification_text">MaTO live bus positions service is running</string>
<string name="db_trips_download_message">Downloading trips from MaTO server</string>
diff --git a/build.gradle b/build.gradle
--- a/build.gradle
+++ b/build.gradle
@@ -11,7 +11,7 @@
}
//kotlin
ext.kotlin_version = '1.9.0'
- ext.coroutines_version = "1.7.3"
+ ext.coroutines_version = "1.8.0"
dependencies {
classpath 'com.android.tools.build:gradle:8.1.4'
@@ -31,8 +31,8 @@
preference_version = "1.2.1"
work_version = "2.9.0"
- acra_version = "5.7.0"
- lifecycle_version = "2.4.1"
+ acra_version = "5.11.3"
+ lifecycle_version = "2.7.0"
arch_version = "2.1.0"
room_version = "2.5.2"
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, May 1, 02:41 (7 h, 2 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1881150
Default Alt Text
D161.1777596062.diff (22 KB)
Attached To
Mode
D161: Re-enable foreground service with special notification channel, upgrade ACRA version
Attached
Detach File
Event Timeline
Log In to Comment