diff --git a/.gitignore b/.gitignore
index ffdee74..cb13c7e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ captures/
.idea/modules.xml
# Comment next line if keeping position of elements in Navigation Editor is relevant for you
.idea/navEditor.xml
+.idea/misc.xml
# Keystore files
# Uncomment the following lines if you do not want to check your keystore files in.
@@ -87,4 +88,4 @@ lint/tmp/
# lint/reports/
# Android Profiling
-*.hprof
\ No newline at end of file
+*.hprof
diff --git a/.idea/misc.xml b/.idea/misc.xml
deleted file mode 100644
index 860da66..0000000
--- a/.idea/misc.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index de65136..7880fe3 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -4,15 +4,15 @@ plugins {
}
android {
- compileSdkVersion 31
+ compileSdkVersion 32
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "fr.oupson.taotoolbox"
minSdkVersion 21
- targetSdkVersion 31
+ targetSdkVersion 32
versionCode 1
- versionName "0.0.3"
+ versionName "0.0.4"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
@@ -43,18 +43,18 @@ android {
}
dependencies {
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.4.1'
- implementation 'com.google.android.material:material:1.5.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.preference:preference-ktx:1.2.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.2'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2'
implementation project(":common")
- implementation 'org.osmdroid:osmdroid-android:6.1.10'
+ implementation 'org.osmdroid:osmdroid-android:6.1.13'
}
\ No newline at end of file
diff --git a/app/src/main/java/fr/oupson/taotoolbox/activities/TaoWidgetConfigurationActivity.kt b/app/src/main/java/fr/oupson/taotoolbox/activities/TaoWidgetConfigurationActivity.kt
index 4af17a2..a24babd 100644
--- a/app/src/main/java/fr/oupson/taotoolbox/activities/TaoWidgetConfigurationActivity.kt
+++ b/app/src/main/java/fr/oupson/taotoolbox/activities/TaoWidgetConfigurationActivity.kt
@@ -292,6 +292,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
super.onDestroy()
if (BuildConfig.DEBUG)
Log.v(TAG, "Closing database")
+
db?.close()
}
diff --git a/app/src/main/java/fr/oupson/taotoolbox/receivers/TaoWidget.kt b/app/src/main/java/fr/oupson/taotoolbox/receivers/TaoWidget.kt
index 2c4bb29..6695f58 100644
--- a/app/src/main/java/fr/oupson/taotoolbox/receivers/TaoWidget.kt
+++ b/app/src/main/java/fr/oupson/taotoolbox/receivers/TaoWidget.kt
@@ -11,8 +11,9 @@ import android.os.Build
import android.util.Log
import android.widget.RemoteViews
import fr.oupson.common.api.LineColors
-import fr.oupson.common.api.RealTimes
+import fr.oupson.common.api.RealtimeStopArea
import fr.oupson.common.api.TaoRestApi
+import fr.oupson.taotoolbox.BuildConfig
import fr.oupson.taotoolbox.R
import fr.oupson.taotoolbox.utils.PrefsWidgetHelper
import kotlinx.coroutines.*
@@ -28,7 +29,8 @@ class TaoWidget : AppWidgetProvider() {
appWidgetId: Int,
taoRestApi: TaoRestApi
) {
- Log.d(TAG, "updateAppWidget, appWidgetId : $appWidgetId")
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "updateAppWidget, appWidgetId : $appWidgetId")
// Construct the RemoteViews object
val views = RemoteViews(context.packageName, R.layout.widget_tao)
@@ -56,7 +58,8 @@ class TaoWidget : AppWidgetProvider() {
val prefs = PrefsWidgetHelper.getPrefs(context, appWidgetId)!! // Caught
val depart = taoRestApi.getNextDeparturesForLine(
prefs.stopId,
- prefs.routeId
+ prefs.routeId,
+ prefs.lineId,
)
views.setRealtime(
@@ -132,7 +135,7 @@ class TaoWidget : AppWidgetProvider() {
stopName: String,
lineName: String,
lineBtm: Bitmap,
- realTimes: RealTimes
+ realTimes: RealtimeStopArea
) {
setImageViewBitmap(
R.id.widget_tao_line_icon_image_view,
@@ -154,7 +157,7 @@ class TaoWidget : AppWidgetProvider() {
setTextViewText(
R.id.widget_tao_next_text_view, context.getString(
R.string.time_remaining,
- realTimes.timeRemaining(0) ?: "∅"
+ realTimes.timeRemaining() ?: "∅"
)
)
@@ -162,7 +165,7 @@ class TaoWidget : AppWidgetProvider() {
R.id.widget_tao_after_next_text_view,
context.getString(
R.string.time_remaining,
- realTimes.timeRemainingAfter(0) ?: "∅"
+ realTimes.timeRemainingAfter() ?: "∅"
)
)
@@ -170,7 +173,7 @@ class TaoWidget : AppWidgetProvider() {
R.id.widget_tao_third_text_view,
context.getString(
R.string.time_remaining,
- realTimes.timeRemainingThird(0) ?: "∅"
+ realTimes.timeRemainingThird() ?: "∅"
)
)
}
@@ -209,10 +212,12 @@ class TaoWidget : AppWidgetProvider() {
appWidgetIds: IntArray
) {
super.onUpdate(context, appWidgetManager, appWidgetIds)
- Log.d(
- TAG,
- "onUpdate : appWidgetIds : ${appWidgetIds.contentToString()}"
- )
+ if (BuildConfig.DEBUG)
+ Log.d(
+ TAG,
+ "onUpdate : appWidgetIds : ${appWidgetIds.contentToString()}"
+ )
+
widgetScope.launch {
val taoRestApi = TaoRestApi().also {
it.requestContext = this.coroutineContext
@@ -226,7 +231,9 @@ class TaoWidget : AppWidgetProvider() {
override fun onDeleted(context: Context?, appWidgetIds: IntArray?) {
super.onDeleted(context, appWidgetIds)
- Log.d(TAG, "onDeleted : ${appWidgetIds?.contentToString()}")
+
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "onDeleted : ${appWidgetIds?.contentToString()}")
runBlocking {
job.cancelAndJoin()
diff --git a/app/src/main/java/fr/oupson/taotoolbox/utils/PrefsWidgetHelper.kt b/app/src/main/java/fr/oupson/taotoolbox/utils/PrefsWidgetHelper.kt
index ab3a06b..85e86d1 100644
--- a/app/src/main/java/fr/oupson/taotoolbox/utils/PrefsWidgetHelper.kt
+++ b/app/src/main/java/fr/oupson/taotoolbox/utils/PrefsWidgetHelper.kt
@@ -4,13 +4,25 @@ import android.content.Context
import android.graphics.Color
import android.util.Log
import androidx.core.content.edit
+import fr.oupson.taotoolbox.BuildConfig
class PrefsWidgetHelper {
+ data class WidgetPrefs(
+ val lineId: String,
+ val lineCode: String,
+ val routeId: String,
+ val routeName: String,
+ val stopId: String,
+ val stopName: String,
+ val bgColor: Int,
+ val textColor: Int
+ )
+
companion object {
private const val LINE_ID = "WIDGET_LINE_ID"
private const val LINE_CODE = "WIDGET_LINE_CODE"
- private const val ROUTE_ID = "WIDGET_LINE_ID"
- private const val ROUTE_NAME = "ROUTE_NAME"
+ private const val ROUTE_ID = "WIDGET_ROUTE_ID"
+ private const val ROUTE_NAME = "WIDGET_ROUTE_NAME"
private const val STOP_ID = "WIDGET_STOP_ID"
private const val STOP_NAME = "WIDGET_STOP_NAME"
private const val BG_COLOR = "WIDGET_LINE_BACKGROUND_COLOR"
@@ -32,7 +44,9 @@ class PrefsWidgetHelper {
bgColor: Int,
textColor: Int
) {
- Log.d(TAG, "savePrefs, widget id : $widgetId")
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "savePrefs, widget id : $widgetId")
+
context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE).edit(true) {
putString("${LINE_ID}_$widgetId", lineId)
putString("${LINE_CODE}_$widgetId", lineCode)
@@ -45,20 +59,11 @@ class PrefsWidgetHelper {
}
}
- data class WidgetPrefs(
- val lineId: String,
- val lineCode: String,
- val routeId: String,
- val routeName: String,
- val stopId: String,
- val stopName: String,
- val bgColor: Int,
- val textColor: Int
- )
-
fun getPrefs(context: Context, widgetId: Int): WidgetPrefs? =
with(context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)) {
- Log.d(TAG, "getPrefs, widget id : $widgetId")
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "getPrefs, widget id : $widgetId")
+
WidgetPrefs(
getString("${LINE_ID}_$widgetId", null) ?: return null,
getString("${LINE_CODE}_$widgetId", null) ?: return null,
@@ -72,7 +77,9 @@ class PrefsWidgetHelper {
}
fun destroyPrefs(context: Context, widgetId: Int) {
- Log.d(TAG, "destroyPrefs, widget id : $widgetId")
+ if (BuildConfig.DEBUG)
+ Log.d(TAG, "destroyPrefs, widget id : $widgetId")
+
val prefs = context.getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE)
prefs.edit(commit = true) {
remove("${LINE_ID}_$widgetId")
diff --git a/app/src/main/java/fr/oupson/taotoolbox/windows/StopInfoWindow.kt b/app/src/main/java/fr/oupson/taotoolbox/windows/StopInfoWindow.kt
index 002ffd7..35f37ac 100644
--- a/app/src/main/java/fr/oupson/taotoolbox/windows/StopInfoWindow.kt
+++ b/app/src/main/java/fr/oupson/taotoolbox/windows/StopInfoWindow.kt
@@ -19,6 +19,7 @@ class StopInfoWindow(
) : InfoWindow(R.layout.window_stop_info, mapView) {
private val job = Job()
private val windowsContext = Dispatchers.IO + job
+ private val scope = CoroutineScope(windowsContext)
private val titleTextView: TextView by lazy { view.findViewById(R.id.window_stop_info_title_text_view) }
@@ -37,20 +38,21 @@ class StopInfoWindow(
}
override fun onOpen(item: Any?) {
+ val size = realtimeList.get()?.size ?: 0
realtimeList.set(null)
- recyclerView.adapter?.notifyDataSetChanged()
+ recyclerView.adapter?.notifyItemRangeRemoved(0, size)
if (item is Marker) {
val id = item.id
titleTextView.text = item.title
- GlobalScope.launch(windowsContext) {
+ scope.launch(windowsContext) {
try {
val realtime = taoRestApi.getRealtimeByStopArea(id)
withContext(Dispatchers.Main) {
realtimeList.set(realtime)
- adapter.notifyDataSetChanged()
+ adapter.notifyItemRangeInserted(0, realtime.size)
}
} catch (e: Exception) {
e.printStackTrace()
@@ -66,5 +68,6 @@ class StopInfoWindow(
override fun onClose() {
windowsContext.cancelChildren()
+ scope.cancel()
}
}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index 5cff940..c987689 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,13 +1,13 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
- ext.kotlin_version = "1.6.10"
- ext.ktor_version = "1.6.3"
+ ext.kotlin_version = "1.7.0"
+ ext.ktor_version = "2.0.3"
repositories {
google()
mavenCentral()
}
dependencies {
- classpath 'com.android.tools.build:gradle:7.1.1'
+ classpath 'com.android.tools.build:gradle:7.1.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
diff --git a/common/build.gradle b/common/build.gradle
index 4ef2eca..4e56830 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -18,29 +18,35 @@ android {
buildTypes {
release {
- //minifyEnabled false
+ // minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
+
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.4.1'
- implementation 'com.google.android.material:material:1.5.0'
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+
+ implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
+
+ implementation("io.ktor:ktor-client-content-negotiation:$ktor_version")
+ implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
+ implementation("io.ktor:ktor-client-logging:$ktor_version")
+ implementation "io.ktor:ktor-client-core:$ktor_version"
+ implementation "io.ktor:ktor-client-android:$ktor_version"
+
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2"
-
- implementation "io.ktor:ktor-client-serialization:$ktor_version"
- implementation "io.ktor:ktor-client-core:$ktor_version"
- implementation "io.ktor:ktor-client-android:$ktor_version"
}
\ No newline at end of file
diff --git a/common/src/main/java/fr/oupson/common/api/Stop.kt b/common/src/main/java/fr/oupson/common/api/Stop.kt
index 84e8238..f8f4aae 100644
--- a/common/src/main/java/fr/oupson/common/api/Stop.kt
+++ b/common/src/main/java/fr/oupson/common/api/Stop.kt
@@ -190,6 +190,11 @@ data class RealtimeStopArea(
(it.date!!.time - Date().time) / (1000 * 60)
}
+ fun timeRemainingThird(): Long? =
+ nextPassages.getOrNull(2)?.let {
+ (it.date!!.time - Date().time) / (1000 * 60)
+ }
+
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
diff --git a/common/src/main/java/fr/oupson/common/api/TaoRestApi.kt b/common/src/main/java/fr/oupson/common/api/TaoRestApi.kt
index 29511fc..b7be1a3 100644
--- a/common/src/main/java/fr/oupson/common/api/TaoRestApi.kt
+++ b/common/src/main/java/fr/oupson/common/api/TaoRestApi.kt
@@ -1,20 +1,28 @@
package fr.oupson.common.api
import io.ktor.client.*
+import io.ktor.client.call.*
import io.ktor.client.engine.android.*
-import io.ktor.client.features.json.*
-import io.ktor.client.features.json.serializer.*
+import io.ktor.client.plugins.contentnegotiation.*
+import io.ktor.client.plugins.logging.*
import io.ktor.client.request.*
import io.ktor.client.request.forms.*
+import io.ktor.client.statement.*
import io.ktor.http.*
+import io.ktor.serialization.kotlinx.json.*
+import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlin.coroutines.CoroutineContext
class TaoRestApi(private val httpClient: HttpClient) {
constructor() : this(HttpClient(Android) {
- install(JsonFeature) {
- serializer = KotlinxSerializer(kotlinx.serialization.json.Json { ignoreUnknownKeys = true })
+ install(ContentNegotiation) {
+ json(kotlinx.serialization.json.Json { ignoreUnknownKeys = true })
+ }
+ install(Logging) {
+ logger = Logger.SIMPLE
+ level = LogLevel.INFO
}
engine {
connectTimeout = 10_1000
@@ -29,12 +37,13 @@ class TaoRestApi(private val httpClient: HttpClient) {
suspend fun getNextDeparturesForLine(
stopId: String,
routeId: String,
+ lineId: String,
limit: Int = 100
- ): RealTimes = withContext(
+ ): RealtimeStopArea = withContext(
requestContext
) {
httpClient.submitForm(
- "$baseUrl/2.0/realtime/byStopAreaAndRoute",
+ "$baseUrl/3.0/realtime/enhanced/byStopAreaAndRoute",
Parameters.build {
append(
"stopAreaId", stopId
@@ -42,10 +51,12 @@ class TaoRestApi(private val httpClient: HttpClient) {
append(
"routeId", routeId
)
+ append("lineId", lineId)
append("limit", "$limit")
+ append("includeLoadPrediction", "false")
},
true
- ) {}
+ ) {}.body()
}
suspend fun getTaoLineJson(
@@ -61,7 +72,7 @@ class TaoRestApi(private val httpClient: HttpClient) {
append("clientLastUpdate", clientLastUpdate ?: "1970-01-01T00:00:00.000Z")
},
true
- ) {}
+ ) {}.bodyAsText()
}
suspend fun getSchedule(stopId: String): Array = withContext(Dispatchers.IO) {
@@ -69,27 +80,35 @@ class TaoRestApi(private val httpClient: HttpClient) {
append(
"stopId", stopId
)
- }, true) {}
+ }, true) {}.body()
}
- suspend fun getRealtimeByStopArea(stopAreaId: String, limit: Int? = null, includeLoadPrediction: Boolean? = null) : Array = withContext(Dispatchers.IO) {
- httpClient.submitForm("https://navigorleans.c-t.io/api/3.0/realtime/byStopArea", Parameters.build {
- append(
- "stopAreaId", stopAreaId
- )
- if (limit != null) {
- append("limit", limit.toString())
- }
+ suspend fun getRealtimeByStopArea(
+ stopAreaId: String,
+ limit: Int? = null,
+ includeLoadPrediction: Boolean? = null
+ ): Array = withContext(Dispatchers.IO) {
+ httpClient.submitForm(
+ "https://navigorleans.c-t.io/api/3.0/realtime/byStopArea",
+ Parameters.build {
+ append(
+ "stopAreaId", stopAreaId
+ )
+ if (limit != null) {
+ append("limit", limit.toString())
+ }
- if (includeLoadPrediction != null) {
- append("includeLoadPrediction", includeLoadPrediction.toString())
- }
- }, true) {}
+ if (includeLoadPrediction != null) {
+ append("includeLoadPrediction", includeLoadPrediction.toString())
+ }
+ },
+ true
+ ) {}.body()
}
suspend fun getTaoGeoJson(
lineId: String
): String = withContext(requestContext) {
- httpClient.get("$baseUrl/2.0/lines/$lineId/geojson/encoded")
+ httpClient.get("$baseUrl/2.0/lines/$lineId/geojson/encoded").bodyAsText()
}
}
\ No newline at end of file
diff --git a/wear_tao/build.gradle b/wear_tao/build.gradle
index 900d121..3073dab 100644
--- a/wear_tao/build.gradle
+++ b/wear_tao/build.gradle
@@ -4,13 +4,13 @@ plugins {
}
android {
- compileSdkVersion 30
+ compileSdkVersion 31
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "fr.oupson.wear_tao"
minSdkVersion 26
- targetSdkVersion 30
+ targetSdkVersion 31
versionCode 1
versionName "1.0"
@@ -23,28 +23,33 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
+
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
+
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.0'
- implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.4.2'
- implementation 'androidx.core:core-ktx:1.6.0'
- implementation 'androidx.appcompat:appcompat:1.3.1'
- implementation 'com.google.android.material:material:1.4.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- implementation 'androidx.wear:wear:1.1.0'
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
+ implementation 'androidx.wear:wear:1.2.0'
implementation "androidx.wear:wear-tiles:1.0.0-alpha01"
debugImplementation "androidx.wear:wear-tiles-renderer:1.0.0-alpha01"
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.1'
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-guava:1.6.0'
+
implementation project(":common")
+
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}
\ No newline at end of file