black and white bed linen

TuneURL SDK Developer Documentation

Easily add audio trigger detection to iOS or Android apps.

Quickstart — iOS

Five steps. Working detector in under ten minutes.

1. Add the framework
Drop TuneURL.xcframework into your Xcode project. The reference app uses a vendored framework in a Dependencies/ folder; Swift Package Manager support is available on request.

2. Bundle the trigger sound
Add trigger_sound.mp3 (provided by TuneURL with your account) to your app target.

3. Initialize the detector
import TuneURL
import AudioStreaming

let triggerURL = Bundle.main.url(
forResource: "trigger_sound", withExtension: "mp3")!
let detector = StreamDetector(triggerURL)

4. Feed PCM from your player
let player = AudioPlayer()

let parse = FilterEntry(name: "detector") { [weak detector] buffer, _ in
detector?.append(buffer)
}
player.frameFiltering.add(entry: parse)

player.play(url: streamURL)

5. Handle matches

detector.matchCallback = { match in
guard match.matchPercentage >= 70 else { return }
DispatchQueue.main.async {
// match.id, match.type, match.name, match.info
self.handleMatch(match)
}
}

That's the full streaming integration. The detector runs continuously on the audio your player decodes. When a trigger is detected and the server returns a match above your threshold, your callback fires on the audio thread — dispatch to main before touching UI.

Quickstart — Android

Android uses a foreground service for OTA capture and the native C++ core for fingerprinting. The reference app wires ExoPlayer's audio sink to the SDK for the streaming path.

1. Add the SDK module
// settings.gradle.kts
include(":tuneurl_sdk")

// app/build.gradle.kts
dependencies {\
implementation(project(":tuneurl_sdk"))
}

2. Configure API endpoints
import com.dekidea.tuneurl.util.TuneURLManager
import com.dekidea.tuneurl.util.Constants

TuneURLManager.updateStringSetting(
context,
Constants.SETTING_SEARCH_FINGERPRINT_URL,
"<your-search-fingerprint-endpoint>"
)
TuneURLManager.updateStringSetting(
context,
Constants.SETTING_INTERESTS_API_URL,
"<your-interests-endpoint>"
)

3. Build OTA detection (microphone)
// Requires RECORD_AUDIO permission

TuneURLManager.startTuneURLService(context)

4. Receive matches

class MatchReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == Constants.SEARCH_FINGERPRINT_RESULT_RECEIVED) {
val match = parseMatch(intent)
// match.id, match.type, match.name, match.info, match.matchPercentage
}
}
}

val filter = IntentFilter(Constants.SEARCH_FINGERPRINT_RESULT_RECEIVED)
ContextCompat.registerReceiver(
context, MatchReceiver(), filter, ContextCompat.RECEIVER_NOT_EXPORTED
)

For the streaming path with ExoPlayer, see the reference app's CapturingRenderersFactory and StreamAudioCapture, which tap decoded PCM and forward it to the SDK's fingerprinter.

The two detection paths

The SDK supports two ways to get audio into the fingerprinter. You can use one or both in the same app.gOTA (microphon

©Copyright 2026. All rights reserved.