github TrackerControl/tracker-control-android 2026102901
Version 2026102901

3 hours ago

Download the latest version here.

  • Refreshed UI of Timeline, Insights, and app details
  • Choose which apps use the remote VPN
  • Import WireGuard profiles by QR code, file, or ZIP
  • More reliable VPN, DNS, tethering, and tracker detection
  • Reduced screen-off battery use
  • Updated tracker lists, translations, and dependencies
  • Many bug fixes

What's Changed

  • Stop asking about Private DNS during onboarding, notify when it breaks by @kasnder in #711
  • Notice a pinned Private DNS when it happens, and warn in the app too by @kasnder in #713
  • deps: bump gradle-wrapper from 9.6.1 to 9.7.0 in the gradle-minor-patch group by @dependabot[bot] in #717
  • deps(rust): bump base64 from 0.23.0 to 0.23.1 in /wgbridge-rs in the cargo-minor-patch group by @dependabot[bot] in #716
  • deps: bump androidx.appcompat:appcompat from 1.7.1 to 1.8.0 in the gradle-minor-patch group by @dependabot[bot] in #726
  • Split agent guidance into a shared agents/ directory and add a Gradle quiet hook by @kasnder in #727
  • Restore DNS policy parity under WireGuard by @kasnder in #738
  • Replace the three per-app toggles with one protection state by @kasnder in #729
  • Route apps around the remote VPN without leaving TrackerControl by @kasnder in #730
  • Collapse the per-app controls into rows that open on demand by @kasnder in #733
  • Decide per-app routing once, in Rust, with tests by @kasnder in #737
  • Guard the agent-config topology with a unit test by @kasnder in #728
  • Dedup DNS attribution rows in one pass, not per candidate row by @kasnder in #741
  • Fix two battery risks in the per-app remote routing feature by @kasnder in #742
  • Align lockdown troubleshooting text with actual behaviour (#743) by @kasnder in #745
  • Deduplicate DNS response rewriting by @kasnder in #739
  • Skip SNI research mode for tunnelled flows by @kasnder in #744
  • Fix offline release build failing on desugar_jdk_libs (CI failure blocking #718) by @kasnder in #746
  • ci: bump the actions group across 1 directory with 2 updates by @dependabot[bot] in #718
  • Gate DoH retries and keep-alives on screen state by @kasnder in #747
  • Bound the update check's network calls with timeouts by @kasnder in #748
  • Synchronize TrackerBlocklist access across packet and UI threads by @kasnder in #750
  • Fix misc correctness bugs: channel bypass-DND, atomic hosts rename, locale, fresh-install version by @kasnder in #755
  • Serialize WG profile store and fix rotation recovery by @kasnder in #754
  • Gate TCP DNS answer recording on known framing by @kasnder in #767
  • Slow the WG connectivity watchdog when the screen is off by @kasnder in #749
  • Fix ServiceSinkhole thread leak and teardown races by @kasnder in #752
  • Harden DNS proxy pool, TCP framing, and fallback validation by @kasnder in #753
  • Cap the DoH response read at 65535 bytes (#761) by @kasnder in #771
  • Trip the DoH circuit breaker per attempt and drop the dead delayed-screen-off alarm by @kasnder in #768
  • Debounce database change notifications without sleeping the handler thread by @kasnder in #770
  • Fix memory-safety and hang bugs in native packet engine by @kasnder in #751
  • Normalise DNS qnames to lowercase on the database write path by @kasnder in #772
  • Fix blocklist load integrity: short reads and premature hosts mtime stamp by @kasnder in #773
  • Fix WireGuard rotation edge cases (#766) by @kasnder in #774
  • Count an oversized DoH body as a failed attempt (#760) by @kasnder in #775
  • Align the UI's shared-IP view with the runtime blocking decision (#759) by @kasnder in #776
  • Fix DNS cache invalidation race in tracker attribution by @kasnder in #777
  • Fix IPv6 extension header walk in handle_ip() by @kasnder in #778
  • Document the fragmented-traffic drop on the direct path (#779) by @kasnder in #780
  • deps: bump the gradle-minor-patch group with 4 updates by @dependabot[bot] in #783
  • Re-apply horizontal padding on configuration change by @kasnder in #793
  • Say what clearing an app's activity does, and confirm it first by @kasnder in #794
  • Fix route prefixes, stale tracker caches and blocklist loss by @kasnder in #790
  • Let a user-initiated start clear the background-user flag by @kasnder in #792
  • Retry a failed VPN replacement instead of stranding a blocking tunnel by @kasnder in #791
  • deps(rust): bump gotatun from 0.8.1 to 0.9.0 in /wgbridge-rs by @dependabot[bot] in #782
  • Port ProtectedUdpFactory to the gotatun 0.9 UDP API by @kasnder in #796
  • Fix alarm timebase, guard numeric prefs, and small correctness nits by @kasnder in #800
  • Warn when a routed LAN resolver loses non-DNS traffic by @kasnder in #799
  • Skip tracker-cache invalidation for refreshed DNS rows by @kasnder in #802
  • Run the network validation probe off the ConnectivityManager thread by @kasnder in #801
  • Retry failed WireGuard startup by @kasnder in #803
  • Publish tracker cache entries atomically by @kasnder in #804
  • Publish tracker-list reloads atomically by @kasnder in #805
  • Recover WireGuard monitoring after stats failures by @kasnder in #806
  • Address review nits from #803, #804, #805 and #806 by @kasnder in #810
  • Accessibility follow-ups from #636: contrast, stat grouping, announcements by @kasnder in #815
  • Preserve DDG's hostname-level breakage exceptions in the bundled TDS by @kasnder in #814
  • Use safer --force-with-lease refspec when pushing update-lists branch by @kasnder in #818
  • Update bundled tracker/host lists by @github-actions[bot] in #821
  • Advertise iOS version in About dialog by @kasnder in #812
  • Walk every DNS-over-TCP frame per recv() with a bufferless stream cursor by @kasnder in #816
  • Guide Proton VPN WireGuard config import by @kasnder in #813
  • Warn when encrypted DNS silently defeats tracker detection by @kasnder in #817
  • Migrate Crowdin synchronization to GitHub Actions by @kasnder in #823
  • Allow reviewed repository translations to sync to Crowdin by @kasnder in #825
  • New Crowdin translations by @github-actions[bot] in #824
  • Define the tc-dns C ABI in the wgbridge cdylib crate by @kasnder in #827
  • Block DNS-over-TCP responses split across socket reads by @kasnder in #828
  • Merged Protection screen with a temporary per-app pause by @kasnder in #826
  • Stop UID-keyed state from outliving the app that set it by @kasnder in #829
  • Dedupe the UID-keyed stores and stop sweeping them on every install by @kasnder in #830
  • Blocking-mode UX: timeline pointer, mode-independent compatibility exclusions, per-app essential blocking by @kasnder in #834
  • New Crowdin translations by @github-actions[bot] in #833
  • Untangle the app details screens by @kasnder in #835
  • Minimal mode: monitor with every tracker list, block only the DuckDuckGo set by @kasnder in #839
  • Rename per-app "essential-only" to "minimal-only" (Minimal blocking only) by @kasnder in #841
  • New Crowdin translations by @github-actions[bot] in #837
  • New Crowdin translations by @github-actions[bot] in #842
  • Finish the Material 3 migration in the theme and cards by @kasnder in #840
  • Reintroduce the tracker explanation at the top of the Trackers tab by @kasnder in #845
  • Close the details screen when the intent names no app by @kasnder in #846
  • Surface Proton VPN setup on the VPN tab by @kasnder in #843
  • Redesign TRACKERS tab as calm category feed by @kasnder in #847
  • Flatten Manage App data-rights sections by @kasnder in #849
  • Modernise the per-app protection screen by @kasnder in #850
  • Make tracker company rows responsive by @kasnder in #851
  • Add stable Compose foundation for app details by @kasnder in #853
  • Migrate Data Rights details to Compose by @kasnder in #854
  • Migrate Trackers details to Compose by @kasnder in #855
  • Migrate Countries details to Compose by @kasnder in #856
  • Migrate Tracker Libraries to Compose by @kasnder in #857
  • Migrate Protection details to Compose by @kasnder in #858
  • Migrate Insights to Compose by @kasnder in #862
  • Migrate Blocklists to Compose by @kasnder in #863
  • Migrate Timeline to Compose by @kasnder in #864
  • Migrate WireGuard profiles to Compose by @kasnder in #865
  • Unify Material colours and headings by @kasnder in #866
  • Polish tracker insights and domain grouping by @kasnder in #867
  • Polish Data Rights and Countries details by @kasnder in #868
  • Request local network access from Troubleshooting by @kasnder in #869
  • Unify screens on Material surface roles by @kasnder in #870
  • Align main tab typography with Material 3 by @kasnder in #871
  • Polish the Compose migration stack for release by @kasnder in #876
  • Codex/issue 832 calm category feed by @kasnder in #877
  • Re-register a deleted provider device instead of reusing its dead key by @kasnder in #861
  • Refresh copyright notices by @kasnder in #844
  • New Crowdin translations by @github-actions[bot] in #848
  • Cut avoidable main-thread work in the Compose details screens by @kasnder in #879
  • Add WireGuard profiles via QR code by @kasnder in #878
  • Take per-app protection writes off the main thread by @kasnder in #883
  • ci: bump actions/setup-java from 5 to 6 in the actions group by @dependabot[bot] in #881
  • deps(rust): bump the cargo-minor-patch group in /wgbridge-rs with 2 updates by @dependabot[bot] in #880
  • Persist unresolved package names when saving details-screen blocklist by @kasnder in #886
  • Stop clearing every network session when the device leaves Doze by @kasnder in #887
  • Fix five high-severity bugs from the codebase review by @kasnder in #889
  • Fix resource leaks on TCP connect failure and service teardown by @kasnder in #890
  • Guard browser intents and preserve pending internet-block entries by @kasnder in #885
  • Cut two avoidable battery costs from the codebase review by @kasnder in #896
  • Fix four protocol bugs in the native packet engine by @kasnder in #897
  • Keep settings import and port forwarding state consistent by @kasnder in #899
  • Fix hosts-list matching misses and harden the DNS path by @kasnder in #900
  • Stop stale async results landing on the wrong view by @kasnder in #901
  • Make WireGuard key rotation crash-consistent and identity-checked by @kasnder in #898
  • Propagate database migration failures instead of swallowing them by @kasnder in #902
  • deps: bump org.jetbrains.kotlin.plugin.compose:org.jetbrains.kotlin.plugin.compose.gradle.plugin from 2.3.21 to 2.4.10 in the gradle-minor-patch group by @dependabot[bot] in #882
  • Toggle WireGuard keepalive per peer instead of reapplying the config by @kasnder in #903
  • Download blocklists conditionally and skip the reload when unchanged by @kasnder in #905
  • Import WireGuard profiles from a file or a zip archive by @kasnder in #907
  • New Crowdin translations by @github-actions[bot] in #908
  • Fix mixed tracker evidence expiry by @kasnder in #910
  • Fix UDP packet-path state handling by @kasnder in #909
  • Fix native credential logging and failed session admission by @kasnder in #921
  • Fix Linux native regression test portability by @kasnder in #922
  • Preserve DNS question provenance and refresh blocking evidence by @kasnder in #924
  • Recover DNS detection across split TCP responses by @kasnder in #925
  • Consolidate bounded DNS and native socket fixes by @kasnder in #926
  • Fix WireGuard verdict caching and TCP overlap handling by @kasnder in #913
  • Implement TCP half-close and back off zero-window probes by @kasnder in #915
  • Recover WireGuard DNS reassembly and TUN write failures by @kasnder in #916
  • Repair remaining TCP/SOCKS5 and WireGuard DNS handling by @kasnder in #919
  • deps(rust): bump gotatun from 0.9.1 to 0.9.2 in /wgbridge-rs in the cargo-minor-patch group by @dependabot[bot] in #929
  • Guard SCREEN_OFF/package-change receivers against RejectedExecutionException by @kasnder in #930
  • New Crowdin translations by @github-actions[bot] in #920
  • Guard main-screen autofill lookup against missing descriptors by @kasnder in #934
  • Improve DoH setup and recover immediately after endpoint changes by @kasnder in #936
  • Keep concurrent ICMP echo identifiers in separate sessions by @kasnder in #939
  • New Crowdin translations by @github-actions[bot] in #938
  • Fix TCP close handling and TUN failure recovery qualification by @kasnder in #942
  • Make displayed values locale-safe by @kasnder in #945
  • Resolve async and adapter lint findings by @kasnder in #943
  • Remove obsolete Android API compatibility paths by @kasnder in #948
  • Preserve app ownership across WireGuard policy reloads by @kasnder in #933
  • Resolve layout and accessibility lint findings by @kasnder in #947
  • Complete missing translations for all locales by @kasnder in #940
  • Resolve remaining locale lint warnings by @kasnder in #944
  • Remove unused Android resources by @kasnder in #949
  • New Crowdin translations by @github-actions[bot] in #950
  • New Crowdin translations by @github-actions[bot] in #951
  • New Crowdin translations by @github-actions[bot] in #955
  • New Crowdin translations by @github-actions[bot] in #958
  • Stop marking unmetered networks as metered while the VPN runs by @kasnder in #960
  • test: move unit tests to Robolectric 4.17 by @kasnder in #963
  • Remove the DHCP responder that hijacks tethered leases by @kasnder in #964
  • deps: bump the gradle-minor-patch group across 1 directory with 3 updates by @dependabot[bot] in #957
  • Compare search domains and excluded routes in Builder.equals by @kasnder in #965
  • Check for a killed VPN from outside the service by @kasnder in #966
  • Remove obsolete legacy watchdog by @kasnder in #967
  • New Crowdin translations by @github-actions[bot] in #961
  • Update bundled tracker/host lists by @github-actions[bot] in #972
  • New Crowdin translations by @github-actions[bot] in #973
  • ci: bump the actions group with 2 updates by @dependabot[bot] in #978
  • deps: bump the gradle-minor-patch group across 1 directory with 6 updates by @dependabot[bot] in #980
  • deps(rust): bump the cargo-minor-patch group across 1 directory with 2 updates by @dependabot[bot] in #984
  • New Crowdin translations by @github-actions[bot] in #985
  • ci: bump actions/upload-artifact from 7.0.1 to 7.0.2 in the actions group by @dependabot[bot] in #986
  • deps: bump the gradle-minor-patch group with 2 updates by @dependabot[bot] in #987
  • deps(rust): bump tokio from 1.53.2 to 1.53.3 in /wgbridge-rs in the cargo-minor-patch group by @dependabot[bot] in #988
  • deps(rust): bump gotatun from 0.9.2 to 0.10.1 in /wgbridge-rs by @dependabot[bot] in #989
  • Route traffic outside a split tunnel's AllowedIPs directly by @kasnder in #981
  • Show a persistent notice when Research disables tracker blocking by @kasnder in #992
  • Clarify custom blocklists and download added lists immediately by @kasnder in #994
  • fix(wgbridge): replace deprecated AsyncFd::with_interest with AsyncFd::register_with_interest by @kasnder in #997
  • fix(wgbridge): rebind UDP sockets to a fresh ephemeral port by @kasnder in #999
  • Reload rules when apps on external storage become available by @kasnder in #998
  • New Crowdin translations by @github-actions[bot] in #993
  • deps(rust): bump the cargo-minor-patch group in /wgbridge-rs with 3 updates by @dependabot[bot] in #1001
  • wg: tell the user when a Mullvad subscription has lapsed by @kasnder in #1005

Full Changelog: 2026080...2026102

Don't miss a new tracker-control-android release

NewReleases is sending notifications on new releases.