Page MenuHomeGitPull.it

D205.1765090545.diff
No OneTemporary

Size
55 KB
Referenced Files
None
Subscribers
None

D205.1765090545.diff

diff --git a/app/src/main/java/it/reyboz/bustorino/backend/LivePositionsServiceStatus.kt b/app/src/main/java/it/reyboz/bustorino/backend/LivePositionsServiceStatus.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/backend/LivePositionsServiceStatus.kt
@@ -0,0 +1,5 @@
+package it.reyboz.bustorino.backend
+
+enum class LivePositionsServiceStatus {
+ OK,CONNECTING, NO_POSITIONS, ERROR_CONNECTION, ERROR_PARSING_RESPONSE, ERROR_NETWORK_RESPONSE
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt b/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
--- a/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
+++ b/app/src/main/java/it/reyboz/bustorino/backend/gtfs/GtfsRtPositionsRequest.kt
@@ -24,19 +24,23 @@
import com.android.volley.toolbox.HttpHeaderParser
import com.google.transit.realtime.GtfsRealtime
+import it.reyboz.bustorino.backend.Fetcher
class GtfsRtPositionsRequest(
- errorListener: Response.ErrorListener?,
+ errorListener: ErrorListener,
val listener: RequestListener) :
Request<ArrayList<LivePositionUpdate>>(Method.GET, URL_POSITION, errorListener) {
override fun parseNetworkResponse(response: NetworkResponse?): Response<ArrayList<LivePositionUpdate>> {
if (response == null){
- return Response.error(VolleyError("Null response"))
+ return Response.error(RequestError(Fetcher.Result.PARSER_ERROR))
+ }
+ if (response.statusCode == 404){
+ return Response.error(RequestError(Fetcher.Result.SERVER_ERROR_404))
+ }
+ else if (response.statusCode != 200){
+ return Response.error(RequestError(Fetcher.Result.SERVER_ERROR))
}
-
- if (response.statusCode != 200)
- return Response.error(VolleyError("Error code is ${response.statusCode}"))
val gtfsreq = GtfsRealtime.FeedMessage.parseFrom(response.data)
@@ -58,16 +62,22 @@
listener.onResponse(response)
}
+ override fun parseNetworkError(volleyError: VolleyError?): VolleyError? {
+ return super.parseNetworkError(volleyError)
+ }
+
companion object{
const val URL_POSITION = "http://percorsieorari.gtt.to.it/das_gtfsrt/vehicle_position.aspx"
const val URL_TRIP_UPDATES ="http://percorsieorari.gtt.to.it/das_gtfsrt/trip_update.aspx"
const val URL_ALERTS = "http://percorsieorari.gtt.to.it/das_gtfsrt/alerts.aspx"
- public interface RequestListener{
+ interface RequestListener{
fun onResponse(response: ArrayList<LivePositionUpdate>?)
}
+ fun interface ErrorListener: Response.ErrorListener
}
+ class RequestError(val result: Fetcher.Result): VolleyError()
}
\ No newline at end of file
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
@@ -10,6 +10,7 @@
import com.hivemq.client.mqtt.mqtt3.Mqtt3ClientBuilder
import com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish
import it.reyboz.bustorino.BuildConfig
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
import org.json.JSONArray
import org.json.JSONException
@@ -198,7 +199,9 @@
responders.remove(wrD)
}
else {
- wrD.get()!!.onUpdateReceived(currentPositions)
+ val resp = wrD.get()!!
+ resp.onStatusUpdate(LivePositionsServiceStatus.OK)
+ resp.onUpdateReceived(currentPositions)
//sent = true
count++
}
@@ -206,6 +209,22 @@
return count
}
+ private fun sendStatusToResponders(status: LivePositionsServiceStatus){
+ val responders = respondersMap
+ for (els in respondersMap.values)
+ for (wrD in els) {
+
+ if (wrD.get() == null) {
+ Log.d(DEBUG_TAG, "Removing weak reference")
+ els.remove(wrD)
+ }
+ else {
+ wrD.get()!!.onStatusUpdate(status)
+ //sent = true
+ }
+ }
+
+ }
/*override fun connectionLost(cause: Throwable?) {
var doReconnect = false
@@ -280,6 +299,7 @@
if(jsonList.get(4)==null){
Log.d(DEBUG_TAG, "We have null tripId: line $lineId veh $vehicleId: $jsonList")
+ sendStatusToResponders(LivePositionsServiceStatus.NO_POSITIONS)
return
}
val posUpdate = LivePositionUpdate(
@@ -334,9 +354,12 @@
//Log.d(DEBUG_TAG, "We have update on line $lineId, vehicle $vehicleId")
} catch (e: JSONException){
Log.w(DEBUG_TAG,"Cannot decipher message on topic $topic, line $lineId, veh $vehicleId (bad JSON)")
+ sendStatusToResponders(LivePositionsServiceStatus.ERROR_PARSING_RESPONSE)
+
} catch (e: Exception){
Log.e(DEBUG_TAG, "Exception occurred", e)
+ sendStatusToResponders(LivePositionsServiceStatus.ERROR_PARSING_RESPONSE)
}
}
@@ -382,9 +405,11 @@
}
- fun interface MQTTMatoListener{
+ interface MQTTMatoListener{
//positionsMap is a dict with line -> vehicle -> Update
fun onUpdateReceived(posUpdates: PositionsMap)
+
+ fun onStatusUpdate(status: LivePositionsServiceStatus)
}
fun getHTTPHeaders(): HashMap<String,String> {
val headers = HashMap<String,String>()
diff --git a/app/src/main/java/it/reyboz/bustorino/data/MatoRepository.kt b/app/src/main/java/it/reyboz/bustorino/data/MatoRepository.kt
--- a/app/src/main/java/it/reyboz/bustorino/data/MatoRepository.kt
+++ b/app/src/main/java/it/reyboz/bustorino/data/MatoRepository.kt
@@ -20,6 +20,7 @@
import android.content.Context
import android.util.Log
import com.android.volley.Response
+import com.android.volley.toolbox.ClearCacheRequest
import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.Result
import it.reyboz.bustorino.backend.mato.MatoQueries
@@ -50,6 +51,13 @@
))
}
+ fun clearVolleyCache(){
+ val clearReq = ClearCacheRequest(netVolleyManager.requestQueue.cache){
+ Log.d(DEBUG_TAG, "Volley cache is cleared")
+ }
+ netVolleyManager.addToRequestQueue(clearReq)
+ }
+
fun interface Callback<T> {
fun onResultAvailable(result: Result<T>)
}
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
@@ -21,6 +21,7 @@
import android.content.Context
import android.util.Log
import androidx.work.*
+import com.android.volley.toolbox.ClearCacheRequest
import it.reyboz.bustorino.backend.Notifications
import it.reyboz.bustorino.data.gtfs.GtfsTrip
import java.util.concurrent.CountDownLatch
@@ -30,19 +31,20 @@
override suspend fun doWork(): Result {
- return downloadGtfsTrips()
- }
-
- /**
- * Download GTFS Trips from Mato
- */
- private fun downloadGtfsTrips():Result{
val tripsList = inputData.getStringArray(TRIPS_KEYS)
if (tripsList== null){
Log.e(DEBUG_TAG,"trips list given is null")
return Result.failure()
}
+ return downloadGtfsTrips(tripsList!!)
+ }
+
+ /**
+ * Download GTFS Trips from Mato
+ */
+ private fun downloadGtfsTrips(tripsList: Array<String>):Result{
+
val gtfsRepository = GtfsRepository(applicationContext)
val matoRepository = MatoRepository(applicationContext)
//clear the matoTrips
@@ -52,7 +54,7 @@
val failedMatoTripsDownload = HashSet<String>()
- Log.i(DEBUG_TAG, "Requesting download for the trips")
+ Log.i(DEBUG_TAG, "Requesting download for ${tripsList.size} trips")
val requestCountDown = CountDownLatch(tripsList.size);
for(trip in tripsList){
queriedMatoTrips.add(trip)
@@ -82,6 +84,8 @@
}
requestCountDown.await()
val tripsIDsCompleted = downloadedMatoTrips.map { trip-> trip.tripID }
+ //clear cache to avoid tripping memory
+ matoRepository.clearVolleyCache()
if (tripsIDsCompleted.isEmpty()){
Log.d(DEBUG_TAG, "No trips have been downloaded, set work to fail")
return Result.failure()
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
@@ -40,6 +40,7 @@
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
@@ -244,7 +245,7 @@
private val tripMarkersAnimators = HashMap<String, ObjectAnimator>()
- private val liveBusViewModel: LivePositionsViewModel by viewModels()
+ private val liveBusViewModel: LivePositionsViewModel by activityViewModels()
//extra items to use the LibreMap
private lateinit var symbolManager : SymbolManager
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/LivePositionsDialogFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/LivePositionsDialogFragment.kt
new file mode 100644
--- /dev/null
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/LivePositionsDialogFragment.kt
@@ -0,0 +1,87 @@
+package it.reyboz.bustorino.fragments
+
+import it.reyboz.bustorino.R
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.Button
+import android.widget.ImageButton
+import android.widget.TextView
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import androidx.fragment.app.activityViewModels
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
+import it.reyboz.bustorino.viewmodels.LivePositionsViewModel
+
+class LivePositionsDialogFragment : DialogFragment() {
+ private val viewModel: LivePositionsViewModel by activityViewModels()
+ private lateinit var providerNameTextView: TextView
+ private lateinit var statusMessageTextView: TextView
+
+
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ //return super.onCreateDialog(savedInstanceState)
+ val builder = AlertDialog.Builder(requireContext())
+ val view = layoutInflater.inflate(R.layout.fragment_dialog_buspositions, null)
+
+ providerNameTextView = view.findViewById<TextView>(R.id.providerNameTextView)
+ statusMessageTextView = view.findViewById<TextView>(R.id.statusMessageTextView)
+ val btnSwitch = view.findViewById<Button>(R.id.btnSwitch)
+ val btnClose = view.findViewById<ImageButton>(R.id.btnClose)
+
+ // OBSERVE VIEWMODEL
+ /*sharedViewModel.variableTitle.observe(this) {
+ tvTitleVariable.text = it
+ }
+
+ sharedViewModel.statusMessage.observe(this) {
+ tvStatusMessage.text = it
+ }
+
+
+
+ */
+
+ btnSwitch.setOnClickListener {
+ viewModel.switchPositionsSource()
+ }
+
+ btnClose.setOnClickListener { dismiss() }
+
+ builder.setView(view)
+ val res = builder.create()
+ res.window?.setBackgroundDrawableResource(R.color.grey_100)
+ return res
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?
+ ): View? {
+
+ viewModel.serviceStatus.observe(this) { serviceStatus ->
+ val message = when (serviceStatus) {
+ LivePositionsServiceStatus.OK -> getString(R.string.live_positions_msg_ok)
+ LivePositionsServiceStatus.NO_POSITIONS -> getString(R.string.live_positions_msg_no_positions)
+ LivePositionsServiceStatus.ERROR_CONNECTION -> getString(R.string.live_positions_msg_connection_error)
+ LivePositionsServiceStatus.ERROR_NETWORK_RESPONSE -> getString(R.string.live_positions_msg_network_error)
+ LivePositionsServiceStatus.ERROR_PARSING_RESPONSE -> getString(R.string.live_positions_msg_parsing_error)
+ LivePositionsServiceStatus.CONNECTING -> getString(R.string.live_positions_msg_connecting)
+
+ }
+ statusMessageTextView.text = message
+ }
+ viewModel.useMQTTPositionsLiveData.observe(this) { useMQTT ->
+ val message = if (useMQTT) {
+ getString(R.string.positions_source_mato_short)
+ } else getString(R.string.positions_source_gtfsrt_short)
+ providerNameTextView.text = message
+ }
+
+ return super.onCreateView(inflater, container, savedInstanceState)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/MapLibreFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/MapLibreFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/MapLibreFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/MapLibreFragment.kt
@@ -27,17 +27,17 @@
import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat
import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
-import androidx.preference.PreferenceManager
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.gson.JsonObject
import it.reyboz.bustorino.R
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
import it.reyboz.bustorino.backend.Stop
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
import it.reyboz.bustorino.backend.mato.MQTTMatoClient
import it.reyboz.bustorino.data.PreferencesHolder
import it.reyboz.bustorino.data.gtfs.TripAndPatternWithStops
-import it.reyboz.bustorino.fragments.SettingsFragment.LIVE_POSITIONS_PREF_MQTT_VALUE
import it.reyboz.bustorino.map.MapLibreUtils
import it.reyboz.bustorino.map.MapLibreStyles
import it.reyboz.bustorino.util.Permissions
@@ -163,8 +163,9 @@
})
//BUS POSITIONS
- private var useMQTTViewModel = true
- private val livePositionsViewModel : LivePositionsViewModel by viewModels()
+ private var usingMQTTPositions = true // THIS IS INSIDE VIEW MODEL NOW
+ private val livePositionsViewModel : LivePositionsViewModel by activityViewModels()
+ private lateinit var busPositionsIconButton: ImageButton
private val positionsByVehDict = HashMap<String, LivePositionUpdate>(5)
private val animatorsByVeh = HashMap<String, ValueAnimator>()
@@ -226,6 +227,10 @@
showUserPositionButton.setOnClickListener(this::switchUserLocationStatus)
followUserButton = rootView.findViewById(R.id.followUserImageButton)
centerUserButton = rootView.findViewById(R.id.centerMapImageButton)
+ busPositionsIconButton = rootView.findViewById(R.id.busPositionsImageButton)
+ busPositionsIconButton.setOnClickListener {
+ LivePositionsDialogFragment().show(parentFragmentManager, "LivePositionsDialog")
+ }
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheet)
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
@@ -273,6 +278,34 @@
rootView.findViewById<View>(R.id.btnClose).setOnClickListener {
hideStopBottomSheet()
}
+ livePositionsViewModel.serviceStatus.observe(viewLifecycleOwner){ status ->
+ //if service is active, update the bus positions icon
+ when(status) {
+ LivePositionsServiceStatus.OK ->
+ setBusPositionsIcon(true, error = false)
+
+ LivePositionsServiceStatus.NO_POSITIONS -> setBusPositionsIcon(true, error = true)
+
+ else -> setBusPositionsIcon(true, error = true)
+ }
+ }
+ livePositionsViewModel.useMQTTPositionsLiveData.observe(viewLifecycleOwner){ useMQTT->
+ if (showBusLayer && isResumed) {
+ if(useMQTT!=usingMQTTPositions){
+ // we have to switch
+ if(useMQTT){
+ //switching to MQTT, the GTFS positions are disabled automatically
+ livePositionsViewModel.requestMatoPosUpdates(MQTTMatoClient.LINES_ALL)
+ } else{
+ //switching to GTFS RT: stop Mato, launch first request
+ livePositionsViewModel.stopMatoUpdates()
+ livePositionsViewModel.requestGTFSUpdates()
+ }
+ }
+ }
+ usingMQTTPositions = useMQTT
+
+ }
Log.d(DEBUG_TAG, "Fragment View Created!")
@@ -342,7 +375,7 @@
mapInitCompleted = true
// we start requesting the bus positions now
- startRequestingPositions()
+ observeBusPositionUpdates()
//Restoring data
var boundsRestored = false
@@ -584,14 +617,17 @@
super.onResume()
mapView.onResume()
- val keySourcePositions = getString(R.string.pref_positions_source)
+ //val keySourcePositions = getString(R.string.pref_positions_source)
if(showBusLayer) {
- useMQTTViewModel = PreferenceManager.getDefaultSharedPreferences(requireContext())
- .getString(keySourcePositions, LIVE_POSITIONS_PREF_MQTT_VALUE)
- .contentEquals(LIVE_POSITIONS_PREF_MQTT_VALUE)
- if (useMQTTViewModel) livePositionsViewModel.requestMatoPosUpdates(MQTTMatoClient.LINES_ALL)
- else livePositionsViewModel.requestGTFSUpdates()
+ if (livePositionsViewModel.useMQTTPositionsLiveData.value!!){
+ livePositionsViewModel.requestMatoPosUpdates(MQTTMatoClient.LINES_ALL)
+ usingMQTTPositions = true
+ }
+ else {
+ livePositionsViewModel.requestGTFSUpdates()
+ usingMQTTPositions = false
+ }
//mapViewModel.testCascade();
livePositionsViewModel.isLastWorkResultGood.observe(this) { d: Boolean ->
Log.d(
@@ -615,7 +651,7 @@
Log.d(DEBUG_TAG, "Fragment paused")
savedMapStateOnPause = saveMapStateInBundle()
- if (useMQTTViewModel) livePositionsViewModel.stopMatoUpdates()
+ if (livePositionsViewModel.useMQTTPositionsLiveData.value!!) livePositionsViewModel.stopMatoUpdates()
}
@@ -736,14 +772,14 @@
/**
* Start requesting position updates
*/
- private fun startRequestingPositions() {
+ private fun observeBusPositionUpdates() {
livePositionsViewModel.updatesWithTripAndPatterns.observe(viewLifecycleOwner) { data: HashMap<String, Pair<LivePositionUpdate, TripAndPatternWithStops?>> ->
Log.d(
DEBUG_TAG,
"Have " + data.size + " trip updates, has Map start finished: " + mapInitCompleted
)
if (mapInitCompleted) updateBusPositionsInMap(data)
- if (!isDetached && !useMQTTViewModel) livePositionsViewModel.requestDelayedGTFSUpdates(
+ if (!isDetached && !livePositionsViewModel.useMQTTPositionsLiveData.value!!) livePositionsViewModel.requestDelayedGTFSUpdates(
3000
)
}
@@ -1054,6 +1090,7 @@
setLocationIconEnabled(true)
if (fromClick) Toast.makeText(context, R.string.location_enabled, Toast.LENGTH_SHORT).show()
pendingLocationActivation =false
+ //locationComponent.locationEngine.requestLocationUpdates()
} else {
if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION)) {
//TODO: show dialog for permission rationale
@@ -1087,6 +1124,17 @@
/**
* Helper method for GUI
*/
+ private fun setBusPositionsIcon(enabled: Boolean, error: Boolean){
+ val ctx = requireContext()
+ if(!enabled)
+ busPositionsIconButton.setImageDrawable(ContextCompat.getDrawable(ctx, R.drawable.bus_pos_circle_inactive))
+ else if(error)
+ busPositionsIconButton.setImageDrawable(ContextCompat.getDrawable(ctx, R.drawable.bus_pos_circle_notworking))
+ else
+ busPositionsIconButton.setImageDrawable(ContextCompat.getDrawable(ctx, R.drawable.bus_pos_circle_active))
+
+ }
+
private fun updateFollowingIcon(enabled: Boolean){
if(enabled)
followUserButton.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.walk_circle_active))
diff --git a/app/src/main/java/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt b/app/src/main/java/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt
--- a/app/src/main/java/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt
+++ b/app/src/main/java/it/reyboz/bustorino/fragments/TestRealtimeGtfsFragment.kt
@@ -11,7 +11,9 @@
import android.widget.TextView
import androidx.fragment.app.viewModels
import it.reyboz.bustorino.R
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
import it.reyboz.bustorino.backend.mato.MQTTMatoClient
+import it.reyboz.bustorino.backend.mato.PositionsMap
import it.reyboz.bustorino.viewmodels.LivePositionsViewModel
@@ -49,10 +51,16 @@
}
*/
- private val listener = MQTTMatoClient.Companion.MQTTMatoListener{
+ private val listener = object : MQTTMatoClient.Companion.MQTTMatoListener{
+ override fun onUpdateReceived(it: PositionsMap) {
+ messageTextView.text = "Update: ${it}"
+ Log.d("BUSTO-TestMQTT", "Received update $it") }
+
+ override fun onStatusUpdate(status: LivePositionsServiceStatus) {
+ Log.d(DEBUG_TAG, "Status changed into $status")
+ }
+
- messageTextView.text = "Update: ${it}"
- Log.d("BUSTO-TestMQTT", "Received update $it")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -120,5 +128,7 @@
fun newInstance() =
TestRealtimeGtfsFragment().apply {
}
+
+ private const val DEBUG_TAG = "BusTO-TestGTFSRTPos"
}
}
\ No newline at end of file
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
@@ -22,6 +22,8 @@
import androidx.lifecycle.*
import androidx.work.OneTimeWorkRequest
import com.android.volley.Response
+import it.reyboz.bustorino.backend.Fetcher
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
import it.reyboz.bustorino.backend.gtfs.GtfsRtPositionsRequest
@@ -62,10 +64,13 @@
}
}
- private val positionRequestErrorListener = Response.ErrorListener {
- Log.e(DEBUG_TI, "Could not download the update, error:\n"+it.stackTrace)
- }
+ /**
+ * Listener for the errors in downloading positions from GTFS RT
+ */
+ private val positionRequestErrorListener = GtfsRtPositionsRequest.Companion.ErrorListener {
+ Log.e(DEBUG_TI, "Could not download the update", it)
+ }
fun requestUpdates(){
if(positionsRequestRunning.value == null || !positionsRequestRunning.value!!) {
val request = GtfsRtPositionsRequest(positionRequestErrorListener, positionRequestListener)
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,15 +20,19 @@
import android.app.Application
import android.util.Log
import androidx.lifecycle.*
+import androidx.preference.PreferenceManager
import androidx.work.WorkInfo
import androidx.work.WorkManager
import com.android.volley.DefaultRetryPolicy
-import com.android.volley.Response
+import it.reyboz.bustorino.R
+import it.reyboz.bustorino.backend.Fetcher
+import it.reyboz.bustorino.backend.LivePositionsServiceStatus
import it.reyboz.bustorino.backend.NetworkVolleyManager
import it.reyboz.bustorino.backend.gtfs.GtfsRtPositionsRequest
import it.reyboz.bustorino.backend.gtfs.GtfsUtils
import it.reyboz.bustorino.backend.gtfs.LivePositionUpdate
import it.reyboz.bustorino.backend.mato.MQTTMatoClient
+import it.reyboz.bustorino.backend.mato.PositionsMap
import it.reyboz.bustorino.data.GtfsRepository
import it.reyboz.bustorino.data.MatoPatternsDownloadWorker
import it.reyboz.bustorino.data.MatoTripsDownloadWorker
@@ -68,6 +72,41 @@
//INPUT FILTER FOR LINE
private var gtfsLineToFilterPos = MutableLiveData<Pair<String,MatoPattern?>>()
+ var serviceStatus = MutableLiveData(LivePositionsServiceStatus.CONNECTING)
+
+ private val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(application)
+ private val keySourcePositions = application.getString(R.string.pref_positions_source)
+ val useMQTTPositionsLiveData: MutableLiveData<Boolean> = MutableLiveData(isMQTTPositionsSelected())//= MutableLiveData(false)
+
+ init {
+ sharedPrefs.registerOnSharedPreferenceChangeListener { shp, key ->
+ if(key == keySourcePositions) {
+ val newV = shp.getString(keySourcePositions, LIVE_POS_PREF_MQTT)
+ useMQTTPositionsLiveData.postValue(newV.contentEquals(LIVE_POS_PREF_MQTT))
+ Log.d(DEBUG_TI, "Changed position source to: $newV")
+ }
+
+ }
+ }
+ private val LIVE_POS_PREF_MQTT = application.getString(R.string.positions_source_mqtt)
+ private val LIVE_POS_PREF_GTFSRT = application.getString(R.string.positions_source_gtfsrt)
+ private fun isMQTTPositionsSelected(): Boolean{
+ return sharedPrefs.getString(keySourcePositions, LIVE_POS_PREF_MQTT)
+ .contentEquals(LIVE_POS_PREF_MQTT)
+ }
+
+ /**
+ * Switch provider of live positions from MQTT to GTFSRT and viceversa
+ */
+ fun switchPositionsSource(){
+ val usingMQTT = useMQTTPositionsLiveData.value!!
+ useMQTTPositionsLiveData.value = !usingMQTT
+ sharedPrefs.edit().putString(keySourcePositions,
+ if(usingMQTT) LIVE_POS_PREF_GTFSRT else LIVE_POS_PREF_MQTT
+ ).apply()
+ Log.d(DEBUG_TI, "Switched positions source in ViewModel")
+ serviceStatus.value = LivePositionsServiceStatus.CONNECTING
+ }
fun setGtfsLineToFilterPos(line: String, pattern: MatoPattern?){
gtfsLineToFilterPos.value = Pair(line, pattern)
}
@@ -91,27 +130,35 @@
/**
* Responder to the MQTT Client
*/
- private val matoPositionListener = MQTTMatoClient.Companion.MQTTMatoListener{
-
- val mupds = ArrayList<LivePositionUpdate>()
- if(lineListening==MQTTMatoClient.LINES_ALL){
- for(sdic in it.values){
- for(update in sdic.values){
- mupds.add(update)
+ private val matoPositionListener = object: MQTTMatoClient.Companion.MQTTMatoListener{
+
+ override fun onUpdateReceived(it: PositionsMap) {
+ val mupds = ArrayList<LivePositionUpdate>()
+ if(lineListening==MQTTMatoClient.LINES_ALL){
+ for(sdic in it.values){
+ for(update in sdic.values){
+ mupds.add(update)
+ }
}
- }
- } else{
- //we're listening to one
- if (it.containsKey(lineListening.trim()) ){
- for(up in it[lineListening]?.values!!){
- mupds.add(up)
+ } else{
+ //we're listening to one
+ if (it.containsKey(lineListening.trim()) ){
+ for(up in it[lineListening]?.values!!){
+ mupds.add(up)
+ }
}
}
+ val time = System.currentTimeMillis()
+ if(lastTimeReceived == (0.toLong()) || (time-lastTimeReceived)>500){
+ positionsToBeMatchedLiveData.postValue(mupds)
+ lastTimeReceived = time
+ }
+ //we have received an update, so set the status to OK
+ serviceStatus.postValue(LivePositionsServiceStatus.OK)
}
- val time = System.currentTimeMillis()
- if(lastTimeReceived == (0.toLong()) || (time-lastTimeReceived)>500){
- positionsToBeMatchedLiveData.postValue(mupds)
- lastTimeReceived = time
+
+ override fun onStatusUpdate(status: LivePositionsServiceStatus) {
+ serviceStatus.postValue(status)
}
}
@@ -267,25 +314,44 @@
private val gtfsPositionsReqListener = object: GtfsRtPositionsRequest.Companion.RequestListener{
override fun onResponse(response: ArrayList<LivePositionUpdate>?) {
Log.i(DEBUG_TI,"Got response from the GTFS RT server")
- response?.let {it:ArrayList<LivePositionUpdate> ->
+ if (response == null){
+ serviceStatus.postValue(LivePositionsServiceStatus.ERROR_CONNECTION)
+ }
+ else response.let { it:ArrayList<LivePositionUpdate> ->
+ val ss: LivePositionsServiceStatus
if (it.size == 0) {
Log.w(DEBUG_TI,"No position updates from the GTFS RT server")
- return
- }
- else {
+ ss = LivePositionsServiceStatus.NO_POSITIONS
+ } else {
//Log.i(DEBUG_TI, "Posting value to positionsLiveData")
viewModelScope.launch { positionsToBeMatchedLiveData.postValue(it) }
-
+ ss = LivePositionsServiceStatus.OK
}
+ serviceStatus.postValue(ss)
}
gtfsRtRequestRunning.postValue(false)
-
}
}
- private val positionRequestErrorListener = Response.ErrorListener {
+
+ /**
+ * Listener for the errors in downloading positions from GTFS RT
+ */
+ private val positionRequestErrorListener = GtfsRtPositionsRequest.Companion.ErrorListener {
Log.e(DEBUG_TI, "Could not download the update", it)
gtfsRtRequestRunning.postValue(false)
+ if(it is GtfsRtPositionsRequest.RequestError){
+ val status = when(it.result) {
+ Fetcher.Result.OK -> LivePositionsServiceStatus.OK
+ Fetcher.Result.PARSER_ERROR -> LivePositionsServiceStatus.ERROR_PARSING_RESPONSE
+ Fetcher.Result.SERVER_ERROR_404 -> LivePositionsServiceStatus.ERROR_NETWORK_RESPONSE
+ Fetcher.Result.SERVER_ERROR -> LivePositionsServiceStatus.ERROR_NETWORK_RESPONSE
+ Fetcher.Result.CONNECTION_ERROR -> LivePositionsServiceStatus.ERROR_CONNECTION
+ else -> LivePositionsServiceStatus.ERROR_CONNECTION
+ }
+ serviceStatus.postValue(status)
+ } else
+ serviceStatus.postValue(LivePositionsServiceStatus.ERROR_NETWORK_RESPONSE)
}
fun requestGTFSUpdates(){
diff --git a/app/src/main/res/drawable/bus_pos_circle_active.xml b/app/src/main/res/drawable/bus_pos_circle_active.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/bus_pos_circle_active.xml
@@ -0,0 +1,20 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/map_toolbar_icon_size"
+ android:height="@dimen/map_toolbar_icon_size"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M0.449,24.048a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1"
+ android:fillColor="@color/map_icon_background_active"
+ android:fillAlpha="0.8"
+ android:strokeColor="#222222"/>
+ <path
+ android:pathData="m32.3,7.3c4.418,0 8,3.582 8,8 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8zM32.3,16.485c-0.873,0 -1.672,0.314 -2.291,0.836L29.786,17.527 32.3,20.041 34.812,17.525C34.169,16.882 33.281,16.485 32.3,16.485ZM32.3,11.744c-2.139,0 -4.089,0.81 -5.56,2.139l-0.308,0.293 1.678,1.674c1.072,-1.072 2.554,-1.736 4.19,-1.736 1.5,0 2.87,0.557 3.914,1.476l0.277,0.259 1.676,-1.676C36.665,12.673 34.591,11.744 32.3,11.744Z"
+ android:strokeWidth="1.778"
+ android:fillColor="#222222"/>
+ <path
+ android:pathData="M23.263,11.464L23.263,14.414L12.939,14.414l0,13.273l20.647,0l0,-2.95l2.95,0l0,11.798l-1.475,0l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475l-1.475,0c-0.815,0 -1.475,-0.66 -1.475,-1.475L30.637,36.536L15.889,36.536l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475L12.939,39.485C12.125,39.485 11.464,38.825 11.464,38.01L11.464,36.536L9.99,36.536L9.99,24.737L8.515,24.737L8.515,18.838L9.99,18.838L9.99,14.414C9.99,12.785 11.31,11.464 12.939,11.464ZM18.838,30.637L12.939,30.637l0,2.95l5.899,0zM33.586,30.637l-5.899,0l0,2.95l5.899,0z"
+ android:fillColor="#222222"/>
+</vector>
diff --git a/app/src/main/res/drawable/bus_pos_circle_inactive.xml b/app/src/main/res/drawable/bus_pos_circle_inactive.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/bus_pos_circle_inactive.xml
@@ -0,0 +1,20 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/map_toolbar_icon_size"
+ android:height="@dimen/map_toolbar_icon_size"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M0.449,24.048a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1"
+ android:fillColor="@color/map_icon_background_inactive"
+ android:fillAlpha="0.75"
+ android:strokeColor="#222222"/>
+ <path
+ android:pathData="m32.3,7.3c4.418,0 8,3.582 8,8 0,4.418 -3.582,8 -8,8 -4.418,0 -8,-3.582 -8,-8 0,-4.418 3.582,-8 8,-8zM32.3,16.485c-0.873,0 -1.672,0.314 -2.291,0.836L29.786,17.527 32.3,20.041 34.812,17.525C34.169,16.882 33.281,16.485 32.3,16.485ZM32.3,11.744c-2.139,0 -4.089,0.81 -5.56,2.139l-0.308,0.293 1.678,1.674c1.072,-1.072 2.554,-1.736 4.19,-1.736 1.5,0 2.87,0.557 3.914,1.476l0.277,0.259 1.676,-1.676C36.665,12.673 34.591,11.744 32.3,11.744Z"
+ android:strokeWidth="1.778"
+ android:fillColor="#222222"/>
+ <path
+ android:pathData="M23.263,11.464L23.263,14.414L12.939,14.414l0,13.273l20.647,0l0,-2.95l2.95,0l0,11.798l-1.475,0l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475l-1.475,0c-0.815,0 -1.475,-0.66 -1.475,-1.475L30.637,36.536L15.889,36.536l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475L12.939,39.485C12.125,39.485 11.464,38.825 11.464,38.01L11.464,36.536L9.99,36.536L9.99,24.737L8.515,24.737L8.515,18.838L9.99,18.838L9.99,14.414C9.99,12.785 11.31,11.464 12.939,11.464ZM18.838,30.637L12.939,30.637l0,2.95l5.899,0zM33.586,30.637l-5.899,0l0,2.95l5.899,0z"
+ android:fillColor="#222222"/>
+</vector>
diff --git a/app/src/main/res/drawable/bus_pos_circle_notworking.xml b/app/src/main/res/drawable/bus_pos_circle_notworking.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/drawable/bus_pos_circle_notworking.xml
@@ -0,0 +1,19 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="@dimen/map_toolbar_icon_size"
+ android:height="@dimen/map_toolbar_icon_size"
+ android:viewportWidth="48"
+ android:viewportHeight="48">
+ <path
+ android:pathData="M0.495,24a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z"
+ android:strokeLineJoin="round"
+ android:strokeWidth="1"
+ android:fillColor="@color/map_icon_background_active"
+ android:strokeColor="#222"
+ android:fillAlpha="0.715968"/>
+ <path
+ android:pathData="M23.309,11.417L23.309,14.366L12.985,14.366l0,13.273l20.647,0l0,-2.95l2.95,0l0,11.798l-1.475,0l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475l-1.475,0c-0.815,0 -1.475,-0.66 -1.475,-1.475L30.683,36.488L15.935,36.488l0,1.475c0,0.815 -0.66,1.475 -1.475,1.475L12.985,39.437C12.171,39.437 11.511,38.777 11.511,37.963L11.511,36.488L10.036,36.488L10.036,24.69L8.561,24.69L8.561,18.79L10.036,18.79L10.036,14.366C10.036,12.737 11.356,11.417 12.985,11.417ZM18.884,30.589L12.985,30.589l0,2.95l5.899,0zM33.632,30.589l-5.899,0l0,2.95l5.899,0z"
+ android:fillColor="#222"/>
+ <path
+ android:pathData="M33.296,23.052C28.74,23.052 25.046,19.359 25.046,14.802 25.046,10.246 28.74,6.552 33.296,6.552c4.556,0 8.25,3.694 8.25,8.25 0,4.556 -3.694,8.25 -8.25,8.25zM32.171,17.277l0,1.65l2.25,0l0,-1.65zM32.171,10.377l0,5.15l2.25,0L34.421,10.377Z"
+ android:fillColor="#222"/>
+</vector>
diff --git a/app/src/main/res/drawable/crosshair_circle_grey.xml b/app/src/main/res/drawable/crosshair_circle_grey.xml
--- a/app/src/main/res/drawable/crosshair_circle_grey.xml
+++ b/app/src/main/res/drawable/crosshair_circle_grey.xml
@@ -2,7 +2,7 @@
android:height="@dimen/map_toolbar_icon_size" android:viewportHeight="48"
android:viewportWidth="48" android:width="@dimen/map_toolbar_icon_size">
- <path android:fillAlpha="0.65" android:fillColor="#c6c6c6" android:pathData="M0.449,24.048a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z" android:strokeColor="#333333" android:strokeLineJoin="round" android:strokeWidth="1.4"/>
+ <path android:fillAlpha="0.75" android:fillColor="#c8c8c8" android:pathData="M0.449,24.048a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z" android:strokeColor="#333333" android:strokeLineJoin="round" android:strokeWidth="1.4"/>
<path android:fillColor="#282828" android:pathData="M22.364,12.661C17.347,13.379 13.379,17.347 12.661,22.364L15.818,22.364l0,3.273L12.661,25.636C13.379,30.653 17.347,34.621 22.364,35.339L22.364,32.182l3.273,0l0,3.157C30.653,34.621 34.621,30.653 35.339,25.636L32.182,25.636l0,-3.273l3.157,0C34.621,17.347 30.653,13.379 25.636,12.661L25.636,15.818L22.364,15.818ZM9.363,22.364C10.117,15.537 15.537,10.117 22.364,9.363L22.364,6l3.273,0L25.636,9.363C32.463,10.117 37.883,15.537 38.637,22.364L42,22.364l0,3.273L38.637,25.636C37.883,32.463 32.463,37.883 25.636,38.637L25.636,42L22.364,42L22.364,38.637C15.537,37.883 10.117,32.463 9.363,25.636L6,25.636L6,22.364ZM27.273,24c0,1.808 -1.465,3.273 -3.273,3.273 -1.808,0 -3.273,-1.465 -3.273,-3.273 0,-1.808 1.465,-3.273 3.273,-3.273 1.808,0 3.273,1.465 3.273,3.273z"/>
diff --git a/app/src/main/res/drawable/location_circlew_grey.xml b/app/src/main/res/drawable/location_circlew_grey.xml
--- a/app/src/main/res/drawable/location_circlew_grey.xml
+++ b/app/src/main/res/drawable/location_circlew_grey.xml
@@ -4,7 +4,7 @@
android:viewportWidth="48"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillAlpha="0.6"
- android:fillColor="#c6c6c6"
+ android:fillColor="#c8c8c8"
android:pathData="M24.064,23.98m-23.21,0a23.21,23.21 0,1 1,46.42 0a23.21,23.21 0,1 1,-46.42 0"
android:strokeColor="#333333" android:strokeLineJoin="round"
android:strokeWidth="1.4"/>
diff --git a/app/src/main/res/drawable/location_circlew_red.xml b/app/src/main/res/drawable/location_circlew_red.xml
--- a/app/src/main/res/drawable/location_circlew_red.xml
+++ b/app/src/main/res/drawable/location_circlew_red.xml
@@ -4,9 +4,9 @@
android:viewportWidth="48"
xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillAlpha="0.75"
- android:fillColor="#f15000"
+ android:fillColor="@color/map_icon_background_active"
android:pathData="M24.064,23.98m-23.21,0a23.21,23.21 0,1 1,46.42 0a23.21,23.21 0,1 1,-46.42 0"
- android:strokeColor="#333333" android:strokeLineJoin="round"
+ android:strokeColor="#222222" android:strokeLineJoin="round"
android:strokeWidth="1.4"/>
<path android:fillColor="#333333"
android:fillType="evenOdd" android:pathData="m23.424,43.817c0,0 0.001,0 0.576,-0.817zM24.576,43.817 L24.58,43.815 24.589,43.808 24.621,43.785c0.027,-0.02 0.067,-0.048 0.117,-0.085 0.101,-0.074 0.246,-0.183 0.43,-0.324 0.368,-0.283 0.889,-0.697 1.513,-1.231 1.247,-1.066 2.91,-2.613 4.575,-4.54C34.564,33.78 38,28.319 38,22.077 38,18.345 36.526,14.766 33.902,12.125 31.277,9.485 27.715,8 24,8 20.285,8 16.723,9.485 14.098,12.125 11.474,14.766 10,18.345 10,22.077c0,6.243 3.436,11.703 6.744,15.529 1.666,1.927 3.329,3.474 4.575,4.54 0.624,0.534 1.145,0.948 1.513,1.231 0.184,0.141 0.329,0.25 0.43,0.324 0.05,0.037 0.09,0.065 0.117,0.085l0.032,0.023 0.009,0.006 0.004,0.003c0.345,0.243 0.808,0.243 1.153,0zM24,43 L24.576,43.817C24.576,43.817 24.576,43.818 24,43ZM29,22c0,2.761 -2.239,5 -5,5 -2.761,0 -5,-2.239 -5,-5 0,-2.761 2.239,-5 5,-5 2.761,0 5,2.239 5,5z"/>
diff --git a/app/src/main/res/drawable/walk_circle_active.xml b/app/src/main/res/drawable/walk_circle_active.xml
--- a/app/src/main/res/drawable/walk_circle_active.xml
+++ b/app/src/main/res/drawable/walk_circle_active.xml
@@ -1,7 +1,7 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true"
android:height="@dimen/map_toolbar_icon_size" android:width="@dimen/map_toolbar_icon_size" android:viewportHeight="48" android:viewportWidth="48" >
- <path android:fillAlpha="0.75" android:fillColor="#f15000" android:pathData="M24.064,23.98m-23.21,0a23.21,23.21 0,1 1,46.42 0a23.21,23.21 0,1 1,-46.42 0"
+ <path android:fillAlpha="0.75" android:fillColor="@color/map_icon_background_active" android:pathData="M24.064,23.98m-23.21,0a23.21,23.21 0,1 1,46.42 0a23.21,23.21 0,1 1,-46.42 0"
android:strokeColor="#333333" android:strokeLineJoin="round" android:strokeWidth="1.4"/>
<path android:fillColor="#333" android:pathData="m16.428,18.116 l5.384,-3.912c0.591,-0.431 1.321,-0.669 2.088,-0.643 1.867,0.046 3.507,1.27 4.077,3.057 0.313,0.981 0.598,1.643 0.856,1.986C30.366,20.641 32.804,21.959 35.55,21.959l0,3.36c-3.653,0 -6.917,-1.666 -9.074,-4.279l-1.172,6.645 3.462,2.905 3.735,10.261L29.344,42 25.917,32.585 20.222,27.806C19.302,27.063 18.804,25.855 19.024,24.608L19.878,19.762 18.741,20.588 15.168,25.506 12.45,23.531 16.399,18.095ZM26.311,12.72c-1.856,0 -3.36,-1.504 -3.36,-3.36 0,-1.856 1.504,-3.36 3.36,-3.36 1.855,0 3.36,1.504 3.36,3.36 0,1.856 -1.504,3.36 -3.36,3.36zM21.319,34.863 L15.92,41.297 13.346,39.137 18.344,33.181 19.598,29.518 22.607,32.038Z"/>
diff --git a/app/src/main/res/drawable/walk_circle_inactive.xml b/app/src/main/res/drawable/walk_circle_inactive.xml
--- a/app/src/main/res/drawable/walk_circle_inactive.xml
+++ b/app/src/main/res/drawable/walk_circle_inactive.xml
@@ -3,8 +3,8 @@
android:height="@dimen/map_toolbar_icon_size" android:width="@dimen/map_toolbar_icon_size"
android:viewportHeight="48" android:viewportWidth="48" >
- <path android:fillAlpha="0.65"
- android:fillColor="#c6c6c6"
+ <path android:fillAlpha="0.75"
+ android:fillColor="@color/map_icon_background_inactive"
android:pathData="M0.449,24.048a23.505,23.505 0,1 0,47.009 0a23.505,23.505 0,1 0,-47.009 0z" android:strokeColor="#333333" android:strokeLineJoin="round"
android:strokeWidth="1.4"/>
diff --git a/app/src/main/res/layout/fragment_dialog_buspositions.xml b/app/src/main/res/layout/fragment_dialog_buspositions.xml
new file mode 100644
--- /dev/null
+++ b/app/src/main/res/layout/fragment_dialog_buspositions.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="15dp"
+ android:orientation="vertical">
+
+
+ <!-- Label fissa (SX) -->
+ <TextView
+ android:id="@+id/tvTitleFixed"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/live_positions_dialog_provider_text"
+ android:textStyle="bold"
+ android:textSize="18sp"
+ android:fontFamily="@font/lato_bold"
+ android:textColor="@color/black_900"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <!-- Label variabile (DX) -->
+ <TextView
+ android:id="@+id/providerNameTextView"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Valore"
+ android:textSize="18sp"
+ app:layout_constraintTop_toTopOf="@+id/tvTitleFixed"
+ app:layout_constraintStart_toEndOf="@id/tvTitleFixed"
+ app:layout_constraintBottom_toTopOf="@id/statusCard"
+ android:layout_marginBottom="8dp"
+ android:layout_marginStart="6dp"
+ android:textColor="@color/black"
+ android:fontFamily="@font/lato_regular"
+ android:textAppearance="@style/TextAppearance.AppCompat.Display3"/>
+
+
+ <!-- BOX del messaggio di stato -->
+ <androidx.cardview.widget.CardView
+ android:id="@+id/statusCard"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="20dp"
+ app:layout_constraintTop_toBottomOf="@+id/providerNameTextView"
+ app:layout_constraintBottom_toTopOf="@id/btnSwitch"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+
+ android:padding="12dp"
+ app:cardCornerRadius="12dp"
+ app:cardElevation="1dp"
+ app:strokeWidth="1dp"
+ android:layout_marginBottom="16dp"
+ android:backgroundTint="@color/grey_200"
+ app:strokeColor="@color/grey_050">
+
+ <TextView
+ android:id="@+id/statusMessageTextView"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="Messaggio di stato..."
+ android:fontFamily="@font/lato_regular"
+ android:textSize="16sp"
+ android:textColor="@color/black"
+ android:padding="8dp"
+ android:textAppearance="@style/TextAppearance.AppCompat.Medium"/>
+
+ </androidx.cardview.widget.CardView>
+
+ <!-- Pulsanti -->
+
+
+ <Button
+ android:id="@+id/btnSwitch"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ app:layout_constraintTop_toBottomOf="@+id/statusCard"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ android:backgroundTint="?colorPrimaryDark"
+ android:textColor="@color/white"
+ android:text="@string/live_positions_switch_provider" />
+
+ <ImageButton
+ android:id="@+id/btnClose"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:layout_marginStart="12dp"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintEnd_toEndOf="parent"
+ android:src="@drawable/close_white_large"
+ android:backgroundTint="?colorPrimaryDark"
+ android:contentDescription="close"
+
+ />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/app/src/main/res/layout/fragment_map.xml b/app/src/main/res/layout/fragment_map.xml
deleted file mode 100644
--- a/app/src/main/res/layout/fragment_map.xml
+++ /dev/null
@@ -1,45 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <androidx.coordinatorlayout.widget.CoordinatorLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:id="@+id/coord_layout"
- android:layout_alignParentBottom="true"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_gravity="bottom|end"
-
- >
- <org.osmdroid.views.MapView android:id="@+id/map"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
- </androidx.coordinatorlayout.widget.CoordinatorLayout>
- <ImageButton
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/centerMapImageButton"
- android:src="@drawable/ic_center_map"
- android:layout_alignParentTop="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:layout_marginTop="10dp"
- android:layout_marginRight="10dp"
- android:background="#00ffffff"
- android:contentDescription="@string/bt_center_map_description"
- android:cropToPadding="true" />
-
- <ImageButton
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:id="@+id/followUserImageButton"
- android:src="@drawable/ic_follow_me"
- android:background="#00ffffff"
- android:contentDescription="@string/bt_follow_me_description"
- android:cropToPadding="true"
- android:layout_below="@+id/centerMapImageButton"
- android:layout_alignLeft="@+id/centerMapImageButton"
- android:layout_alignStart="@+id/centerMapImageButton"
- android:layout_marginTop="10dp" />
-</RelativeLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_map_libre.xml b/app/src/main/res/layout/fragment_map_libre.xml
--- a/app/src/main/res/layout/fragment_map_libre.xml
+++ b/app/src/main/res/layout/fragment_map_libre.xml
@@ -185,16 +185,27 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/followUserImageButton"
- android:src="@drawable/ic_follow_me"
+ android:src="@drawable/walk_circle_inactive"
android:background="#00ffffff"
android:contentDescription="@string/bt_follow_me_description"
- android:cropToPadding="true"
android:layout_marginEnd="1dp"
android:layout_below="@+id/centerMapImageButton"
android:layout_alignStart="@+id/centerMapImageButton"
android:layout_marginTop="7dp" />
+ <ImageButton
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:id="@+id/busPositionsImageButton"
+ android:src="@drawable/bus_pos_circle_inactive"
+ android:background="#00ffffff"
+ android:contentDescription="@string/bt_follow_me_description"
+ android:layout_marginEnd="1dp"
+
+ android:layout_below="@+id/followUserImageButton"
+ android:layout_alignStart="@+id/followUserImageButton"
+ android:layout_marginTop="7dp" />
</RelativeLayout>
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
--- a/app/src/main/res/values/colors.xml
+++ b/app/src/main/res/values/colors.xml
@@ -10,6 +10,7 @@
<color name="blue_620">#2a65e8</color>
<color name="blue_700">#2060dd</color>
<color name="brown_vd">#8A4247</color><!-- #1976D2 -->
+ <color name="dialog_background">#FFF3E0</color>
<color name="blue_mid_2">#2378e8</color>
<color name="blue_c_or_700">#0079f5</color>
@@ -29,6 +30,8 @@
<color name="grey_100">#F5F5F5</color>
<color name="grey_200">#dddddd</color>
<color name="grey_050">#f8f8f8</color>
+ <color name="grey_400">#bababa</color>
+ <color name="grey_500">#acacac</color>
<color name="grey_600">#757575</color>
<color name="grey_700">#444</color>
<color name="grey_800">#353535</color>
@@ -40,6 +43,9 @@
<color name="red_darker">#b30000</color>
<color name="red_orange">#dd441f</color>
<color name="red_dark">#b30d0d</color>
+ <color name="orange_icons">#f15000</color>
+ <color name="orange_icons_10light">#f2621a</color>
+ <color name="orange_icons_20light">#f47333</color>
<color name="blue_extraurbano">#2060DD</color>
<color name="white">#FFFFFF</color>
<color name="black">#000000</color>
@@ -63,4 +69,6 @@
<color name="urban_bus_bg">@color/orange_500</color>
<color name="extraurban_bus_bg">@color/blue_extraurbano</color>
<color name="metro_bg">@color/metro_red</color>
+ <color name="map_icon_background_active">@color/orange_icons_10light</color>
+ <color name="map_icon_background_inactive">@color/grey_400</color>
</resources>
\ No newline at end of file
diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml
--- a/app/src/main/res/values/keys.xml
+++ b/app/src/main/res/values/keys.xml
@@ -3,6 +3,9 @@
tools:ignore="MissingTranslation">
<string name="pref_layout" translatable="false">layout_pref</string>
<string name="pref_update_db_now" translatable="false">pref_update_db_now</string>
+ <string name="positions_source_mqtt" translatable="false">mqtt</string>
+ <string name="positions_source_gtfsrt" translatable="false">gtfsrt</string>
+
<array name="first_screen_values">
<item>arrivals</item>
@@ -26,8 +29,8 @@
<string name="pref_positions_source">pref_positions_source</string>
<array name="positions_source_values">
- <item>mqtt</item>
- <item>gtfsrt</item>
+ <item>@string/positions_source_mqtt</item>
+ <item>@string/positions_source_gtfsrt</item>
</array>
<!-- MapLibre Preferences -->
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
@@ -360,6 +360,16 @@
<string name="showing_same_direction">Direction is already shown</string>
<string name="destination_loading">Loading destination…</string>
<string name="destination_unknown">Destination unknown</string>
-
+ <!-- LIVE POSITIONS DIALOG -->
+ <string name="live_positions_msg_ok">Service for positions working normally</string>
+ <string name="live_positions_msg_no_positions">No positions received</string>
+ <string name="live_positions_msg_connection_error">Error connecting to the server</string>
+ <string name="live_positions_msg_parsing_error">Error parsing the server response</string>
+ <string name="live_positions_msg_network_error">Error: network response is not as expected</string>
+ <string name="live_positions_msg_connecting">Connecting...</string>
+ <string name="positions_source_mato_short">MaTO</string>
+ <string name="positions_source_gtfsrt_short">GTFS RT</string>
+ <string name="live_positions_dialog_provider_text">Live positions source:</string>
+ <string name="live_positions_switch_provider">Switch source</string>
</resources>

File Metadata

Mime Type
text/plain
Expires
Sun, Dec 7, 07:55 (21 h, 1 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1426401
Default Alt Text
D205.1765090545.diff (55 KB)

Event Timeline