Skip to content

Send DULT Sound_Stop when continuous ringing is stopped - #242

Merged
parawanderer merged 2 commits into
parawanderer:mainfrom
alex-so-3:fix/dult-sound-stop
Oct 13, 2026
Merged

parawanderer merged 2 commits into
parawanderer:mainfrom
alex-so-3:fix/dult-sound-stop

Conversation

@alex-so-3

@alex-so-3 alex-so-3 commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Stopping continuous ringing only stopped the app from re-triggering the sound. A DULT accessory (third-party Find My trackers) kept sounding until its own timeout.

AccessorySoundTrigger gets a stopSound, and the BLE implementation writes the DULT Sound_Stop opcode (0x0301) to the non-owner control point when the user stops ringing. AirTags have no stop command in the paths this app uses and stop by themselves, so nothing changes for them.

Verified: on a phone, with a commercial DULT tracker and with a DIY tag that implements DULT: the sound now stops when ringing is stopped. It stops with a short delay, because the app first has to connect to the tracker to send the command. ./gradlew testAll and add_strings.py --check pass.

Stopping only ended the re-triggering, so a DULT accessory kept sounding until its
own timeout. AirTags have no stop command and stop by themselves; unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016xeHfDLMuUeusX9PEgNEmY
@parawanderer

Copy link
Copy Markdown
Owner

Thanks for checking this + the fix & contribution. Checking this for issues and seeing if it makes sense to add a test to cover this...

@parawanderer parawanderer added bug Something isn't working @app Issues regarding the OpenTagViewer Android app labels Oct 13, 2026
stopSound now goes through an injected GattStopper seam like the rest of BleAccessorySoundTrigger, so the JVM suite covers it: permission, no candidates, not found, found, and a failing stop.

The stop is sent only when the ping actually rang over DULT, so stopping an AirTag no longer costs a scan and a connection. A new ping for the same tag cancels a stop still in flight, which could otherwise arrive after the new start and silence it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@parawanderer

Copy link
Copy Markdown
Owner

Pushed 09f2abb on top:

  • stopSound goes through an injected GattStopper seam instead of instanceof BluetoothDevice plus a static call, so BleAccessorySoundTriggerTest covers it: no permission, no candidates, not nearby, found, and a failing stop.
  • The stop is only sent when the ping actually rang over DULT (BleSoundTriggerResult.hasStopCommand). Stopping an AirTag no longer costs a scan and a GATT connection.
  • Starting a new ping for the same tag cancels a stop still in flight. Before, that stop could arrive after the new Sound_Start and silence it.
  • Imports instead of fully qualified names, braces on the one-line ifs, and the unused async variable is gone.

Drafted by Claude Code, reviewed by @parawanderer

@parawanderer
parawanderer deployed to Android Build October 13, 2026 09:16 — with GitHub Actions Active
@parawanderer
parawanderer deployed to Android Build October 13, 2026 09:16 — with GitHub Actions Active
@parawanderer
parawanderer merged commit d8ce2e0 into parawanderer:main Oct 13, 2026
4 checks passed

This branch was successfully deployed

1 active deployment
Android Build — 09f2abb0 Deployed Oct 13, 2026 by parawanderer via build #315
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

@app Issues regarding the OpenTagViewer Android app bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants