From b2140c3d42b7a0c64d56a7b4510ed59fd0ba82c5 Mon Sep 17 00:00:00 2001 From: oupson Date: Sun, 10 Jul 2022 16:41:29 +0200 Subject: [PATCH] Fix widget not working and update deps --- .gitignore | 3 +- .idea/misc.xml | 9 --- app/build.gradle | 20 +++--- .../TaoWidgetConfigurationActivity.kt | 1 + .../oupson/taotoolbox/receivers/TaoWidget.kt | 31 +++++---- .../taotoolbox/utils/PrefsWidgetHelper.kt | 39 +++++++----- .../taotoolbox/windows/StopInfoWindow.kt | 9 ++- build.gradle | 6 +- common/build.gradle | 24 ++++--- .../main/java/fr/oupson/common/api/Stop.kt | 5 ++ .../java/fr/oupson/common/api/TaoRestApi.kt | 63 ++++++++++++------- wear_tao/build.gradle | 29 +++++---- 12 files changed, 142 insertions(+), 97 deletions(-) delete mode 100644 .idea/misc.xml 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