2

I have a watchOS3 workout app that uses haptic notifications. It setup correctly to run a workout session and haptics work when running in the background. However, if bluetooth headphones are connected to the apple watch, then you only get the haptic vibration OR the audio chime for the haptic, depending on whether the app is currently showing on the watch face or running in background.

Here's how I'm playing the haptic:

WKInterfaceDevice.current().play(.notification)

Here are the details:

  • Apple Watch Nike+ Unpaired to Headphones: Haptic and chime sound activate regardless of whether the watch face is on or off. Chime sound is loud and clear.

  • Apple Watch Nike+ Paired to Bluetooth Headphones: Haptic only active if watch face is on, audio chime is off. Audio chime is on when watch face is off, haptic is off. Chime sound is loud and clear.

I tested the app pairing the Apple Watch separately with the Platronic Backbeat Go 2 (released 7/2013) and the Bose QuietControl 30 (released 10/2016). The results were the same.

Anyone know if this is a limitation of watchOS 3, a bug, or is there something else I need to be doing?

Thanks, Jeff

Ketan P
  • 4,259
  • 3
  • 30
  • 36
jeffbailey
  • 137
  • 6

2 Answers2

0

There's another factor to consider, which is whether the main Watch mute switch is on or off.

I found the following to be a suitable workaround.

When you want your audio/haptic to be noticed while music is playing on Bluetooth Headphones, have this AVAudioSession category set:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)

Then, when you're done with your audio/haptic, reset the AVAudioSession back to:

AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)

I have this helper class to help manage the states:

import AVFoundation

enum AudioPlaybackState {
    case playback
    case playbackDuckOthers
}

class AVAudio {
    private init() {}   // strictly a helper class

    static func setAudioState(_ state: AudioPlaybackState) {
        DispatchQueue.main.async {
            do {
                deactivateAudioSession()
                switch state {
                case .playback:
                    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .mixWithOthers)
                case .playbackDuckOthers:
                    try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, with: .duckOthers)
                }
                activateAudioSession()
            } catch {}
        }
    }

    static func deactivateAudioSession() {
        activateAudioSession(false)
    }

    private static func activateAudioSession(_ value: Bool=true) {
        do {
            try AVAudioSession.sharedInstance().setActive(value)
        } catch {}
    }
}

Then, I can switch quickly by: AVAudio.setAudioState(.playbackDuckOthers)

Hoon
  • 31
  • 1
  • 4
  • Is this working still in the latest WatchOS 6? I cant seem to get any haptics to trigger when the app is backgrounded and playing music via bluetooth headphones – bencallis Jun 11 '20 at 01:36
0

The behavior documented in the question is the the way its supposed to be, according to Apple. The given reason is because of the delay between the haptic tap and the haptic audio when using bluetooth headphones. I'm hoping this behavior changes in the future...

jeffbailey
  • 137
  • 6