diff --git a/android/app/build.gradle b/android/app/build.gradle index 7ea9a120..c4a68ae2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -89,7 +89,7 @@ flutter { dependencies { implementation 'com.android.support:multidex' - implementation 'joda-time:joda-time:2.12.6' + implementation 'joda-time:joda-time:2.12.7' def appcompat_version = "1.6.1" implementation("androidx.appcompat:appcompat:$appcompat_version") implementation("androidx.appcompat:appcompat-resources:$appcompat_version") diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index 20f07b9b..49b0275e 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -1,4 +1,42 @@ +# joda -keep class org.joda.** {*;} -dontwarn org.joda.** + +# prettytime +-keep class org.ocpsoft.pretty.time.i18n.** -keep class org.ocpsoft.prettytime.i18n.** +-keep class org.ocpsoft.prettytime.units.** -keepnames class ** implements org.ocpsoft.prettytime.TimeUnit + +# gson +-keepclassmembers,allowobfuscation class * { + @com.google.gson.annotations.SerializedName ; +} +-keep class * { + @com.google.gson.annotations.SerializedName ; +} +-if class * +-keepclasseswithmembers class <1> { + (...); + @com.google.gson.annotations.SerializedName ; +} +-keepnames class com.fasterxml.jackson.databind.** { *; } +-dontwarn com.fasterxml.jackson.databind.** + +# entires recommended by Android Studio +-dontwarn com.google.android.play.core.splitcompat.SplitCompatApplication +-dontwarn com.google.android.play.core.splitinstall.SplitInstallManager +-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest$Builder +-dontwarn com.google.android.play.core.splitinstall.SplitInstallRequest +-dontwarn com.google.android.play.core.splitinstall.SplitInstallStateUpdatedListener +-dontwarn com.google.android.play.core.tasks.OnFailureListener +-dontwarn com.google.android.play.core.tasks.OnSuccessListener +-dontwarn com.google.android.play.core.tasks.Task +-dontwarn com.google.api.client.http.GenericUrl +-dontwarn com.google.api.client.http.HttpHeaders +-dontwarn com.google.api.client.http.HttpRequest +-dontwarn com.google.api.client.http.HttpRequestFactory +-dontwarn com.google.api.client.http.HttpResponse +-dontwarn com.google.api.client.http.HttpTransport +-dontwarn com.google.api.client.http.javanet.NetHttpTransport$Builder +-dontwarn com.google.api.client.http.javanet.NetHttpTransport diff --git a/android/app/src/main/kotlin/de/tum/in/tumcampus/util/DateTimeSerializer.kt b/android/app/src/main/kotlin/de/tum/in/tumcampus/util/DateTimeSerializer.kt index a143911b..9b09e035 100644 --- a/android/app/src/main/kotlin/de/tum/in/tumcampus/util/DateTimeSerializer.kt +++ b/android/app/src/main/kotlin/de/tum/in/tumcampus/util/DateTimeSerializer.kt @@ -7,17 +7,21 @@ import org.joda.time.DateTime import org.joda.time.format.DateTimeFormat import java.lang.reflect.Type -class LocalDateTimeDeserializer : JsonDeserializer { +class LocalDateTimeDeserializer : JsonDeserializer { override fun deserialize( json: JsonElement?, typeOfT: Type?, context: JsonDeserializationContext? - ): DateTime { + ): DateTime? { return deserializeStringToDate(json?.asString) } } -fun deserializeStringToDate(dateString: String?): DateTime { - val formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS") - return DateTime.parse(dateString, formatter) +fun deserializeStringToDate(dateString: String?): DateTime? { + return try { + val formatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSSSS") + DateTime.parse(dateString, formatter) + } catch (_: Exception) { + null + } } \ No newline at end of file diff --git a/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/CalendarWidget.kt b/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/CalendarWidget.kt index b98bfe32..1075639a 100644 --- a/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/CalendarWidget.kt +++ b/android/app/src/main/kotlin/de/tum/in/tumcampus/widgets/calendar/CalendarWidget.kt @@ -51,8 +51,8 @@ private fun updateAppWidget( val p = PrettyTime() val widgetData = HomeWidgetPlugin.getData(context) val lastSaved = widgetData.getString("calendar_save", null) - val lastSavedDate = deserializeStringToDate(lastSaved).toLocalDate() - val lastSavedDateString = p.format( deserializeStringToDate(lastSaved).toDate()) + val lastSavedDate = deserializeStringToDate(lastSaved)?.toLocalDate() + val lastSavedDateString = p.format( deserializeStringToDate(lastSaved)?.toDate()) remoteViews.setTextViewText(R.id.calendar_widget_updated_on, lastSavedDateString) val pendingIntentWithData = HomeWidgetLaunchIntent.getActivity( diff --git a/lib/base/networking/cache/cache.dart b/lib/base/networking/cache/cache.dart index 872422a9..63e7f0bd 100644 --- a/lib/base/networking/cache/cache.dart +++ b/lib/base/networking/cache/cache.dart @@ -9,21 +9,7 @@ class Cache { Cache({required this.isar}); - void add(String body, Uri uri) { - final today = DateTime.now(); - final cacheEntry = CacheEntry( - id: fastHash(uri.toString()), - url: uri.toString(), - validUntil: today.add(ttl), - saved: today, - data: body, - ); - isar.writeTxn( - () => isar.cacheEntrys.put(cacheEntry), - ); - } - - void addString(String body, String uri) { + void add(String body, String uri) { final today = DateTime.now(); final cacheEntry = CacheEntry( id: fastHash(uri), @@ -37,15 +23,15 @@ class Cache { ); } - CacheEntry? get(Uri uri) { - final hash = fastHash(uri.toString()); + CacheEntry? get(String uri) { + final hash = fastHash(uri); final entry = isar.txnSync(() => isar.cacheEntrys.getSync(hash)); if (entry != null) { final today = DateTime.now(); if (entry.validUntil.isAfter(today)) { return entry; } else { - isar.writeTxnSync(() => isar.cacheEntrys.deleteSync(hash)); + isar.writeTxn(() => isar.cacheEntrys.delete(hash)); return null; } } else { @@ -53,15 +39,15 @@ class Cache { } } - CacheEntry? getWithString(String uri) { + Future getAsync(String uri) async { final hash = fastHash(uri); - final entry = isar.txnSync(() => isar.cacheEntrys.getSync(hash)); + final entry = await isar.txn(() => isar.cacheEntrys.get(hash)); if (entry != null) { final today = DateTime.now(); if (entry.validUntil.isAfter(today)) { return entry; } else { - isar.writeTxnSync(() => isar.cacheEntrys.deleteSync(hash)); + isar.writeTxn(() => isar.cacheEntrys.delete(hash)); return null; } } else { diff --git a/lib/base/networking/cache/grpc_cache_interceptor.dart b/lib/base/networking/cache/grpc_cache_interceptor.dart index e6f51d4a..4ca367ad 100644 --- a/lib/base/networking/cache/grpc_cache_interceptor.dart +++ b/lib/base/networking/cache/grpc_cache_interceptor.dart @@ -29,7 +29,7 @@ class GrpcCacheInterceptor implements ClientInterceptor { ClientUnaryInvoker invoker, ) { final key = method.path; - final cachedResponse = cache.getWithString(key); + final cachedResponse = cache.get(key); final factory = _getFactory(); if (cachedResponse != null && factory != null) { final data = factory(cachedResponse.data); @@ -47,7 +47,7 @@ class GrpcCacheInterceptor implements ClientInterceptor { /// If not found in cache, invoke the actual RPC and cache the response final response = invoker(method, request, options); response.then((data) { - cache.addString((data as GeneratedMessage).writeToJson(), key); + cache.add((data as GeneratedMessage).writeToJson(), key); }); return response; diff --git a/lib/base/networking/cache/rest_cache_interceptor.dart b/lib/base/networking/cache/rest_cache_interceptor.dart index cbfba104..69aa4a25 100644 --- a/lib/base/networking/cache/rest_cache_interceptor.dart +++ b/lib/base/networking/cache/rest_cache_interceptor.dart @@ -29,7 +29,7 @@ class RestCacheInterceptor implements Interceptor { if (options.extra["forcedRefresh"] == "true") { cache.delete(key); } else { - final cacheEntry = cache.getWithString(key); + final cacheEntry = await cache.getAsync(key); /// device is online, fetch every 10 minutes if (cacheEntry != null && @@ -54,7 +54,7 @@ class RestCacheInterceptor implements Interceptor { if (options.extra["forcedRefresh"] == "true") { cache.delete(key); } else { - final cacheEntry = cache.getWithString(key); + final cacheEntry = await cache.getAsync(key); if (cacheEntry != null && DateTime.now().difference(cacheEntry.saved).inDays <= 30) { return handler.resolve( @@ -78,7 +78,7 @@ class RestCacheInterceptor implements Interceptor { @override void onResponse(Response response, ResponseInterceptorHandler handler) { final key = response.realUri.toString(); - cache.addString(response.data, key); + cache.add(response.data, key); response.extra = response.extra..addAll({"saved": DateTime.now()}); handler.next(response); }