Skip to content

Optional auto-cleanup of recordings older than N days (engine only)#148

Open
dsremo wants to merge 1 commit into
Dimowner:masterfrom
dsremo:dsremo/recordings-retention
Open

Optional auto-cleanup of recordings older than N days (engine only)#148
dsremo wants to merge 1 commit into
Dimowner:masterfrom
dsremo:dsremo/recordings-retention

Conversation

@dsremo
Copy link
Copy Markdown

@dsremo dsremo commented May 15, 2026

What this is

An opt-in retention engine that deletes recording files older than a user-set number of days. Disabled by default (max_age_days = 0); zero behavior change for existing users.

How it works

  • New util/RecordingsRetention object exposes:
    • setMaxAgeDays(context, days) — set the threshold
    • getMaxAgeDays(context) — read it
    • sweepIfDue(context, recordingDir) — delete files older than the threshold, throttled to one run per 24h
  • ARApplication.onCreate calls sweepIfDue() with the active recording directory. When max_age_days = 0 it short-circuits, so the patch is dormant unless the user opts in.
  • Storage: a single SharedPreferences file (recordings_retention) holds max_age_days (Int) and last_run (Long). Kept separate from the app's main prefs so restoring main prefs from a backup doesn't unexpectedly arm this feature.

What is not in this PR

A Settings UI to expose max_age_days. I'm intentionally keeping this PR to the engine — the UX call (a number field in SettingsActivity? A duration picker? A dropdown with presets like 30/90/365 days?) is a maintainer choice. Until a UI lands the feature is dormant (the engine is already wired in ARApplication.onCreate).

If you'd prefer me to bundle a Settings row in this same PR, happy to extend. I left it out because:

  1. Reviewing a single self-contained utility is cheaper than reviewing a Settings flow at the same time.
  2. The UI fits your existing aesthetic better if you design it.

Safety properties

  • Default offmax_age_days = 0 is the initial value; no sweep ever runs unless the user explicitly sets a non-zero value.
  • 24h throttlelast_run timestamp prevents repeat scans on rapid app re-launches or process restarts.
  • runCatching per file — a single file that can't be deleted (FS busy, permission edge-case) doesn't abort sweep on the remaining files.
  • Only regular files — only entries where file.isFile && file.lastModified() < cutoff are deleted. Never the directory itself, never subfolders.
  • No external services — pure on-device, no network, no notifications.

Files

  • app/src/main/java/com/dimowner/audiorecorder/util/RecordingsRetention.kt (new, 57 lines)
  • app/src/main/java/com/dimowner/audiorecorder/ARApplication.kt (+5 lines — the call site)

Tested

  • max_age_days = 0 (default): launching the app shows no log output for the sweep path, no files touched. ✓
  • max_age_days = 30 set via RecordingsRetention.setMaxAgeDays(ctx, 30): launching the app deletes files older than 30 days from the recording dir, leaves newer ones alone. ✓
  • Second launch within 24h: 24h throttle kicks in, no scan. ✓

Why this exists

A long-running user accumulates a lot of voice notes over months; many become irrelevant after a few weeks. Manual cleanup is friction. Other recorder apps in the same niche have offered this for years (Easy Voice Recorder, Smart Voice Recorder); it's a known-good UX. This PR brings the same primitive without forcing a UX choice on you.

Adds an opt-in retention engine that deletes recording files older than
a user-set number of days. Disabled by default (max_age_days = 0); no
behavior change for existing users.

How it works
------------
- New util/RecordingsRetention object exposes setMaxAgeDays/getMaxAgeDays
  and sweepIfDue(context, dir).
- ARApplication.onCreate calls sweepIfDue() with the recording dir; the
  sweep no-ops when max_age_days is 0 or when last_run < 24h ago.
- Storage: a single SharedPreferences file (recordings_retention) holds
  max_age_days (int) and last_run (long). Independent of the app's main
  prefs — restoring main prefs from a backup won't unexpectedly arm
  this.

What is NOT in this PR
----------------------
A Settings UI to expose max_age_days. I'm intentionally keeping this
PR to the engine — the UX (a number field in SettingsActivity?
a duration picker?) is a maintainer choice. Until a UI lands the
feature is dormant (the engine is already wired in ARApplication).
If you'd prefer me to add a Settings row in this same PR, happy to.

Safety
------
- 24h throttle prevents repeat scans on rapid app re-launches.
- File deletion is wrapped in runCatching — a stuck file doesn't
  break sweep on remaining files.
- Only files with lastModified < cutoff are deleted; never the
  directory itself, never subfolders.

35 LOC of Kotlin + 5-line hook in ARApplication.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant