Audio Marker state and activity results
Since Android 5.0.10, iOS 5.0.9 and Flutter 0.3.5 for Android/iOS, the SDK manages the current Audio Marker state and its association with recognized activities. Enable Audio Marker recognition when your SORI Console application uses it; it remains disabled by default.
Install or update
Render the current marker
Render the state delivered by the SDK. It distinguishes inactive recognition, listening, a detected marker whose identity is unresolved, an identified marker, and cleared state. Only the identified state carries the Audio Marker ID and name resolved by SORI Console. An unresolved detection must not reuse the previous marker name.
The SDK can keep eligible marker evidence for up to four seconds without a fresh detection, but this is not a guaranteed four-second display period. Consecutive misses, low input level (low RMS), silence, a different unidentified marker, or stopping/resetting recognition can clear or invalidate the state. Read the current snapshot or subscribe again when your UI reconnects. Reading a snapshot or receiving a delayed response does not restart the retention period. Applications do not need their own expiry timer.
Update the matching activity
While marker evidence remains eligible, the SDK enriches subsequent material recognition requests through the marker trait (trait.marker). If the material is recognized first and its marker is identified later, the SDK can update that same activity without another successful material match. The SDK manages association and the server update; applications do not need to construct marker traits or send their own update requests.
- Insert or update a result using the exact activity ID supplied by the SDK, including a delayed update to an earlier result. Do not attach the current header marker to whichever result is newest.
- Keep the original recognition time, position and row order when applying an enrichment.
- Clearing the current marker does not remove a marker already accepted for a historical activity. A delayed activity result also does not make that marker current again.
- An activity result may have no campaign. Render its available identity and marker fields without assuming a campaign is present.
Android
Public Android 5.0.12 API reference
Extend SORIListener and use onAudioMarkerStateChanged and onActivityResult. The current snapshot is available as sori.audioMarkerState (getAudioMarkerState() in Java). If you implement ISORIListener directly, also implement the optional ISORIAudioMarkerStateListener and ISORIActivityResultListener interfaces for these callbacks.
import android.util.Log
import com.iplateia.sorisdk.SORIAudioMarkerState
import com.iplateia.sorisdk.SORIActivityResult
import com.iplateia.sorisdk.SORIListener
import com.iplateia.sorisdk.SORIConfig
sori.setConfig(SORIConfig(audiomarker = true))
sori.setListener(this, object : SORIListener() {
override fun onAudioMarkerStateChanged(state: SORIAudioMarkerState) {
// Render the current state; marker is null until identified.
Log.d("SORI", "${state.status}: ${state.marker?.name}")
}
override fun onActivityResult(result: SORIActivityResult) {
// Insert or update the row identified by result.activityId.
Log.d("SORI", "${result.activityId}: ${result.audioMarker?.name}")
}
})
val current = sori.audioMarkerStateiOS
After configuring the recognizer, attach audioMarkerStateHandler and activityResultHandler. Read currentAudioMarkerState when a snapshot is needed. Use weak captures if the handlers reference your view controller.
recognizer.audiomarker = true
recognizer.audioMarkerStateHandler = { snapshot in
// Render the current state; audioMarker is nil until identified.
print(snapshot.state, snapshot.audioMarker?.name ?? "")
}
recognizer.activityResultHandler = { result in
// Insert or update the row identified by result.activityID.
print(result.activityID, result.audioMarker?.name ?? "")
}
let current = recognizer.currentAudioMarkerStateFlutter
On Android and iOS, use audioMarkerStateChanged, activityResult and getCurrentAudioMarkerState(). SORIRecognitionState applies the SDK events and keeps results indexed by activity ID; your app can render currentAudioMarker and activities.
await recognizer.configure(
config: const SORIRecognitionConfig(audiomarker: true),
);
final markerView = SORIRecognitionState();
final markerSubscription = recognizer.events.listen((event) {
if (markerView.accept(event)) {
// Rebuild your UI from markerView.currentAudioMarker and
// markerView.activities. Each result keeps its own activityId.
}
});
final current = await recognizer.getCurrentAudioMarkerState();
if (current != null && markerView.acceptAudioMarkerState(current)) {
// Rebuild the current-marker UI from markerView.currentAudioMarker.
}Cancel markerSubscription when its UI scope is disposed. Keep your existing campaign listener as a fallback for older servers that omit activity IDs.
Compatibility
Existing start/stop flows and campaign/discovery callbacks remain available. For new current-marker UI, use the state API above: a discovery callback is not an expiry notification. Older servers that omit an activity ID still support legacy campaign callbacks but cannot provide the new exact-ID activity result.
Flutter Web retains its existing recognition and event behavior. The new native current-state, expiry and independent late-marker update behavior applies to Android/iOS. getCurrentAudioMarkerState() returns null on Web; do not use it as proof that no marker was detected.
