Fix widget not working and update deps

This commit is contained in:
oupson 2022-07-10 16:41:29 +02:00
parent 6e8660a7be
commit b2140c3d42
12 changed files with 142 additions and 97 deletions

3
.gitignore vendored
View File

@ -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
*.hprof

View File

@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

View File

@ -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'
}

View File

@ -292,6 +292,7 @@ class TaoWidgetConfigurationActivity : AppCompatActivity() {
super.onDestroy()
if (BuildConfig.DEBUG)
Log.v(TAG, "Closing database")
db?.close()
}

View File

@ -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()

View File

@ -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")

View File

@ -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()
}
}

View File

@ -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

View File

@ -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"
}

View File

@ -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

View File

@ -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<Schedule> = 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<RealtimeStopArea> = 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<RealtimeStopArea> = 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()
}
}

View File

@ -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'
}