attempt to stop crashes on Android 6 (but they didn't work)

This commit is contained in:
2026-02-26 20:26:43 -07:00
parent cff7b659dc
commit 4565e43479
10 changed files with 29 additions and 19 deletions

View File

@@ -94,6 +94,7 @@ The project includes an automated build script that handles both TypeScript and
```bash ```bash
# Build all platforms # Build all platforms
# Requires npm & gradle (with Java)
./scripts/build-native.sh ./scripts/build-native.sh
# Build specific platform # Build specific platform

View File

@@ -37,6 +37,7 @@ android {
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8
} }
@@ -116,6 +117,8 @@ dependencies {
implementation "com.google.code.gson:gson:2.10.1" implementation "com.google.code.gson:gson:2.10.1"
implementation "androidx.core:core:1.12.0" implementation "androidx.core:core:1.12.0"
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
// Room annotation processor - use kapt for Kotlin, annotationProcessor for Java // Room annotation processor - use kapt for Kotlin, annotationProcessor for Java
kapt "androidx.room:room-compiler:2.6.1" kapt "androidx.room:room-compiler:2.6.1"
annotationProcessor "androidx.room:room-compiler:2.6.1" annotationProcessor "androidx.room:room-compiler:2.6.1"

View File

@@ -229,7 +229,7 @@ public class DailyNotificationFetcher {
content.getTitle(), content.getTitle(),
content.getBody(), content.getBody(),
content.getScheduledTime(), content.getScheduledTime(),
java.time.ZoneId.systemDefault().getId() java.util.TimeZone.getDefault().getID()
); );
entity.priority = mapPriority(content.getPriority()); entity.priority = mapPriority(content.getPriority());
try { try {

View File

@@ -1162,12 +1162,12 @@ open class DailyNotificationPlugin : Plugin() {
} else { } else {
call.reject("Daily notification scheduling failed") call.reject("Daily notification scheduling failed")
} }
} catch (e: Exception) { } catch (e: Throwable) {
Log.e(TAG, "Failed to schedule daily notification", e) Log.e(TAG, "Failed to schedule daily notification", e)
call.reject("Daily notification scheduling failed: ${e.message}") call.reject("Daily notification scheduling failed: ${e.message}")
} }
} }
} catch (e: Exception) { } catch (e: Throwable) {
Log.e(TAG, "Schedule daily notification error", e) Log.e(TAG, "Schedule daily notification error", e)
call.reject("Daily notification error: ${e.message}") call.reject("Daily notification error: ${e.message}")
} }
@@ -2729,7 +2729,7 @@ object ScheduleHelper {
} }
true true
} catch (e: Exception) { } catch (e: Throwable) {
Log.e("ScheduleHelper", "Failed to schedule daily notification", e) Log.e("ScheduleHelper", "Failed to schedule daily notification", e)
false false
} }

View File

@@ -740,7 +740,7 @@ public class DailyNotificationWorker extends Worker {
content.getTitle(), content.getTitle(),
content.getBody(), content.getBody(),
content.getScheduledTime(), content.getScheduledTime(),
java.time.ZoneId.systemDefault().getId() java.util.TimeZone.getDefault().getID()
); );
entity.priority = mapPriorityToInt(content.getPriority()); entity.priority = mapPriorityToInt(content.getPriority());
try { try {

View File

@@ -211,7 +211,7 @@ class FetchWorker(
title, title,
body, body,
notificationTime, notificationTime,
java.time.ZoneId.systemDefault().id java.util.TimeZone.getDefault().id
) )
entity.priority = 0 // default priority entity.priority = 0 // default priority
entity.vibrationEnabled = true entity.vibrationEnabled = true

View File

@@ -257,7 +257,7 @@ class NotifyReceiver : BroadcastReceiver() {
config.title, config.title,
config.body ?: (if (contentCache != null) String(contentCache.payload) else ""), config.body ?: (if (contentCache != null) String(contentCache.payload) else ""),
triggerAtMillis, triggerAtMillis,
java.time.ZoneId.systemDefault().id java.util.TimeZone.getDefault().id
) )
entity.priority = when (config.priority) { entity.priority = when (config.priority) {
"high", "max" -> 2 "high", "max" -> 2
@@ -275,7 +275,7 @@ class NotifyReceiver : BroadcastReceiver() {
roomStorage.saveNotificationContent(entity).get() roomStorage.saveNotificationContent(entity).get()
Log.d(TAG, "Stored notification content in database: id=$notificationId (for recovery tracking)") Log.d(TAG, "Stored notification content in database: id=$notificationId (for recovery tracking)")
} }
} catch (e: Exception) { } catch (e: Throwable) {
Log.w(TAG, "Failed to store notification content in database, continuing with alarm scheduling", e) Log.w(TAG, "Failed to store notification content in database, continuing with alarm scheduling", e)
} }
@@ -400,14 +400,18 @@ class NotifyReceiver : BroadcastReceiver() {
Log.i(TAG, "Exact alarm scheduled (setExact): triggerAt=$triggerAtMillis, requestCode=$requestCode") Log.i(TAG, "Exact alarm scheduled (setExact): triggerAt=$triggerAtMillis, requestCode=$requestCode")
} }
} catch (e: SecurityException) { } catch (e: Throwable) {
Log.w(TAG, "Cannot schedule exact alarm, falling back to inexact", e) Log.w(TAG, "Cannot schedule exact alarm, falling back to inexact", e)
try {
alarmManager.set( alarmManager.set(
AlarmManager.RTC_WAKEUP, AlarmManager.RTC_WAKEUP,
triggerAtMillis, triggerAtMillis,
pendingIntent pendingIntent
) )
Log.i(TAG, "Inexact alarm scheduled (fallback): triggerAt=$triggerAtMillis, requestCode=$requestCode") Log.i(TAG, "Inexact alarm scheduled (fallback): triggerAt=$triggerAtMillis, requestCode=$requestCode")
} catch (fallbackError: Throwable) {
Log.e(TAG, "Fallback alarm scheduling also failed", fallbackError)
}
} }
// Update database schedule with new nextRunAt so getNotificationStatus() returns correct value // Update database schedule with new nextRunAt so getNotificationStatus() returns correct value
@@ -462,8 +466,7 @@ class NotifyReceiver : BroadcastReceiver() {
Log.d(SCHEDULE_TAG, "Created new schedule in database: id=$stableScheduleId, nextRunAt=$triggerAtMillis") Log.d(SCHEDULE_TAG, "Created new schedule in database: id=$stableScheduleId, nextRunAt=$triggerAtMillis")
} }
} }
} catch (e: Exception) { } catch (e: Throwable) {
// Log but don't fail - alarm is already scheduled, DB update is best-effort
Log.w(SCHEDULE_TAG, "Failed to update schedule in database: $stableScheduleId (alarm still scheduled)", e) Log.w(SCHEDULE_TAG, "Failed to update schedule in database: $stableScheduleId (alarm still scheduled)", e)
} }
} }

View File

@@ -273,7 +273,7 @@ class ReactivationManager(private val context: Context) {
"Daily Notification", "Daily Notification",
"Your daily update is ready", "Your daily update is ready",
scheduledTime, scheduledTime,
java.time.ZoneId.systemDefault().id java.util.TimeZone.getDefault().id
) )
notification.deliveryStatus = "missed" notification.deliveryStatus = "missed"
notification.lastDeliveryAttempt = System.currentTimeMillis() notification.lastDeliveryAttempt = System.currentTimeMillis()
@@ -1043,7 +1043,7 @@ class ReactivationManager(private val context: Context) {
"Daily Notification", "Daily Notification",
"Your daily update is ready", "Your daily update is ready",
scheduledTime, scheduledTime,
java.time.ZoneId.systemDefault().id java.util.TimeZone.getDefault().id
) )
notification.deliveryStatus = "missed" notification.deliveryStatus = "missed"
notification.lastDeliveryAttempt = System.currentTimeMillis() notification.lastDeliveryAttempt = System.currentTimeMillis()

View File

@@ -65,6 +65,7 @@ emulator -avd AVD_NAME
adb devices adb devices
# Now install on the emulator # Now install on the emulator
# ... which can take a looooooong time
adb install -r ./app/build/outputs/apk/debug/app-debug.apk adb install -r ./app/build/outputs/apk/debug/app-debug.apk
# Now start the app # Now start the app

View File

@@ -17,6 +17,7 @@ android {
} }
} }
compileOptions { compileOptions {
coreLibraryDesugaringEnabled true
sourceCompatibility JavaVersion.VERSION_17 sourceCompatibility JavaVersion.VERSION_17
targetCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17
} }
@@ -62,6 +63,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-service:2.7.0' implementation 'androidx.lifecycle:lifecycle-service:2.7.0'
implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.google.code.gson:gson:2.10.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.4'
testImplementation "junit:junit:$junitVersion" testImplementation "junit:junit:$junitVersion"
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion" androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion" androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"