Home > Blockchain >  How to monitor headphoneAudioExposureEvent using Apple HealthKit?
How to monitor headphoneAudioExposureEvent using Apple HealthKit?

Time:10-28

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?

  • Related