Skip to content

Implementation ​

This guide uses iOS SDK 5.1.0. See installation and update instructions.

Configure the recognizer ​

Import the SORI framework and configure the shared recognizer with your SORI application credentials.

swift
import SORI

let recognizer = SORIAudioRecognizer.shared()
let configuration = SORIAudioRecognizer.Configuration(
    applicationID: "YOUR_SORI_APP_ID",
    secretKey: "YOUR_SORI_SECRET_KEY"
)

recognizer.configure(configuration)

Start recognition ​

Call startRecognition(repeat:handler:) after configuration. The handler receives the campaign payload returned by SORI API when a registered material is recognized.

swift
recognizer.startRecognition(repeat: true) { media, error in
    if let error {
        print("SORI recognition error: \(error)")
        return
    }

    guard let campaign = media as? [String: Any] else {
        return
    }

    handleRecognizedCampaign(campaign)
}

Enable Audio Marker recognition ​

Audio Marker recognition is disabled by default. In the default mode, iOS recognition remains fingerprint-only. Enable it only when your SORI Console setup uses Audio Markers.

swift
let configuration = SORIAudioRecognizer.Configuration(
    applicationID: "YOUR_SORI_APP_ID",
    secretKey: "YOUR_SORI_SECRET_KEY"
)
configuration.audiomarker = true

recognizer.configure(configuration)

For current-marker UI and later activity enrichment, use the SDK-managed state and activity result APIs. The SDK manages expiry, marker traits and updates to the same activity. Existing campaign and discovery callbacks remain compatible.

Render an ordered continuous-activity timeline ​

The following guidance is for existing campaign callbacks. For the new SDK-accepted activity results, use the exact-ID update rules in Audio Marker state and activity results; these results can update the matching historical activity.

The recognition handler can first return a campaign for a material and later return a marker-refined campaign for that same activity. Show the first result immediately, but keep an explicit current segment in application state. The public payload dictionary may provide activity_id, material_id, and trait.marker.

  • A non-empty activity_id may refine only the current row with that exact ID. Do not search the complete timeline by activity, campaign, or material ID.
  • Older payloads may omit activity_id. In that case, a material_id fallback is safe only for the current row and must not become a global identity.
  • Retain the time, position, and other first-observation metadata stored for the row. The later callback updates marker and campaign presentation fields, not the original observation.
  • Merge marker and refined campaign values so later marker misses or less complete duplicate payloads cannot downgrade the current row.
  • A different material_id seals the previous segment. Ignore delayed refinements for an older activity after that boundary.

Therefore A(activity-1) -> A'(activity-1, marker) -> A(activity-1, marker miss) is one row, while A(activity-1) -> B(activity-2) -> delayed A'(activity-1) keeps B current and does not rewrite the historical A.

Stop recognition ​

Stop recognition when your app no longer needs microphone capture.

swift
recognizer.stopRecognition()

Background recognition ​

If your app needs background recognition, add audio to UIBackgroundModes in Info.plist. Background recognition works while the app is running. If the app is terminated, recognition also stops.

Error handling ​

Recognition errors are delivered through the recognition handler and SORI error notifications. To observe error notifications, register for SORIError.errorNotificationName():

swift
NotificationCenter.default.addObserver(forName: SORIError.errorNotificationName(), object: nil, queue: OperationQueue.main) { notification in
    guard let error = notification.object as? NSError,
          let code = SORIErrorCode(rawValue: error.code) else {
        print("Unknown error notification: \(notification)")
        return
    }

    if code == .authenticationFailure {
        print("Failed to authenticate")
    }
}