Android 16 bug: EncryptedSharedPreferences threw on ANY exception (Keystore
busy during screen-lock/BG wakeup) and the code deleted the encrypted prefs
file on any failure, permanently erasing session cookies. Now only
KeyPermanentlyInvalidatedException (biometric/PIN change) triggers delete;
transient failures preserve the file for the next session.
Also prevents saving cookies to plain-text fallback prefs if encrypted prefs
are unavailable.
WorkManager periodic (15 min, requires network) added alongside AlarmManager
as a Doze-mode backup for Android 16, where inexact alarms can be batched up
to 75 min.
UI: sync icon 24→32dp (large widget), 20→28dp (small); reset-time font
9→11sp (large), 8→10sp (small).
Security:
- All Log.d response-body and URL-bearing logs gated behind BuildConfig.DEBUG
- Cookie header value stripped of CRLF to prevent HTTP header injection
- LoginActivity coroutine migrated from bare CoroutineScope to lifecycleScope
- Widget removed from keyguard (lock-screen) category — usage data is sensitive
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- onResume() no longer triggers a refresh every time — only fetches when
data is >5 min stale, so returning to app shows cached data instantly
without a loading spinner
- Fix CancellationException being swallowed by catch(Exception) in
refreshUsage(), which caused updates to run on a destroyed activity
- EncryptedSharedPreferences key invalidation (caused by enabling/changing
biometrics or screen lock) now deletes the stale encrypted file and
recreates it cleanly, rather than silently using empty fallback prefs
- Wrap all securePrefs read/write ops in try-catch so a mid-session
Keystore failure degrades gracefully instead of crashing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two root causes:
- Alarms don't survive reboot — BootReceiver now restarts alarm + triggers
an immediate fetch on BOOT_COMPLETED
- onUpdate() drew from cached prefs but never fetched fresh data — now
triggers an immediate refresh so the widget is live on every launcher redraw
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove KEY_COOKIES_BACKUP plaintext fallback from PreferencesManager
- getCookies() now fails closed (force re-login) if EncryptedSharedPreferences unavailable
- Set android:allowBackup="false" to prevent adb backup extraction of session data
- Add missing gradle-wrapper.jar to repo
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>