diff --git a/app/build.gradle b/app/build.gradle
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -102,7 +102,7 @@
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.1'
+ implementation 'com.github.hannesa2:paho.mqtt.android:4.2'
// ViewModel
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
@@ -10,6 +10,9 @@
+
+
+
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
@@ -12,6 +12,8 @@
public static final String DEFAULT_CHANNEL_ID ="Default";
public static final String DB_UPDATE_CHANNELS_ID ="Database Update";
+ //match this value to the one used by the MQTTAndroidClient MANUALLY
+
public static void createDefaultNotificationChannel(Context context) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
@@ -51,7 +53,7 @@
public static Notification makeMatoDownloadNotification(Context context,String title){
return new NotificationCompat.Builder(context, Notifications.DB_UPDATE_CHANNELS_ID)
//.setContentIntent(PendingIntent.getActivity(context, 0, Intent(context, MainActivity::class.java), Constants.PENDING_INTENT_FLAG_IMMUTABLE))
- .setSmallIcon(R.drawable.bus)
+ .setSmallIcon(R.drawable.ic_bus_stilized_transparent)
.setOngoing(true)
.setAutoCancel(true)
.setOnlyAlertOnce(true)
@@ -66,6 +68,15 @@
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));
+ }
+
+ public static void cancelNotification(Context context, int notificationID){
+ NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ manager.cancel(notificationID);
+ }
+
public static void createDBNotificationChannel(Context context){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
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
@@ -1,23 +1,25 @@
package it.reyboz.bustorino.backend.mato
+import android.app.Notification
+import android.app.NotificationManager
import android.content.Context
+import android.os.Build
import android.util.Log
import androidx.lifecycle.LifecycleOwner
import info.mqtt.android.service.Ack
-import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
-import org.eclipse.paho.client.mqttv3.*
import info.mqtt.android.service.MqttAndroidClient
import info.mqtt.android.service.QoS
-
+import it.reyboz.bustorino.backend.Notifications
+import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
+import org.eclipse.paho.client.mqttv3.*
import org.json.JSONArray
import org.json.JSONException
import java.lang.ref.WeakReference
-import java.util.ArrayList
-import java.util.Properties
+import java.util.*
typealias PositionsMap = HashMap >
-class MQTTMatoClient private constructor(): MqttCallbackExtended{
+class MQTTMatoClient(): MqttCallbackExtended{
private var isStarted = false
private var subscribedToAll = false
@@ -30,14 +32,27 @@
private val currentPositions = PositionsMap()
private lateinit var lifecycle: LifecycleOwner
+ //TODO: remove class reference to context (always require context in all methods)
private var context: Context?= null
private var connectionTrials = 0
+ private var notification: Notification? = null
+
+ //private lateinit var notification: Notification
private fun connect(context: Context, iMqttActionListener: IMqttActionListener?){
val clientID = "mqtt-explorer-${getRandomString(8)}"//"mqttjs_${getRandomString(8)}"
+ //notification = Notifications.makeMQTTServiceNotification(context)
+
client = MqttAndroidClient(context,SERVER_ADDR,clientID,Ack.AUTO_ACK)
+ if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
+ //we need a notification
+ val notific = Notifications.makeMQTTServiceNotification(context)
+ client.setForegroundService(notific)
+ notification=notific
+ }
+
val options = MqttConnectOptions()
//options.sslProperties =
@@ -121,7 +136,7 @@
return true
}
- fun desubscribe(responder: MQTTMatoListener){
+ fun stopMatoRequests(responder: MQTTMatoListener){
var removed = false
for ((line,v)in respondersMap.entries){
var done = false
@@ -143,7 +158,8 @@
}
removed = done || removed
}
- // remove lines that have no responders
+ // check responders map, remove lines that have no responders
+
for(line in respondersMap.keys){
if(respondersMap[line]?.isEmpty() == true){
respondersMap.remove(line)
@@ -155,6 +171,15 @@
return currentPositions
}
+ /**
+ * Cancel the notification
+ */
+ fun removeNotification(context: Context){
+ val notifManager = context.applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+
+ notifManager.cancel(MQTT_NOTIFICATION_ID)
+ }
+
private fun sendUpdateToResponders(responders: ArrayList>): Int{
//var sent = false
var count = 0
@@ -227,9 +252,7 @@
try {
val jsonList = JSONArray(messString)
- //val full = if(jsonList.length()>7) {
- // if (jsonList.get(7).equals(null)) null else jsonList.getInt(7)
- //}else null
+
/*val posUpdate = MQTTPositionUpdate(lineId+"U", vehicleId,
jsonList.getDouble(0),
jsonList.getDouble(1),
@@ -240,7 +263,6 @@
if(jsonList.get(6).equals(null)) null else jsonList.getInt(6),
//full
)
-
*/
if(jsonList.get(4)==null){
Log.d(DEBUG_TAG, "We have null tripId: line $lineId veh $vehicleId: $jsonList")
@@ -309,18 +331,22 @@
//NOT USED (we're not sending any messages)
}
+ /**
+ * Stop the service forever. Client has not to be used again!!
+ */
+ fun closeClientForever(){
+ client.close()
+ }
+
companion object{
const val SERVER_ADDR="wss://mapi.5t.torino.it:443/scre"
const val LINES_ALL="ALL"
private const val DEBUG_TAG="BusTO-MatoMQTT"
- @Volatile
- private var instance: MQTTMatoClient? = null
+ //this has to match the value in MQTT library (MQTTAndroidClient)
+ const val MQTT_NOTIFICATION_ID: Int = 77
- fun getInstance() = instance?: synchronized(this){
- instance?: MQTTMatoClient().also { instance= it }
- }
@JvmStatic
fun mapTopic(lineId: String): String{
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
@@ -91,7 +91,7 @@
.setContentTitle(con.getString(R.string.database_update_msg_notif))
.setProgress(0,0,true)
.setPriority(NotificationCompat.PRIORITY_LOW);
- builder.setSmallIcon(R.drawable.ic_bus_orange);
+ builder.setSmallIcon(R.drawable.ic_bus_stilized);
notificationManager.notify(notification_ID,builder.build());
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
@@ -42,7 +42,7 @@
private val netVolleyManager = NetworkVolleyManager.getInstance(application)
- private var mqttClient = MQTTMatoClient.getInstance()
+ private var mqttClient = MQTTMatoClient()
private var lineListening = ""
private var lastTimeReceived: Long = 0
@@ -155,7 +155,7 @@
fun stopMatoUpdates(){
viewModelScope.launch {
val tt = System.currentTimeMillis()
- mqttClient.desubscribe(matoPositionListener)
+ mqttClient.stopMatoRequests(matoPositionListener)
val time = System.currentTimeMillis() -tt
Log.d(DEBUG_TI, "Took $time ms to unsubscribe")
}
@@ -212,7 +212,14 @@
}
}
+ override fun onCleared() {
+ //stop the MQTT Service
+ Log.d(DEBUG_TI, "Clearing the live positions view model, stopping the mqttClient")
+ mqttClient.closeClientForever()
+ super.onCleared()
+ }
+
companion object{
private const val DEBUG_TI = "BusTO-LivePosViewModel"
}
}
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_bus_stilized.xml b/app/src/main/res/drawable/ic_bus_stilized.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/ic_bus_stilized.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_bus_stilized_transparent.xml b/app/src/main/res/drawable/ic_bus_stilized_transparent.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/ic_bus_stilized_transparent.xml
@@ -0,0 +1,9 @@
+
+
+
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
@@ -131,6 +131,8 @@
Consenti l\'accesso alla posizione per mostrarla sulla mappa
+ Consenti l\'accesso alla posizione per mostrare le fermate vicine
+
Abilitare il GPS
arriva alle
alla fermata
@@ -175,6 +177,8 @@
Canale default delle notifiche
Operazioni sul database
Informazioni sul database (aggiornamento)
+ Servizio posizioni in tempo reale attivo
+
Downloading trips from MaTO server
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,6 +203,7 @@
Default channel for notifications
Database operations
Updates of the app database
+ Bus live positions service is running
Downloading trips from MaTO server