Skip to content

Update Notification Logic

Fabian edited this page Aug 27, 2026 · 3 revisions

Trigger sources

Source When it fires Status
ConnectivityReceiver (dynamic, registered from main.py) App process alive + WiFi/data connects Instant check
UpdateCheckWorker (WorkManager) Every 15 min, only when network available Survives app kills

Both run entirely in Java — no Python needed for the check/notify.

Core logic (shared by both, identical flow)

  1. Cooldown gateSharedPreferences("update_checker_prefs", 0)last_notified_timestamp. If < 7 days since last notify, skip.
  2. HTTP GET https://api.github.com/.../releases/latest (10s timeout).
  3. Version compare — GitHub tag_name vs installed PackageInfo.versionName. Equal → skip.
  4. NotifyNotificationCompat on channel update_channel, id 999. Tap → PendingIntent launches the app with extras action=open_update, version=X.
  5. Save timestamplast_notified_timestamp = now (starts the 7-day clock).

Python side (only handles the tap)

  • main.py _bind_update_intent_listeneron_new_intent fires when notification tapped while app is alive → handle_update_intent(self, intent=intent)
  • update_checker.py handle_update_intent — reads action extra; if open_update, navigates to the update screen via _navigate_to_update_screen
  • If app was killed, the tap's intent is picked up by getIntent() in on_start/on_resume instead

Scheduling (one Java helper, called from Python on launch)

  • WorkScheduler.java — holds all WorkManager logic (Constraints, PeriodicWorkRequest, enqueueUniquePeriodicWork), avoiding jnius nested-class/covariant-return issues (Constraints$Builder, PeriodicWorkRequest.Builder.build() returning base WorkRequest).
  • update_checker.py schedule_update_check — calls WorkScheduler.scheduleUpdateCheck(context) once per launch. Work every 15 min with NetworkType.CONNECTED constraint. ExistingPeriodicWorkPolicy.KEEP prevents duplicates across re-launches.

Notes on receiver behavior

  • ConnectivityReceiver.onReceive does no network pre-check — it goes straight to the cooldown gate. If there's no real internet, the HTTP GET fails gracefully inside fetchLatestVersion (the initial getActiveNetworkInfo() check was removed: it falsely reported offline during the broadcast's brief transition window).
  • Adding a new Java class (WorkScheduler.java) requires a full rebuild; it's not covered by the adb-push source override.

Test hooks (temp)

  • VERSION temporarily "1.0.8" so GitHub's 1.0.9.1 is detected as newer (needs revert)
  • Config Clear in the Stats screen resets update_checker_prefs so you can re-trigger immediately

Key limitation

The ConnectivityReceiver check itself (the HTTP/notify part) only runs while the app's process is alive due to dynamic registration — but the WorkManager worker covers the killed-app case at 15-min granularity, which is WorkManager's floor.