Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2026 System Services

WWDC26 · 8 min · System Services

Find your accessory with Bluetooth Channel Sounding

Get started with Channel Sounding to bring distance and direction awareness to your Bluetooth accessories. Dive into the new Nearby Interaction and Core Bluetooth APIs, and walk through the accessory-side changes you’ll need. Optimize power consumption while ensuring a smooth, responsive experience.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 4 snippets

Start a Core Bluetooth Channel Sounding session swift · at 3:43 ↗
import CoreBluetooth

func isChannelSoundingSupported() -> BOOL {
    guard centralManager.state == .poweredOn else { return }
    if #available(iOS 27.0, *) {
        // Check current device supports Bluetooth Channel Sounding
        return CBCentralManager.supportsFeatures(.channelSounding)
    }
}

func startChannelSounding(_ peripheral: CBPeripheral) {
    guard peripheral.isConnected else { return }
    if #available(iOS 27.0, *) {  
        // Step 1: Create a CBChannelSoundingSessionConfiguration
        let config = CBChannelSoundingSessionConfiguration(role: .initiator)

        // Step 2: Start the channel sounding session
        peripheral.startChannelSoundingSession(config)
    }
}
Receive distance results and cancel a session swift · at 4:09 ↗
import CoreBluetooth

// Receive distance results
func peripheral(_ peripheral: CBPeripheral,
                didReceive results: CBChannelSoundingProcedureResults?,
                error: Error?) {
    guard let results = results else { return }

    let distance = results.distance
    
    // Do something with distance
}

// Cancel a Channel Sounding session
func cancelChannelSounding(_ peripheral: CBPeripheral) {
    guard peripheral.isConnected else { return }
    if #available(iOS 27.0, *) {
        // Cancel the channel sounding session
        peripheral.cancelChannelSoundingSession(config)
    }
}

func peripheral(_ peripheral: CBPeripheral,
                didCompleteChannelSoundingSession error: Error?) {   
    // Session is complete
}
Start a Nearby Interaction Channel Sounding session swift · at 4:41 ↗
import CoreBluetooth
import NearbyInteraction

// Configure a Nearby Interaction Channel Sounding session
func startChannelSoundingThroughNearbyInteraction(_ peripheral: CBPeripheral) {
    if #available(iOS 27.0, *) {        
        // Step 1: Check current device supports Bluetooth Channel Sounding
        guard NISession.deviceCapabilities.supportsBluetoothChannelSounding else { return }

        // Step 2: Create an NINearbyAccessoryConfiguration
        let config = NINearbyAccessoryConfiguration(
            bluetoothChannelSoundingIdentifier: peripheral.identifier, 
            previousChannelSoundingIdentifier: nil)

        // Step 3: Enable camera assistance for direction support
        if NISession.deviceCapabilities.supportsCameraAssistance { 
            config.isCameraAssistanceEnabled = true
        }
    }
}
Run a Nearby Interaction Channel Sounding session swift · at 5:19 ↗
import CoreBluetooth
import NearbyInteraction

// Run a Nearby Interaction Channel Sounding session
func runChannelSoundingThroughNearbyInteraction(_ config: NINearbyAccessoryConfiguration) {
    // Create an NISession
    let session = NISession()
    session.delegate = self
    // Run the NISession with the accessory configuration
    session.run(config)
}

// Improve Nearby Interaction direction outputs
func updateAccessoryMotionState(_ isMoving: Bool) {
    NIMotionActivityState motionState = isMoving ? .moving : .stationary
    
    // Tell NISession about.the accessory's motion state
    session.updateMotionState(motionState, forObjectWithToken: object.discoveryToken)
}

// Receive NISession updates
func session(_ session: NISession, didUpdate nearbyObjects: [NINearbyObjects]) {   
    guard let object = nearbyObjects.first else { return }

    if let distance = object.distance {
        // Do something with distance
    }

    if let direction = object.horizontalAngle {
        // Do something with horizontal angle
    }
}

Resources