I'm building an app which generates sounds and needs to monitor their volume. I'm trying to use HealthKit for it and this is what I have done so far:
private let healthStore = HKHealthStore()
func observeHeadphoneAudio() {
guard let type = HKObjectType.categoryType(forIdentifier: .headphoneAudioExposureEvent) else {
return
}
healthStore.requestAuthorization(toShare: nil, read: [type]) { [weak self] success, error in
if let error = error {
log.warning(error.localizedDescription)
} else if success {
self?.fetch(type: type)
}
}
}
func fetch(type: HKCategoryType) {
let descriptor = HKQueryDescriptor(sampleType: type, predicate: nil)
let query = HKObserverQuery(queryDescriptors: [descriptor]) { query, samples, completion, error in
if let error = error {
log.warning(error.localizedDescription)
}
if let samples = samples {
log.info(samples)
}
}
healthStore.execute(query)
}
I'm starting it while generating a sound, query completion is executed once with empty samples set, and that's it.
What is the proper way to monitor headphone audio exposure?
CodePudding user response:
Are you looking for headphone audio exposure or headphone audio exposure event? The latter is generated when you exceed headphone audio exposure limits. See
https://developer.apple.com/documentation/healthkit/hkquantitytypeidentifier/3081272-headphoneaudioexposure/ https://developer.apple.com/documentation/healthkit/hkcategorytypeidentifier/3552059-headphoneaudioexposureevent
CodePudding user response:
I changed type of event to headphoneAudioExposure
and created something like this:
private let healthStore = HKHealthStore()
func start() {
authorize { [weak self] type in
self?.runQuery(for: type)
}
}
func authorize(successHandler: @escaping (HKQuantityType) -> Void ) {
guard let type = HKObjectType.quantityType(forIdentifier: .headphoneAudioExposure) else {
return
}
healthStore.requestAuthorization(toShare: nil, read: [type]) { success, error in
if let error = error {
log.warning(error.localizedDescription)
} else if success {
successHandler(type)
} else {
log.warning("Unknown error")
}
}
}
func runQuery(for type: HKQuantityType) {
let startDate = Date()
let predicate = HKQuery.predicateForSamples(withStart: startDate,
end: .distantFuture,
options: .strictStartDate)
let interval = DateComponents(nanosecond: 500_000_000)
let query = HKStatisticsCollectionQuery(quantityType: type,
quantitySamplePredicate: predicate,
options: .mostRecent,
anchorDate: startDate,
intervalComponents: interval)
query.initialResultsHandler = { _, statisticsCollection, error in
log.info("----------INITIAL-----------")
if let error = error {
log.warning(error.localizedDescription)
} else if let lastStatistics = statisticsCollection?.statistics().last {
log.info(lastStatistics.startDate)
log.info(lastStatistics.endDate)
log.info(lastStatistics.mostRecentQuantity())
} else {
log.warning("No statistics yet")
}
log.info("----------INITIAL-----------")
}
query.statisticsUpdateHandler = { _, statistics, _, error in
if let error = error {
log.warning(error.localizedDescription)
} else if let statistics = statistics {
log.info("---------UPDATE------------")
log.info(statistics.startDate)
log.info(statistics.endDate)
log.info(statistics.mostRecentQuantity())
log.info(statistics.quantityType)
}
}
healthStore.execute(query)
}
Problem with this code is that sometime it's working sometime is not, and I have no idea why. Also, when I'm able to get some data in statisticsUpdateHandler
they are coming in packets once per 60-70 seconds.
Any suggestions, what am I doing wrong?