iOS 17.4 (21E217) CMAltimeter not working

I have apps using CMAltimeter to get sensor data, but recently they stop working with iOS 17.4, it is not release but some user running beta version, the is no access to the sensor data anymore (altitude and barometer). Some user report they can fix it by manual the "Motion & Fitness" permission but it only appear on some device. Report has been sent to Apple but I post here to find the solution to fix it.

Answered by DTS Engineer in 783549022

Hello all, as you may have realized by now, 17.4.1 has not fixed the problem you have been seeing.

I would like to first clarify what problem we are talking about, and for what problem we are recommending a workaround and waiting for a fix. The "problem" is twofold:

  1. Starting with iOS 17.4 using CMAltimeter requires the declaration of NSMotionUsageDescription, authorization by the user, and have not turned off Fitness Tracking in settings:

This is not a bug. This is a permanent change per privacy requirements, and it is not going to go back to a state as before iOS 17.4, so you must change your app to include this privacy change.

  1. Along with the above change, there was a behavior mismatch where if the app is only using CMAltimeter APIs like startRelativeAltitudeUpdates() in a simple pattern, this was not triggering the authorization prompt necessary for the altimeter data to be accessed. Apps that were already using other APIs that required this permission earlier, do not run into this issue.

This behavior is the one we are looking to change, where simply using CMAltimeter in a simple pattern will be enough to obtain the authorization. This change was not made in 17.4.1 but is being investigated for a future version.

To alleviate this, I had suggested a workaround using the CMPedometer API that was going to trigger the authorization prompt, after which apps only using CMAltimeter would work without issues. While that workaround we came up with quickly still works, we now have a better recommendation that does not require the use of another API, and we believe is more power efficient and has wider support of devices. The new recommended workaround is this:

func startAltitudeUpdatesViaMotionManager() {
    self.motionActivityMotionManager.queryActivityStarting(from: .now, to: .now, to: .main) { _, _ 
    in
    self.altimeterManager.startRelativeAltitudeUpdates(to: .main) { altitudeData, error
        // Handle altitude updates
    }
  }
}

If you call startRelativeAltitudeUpdates() using this pattern, this will solve the issue of the authorization prompt not appearing when using a more simple pattern. Also, this does not require the use of an unrelated and API which you would want to rush to remove from your code once a change is made to have the simple call patterns to trigger the authorization dialog.

None of the iOS Barometer apps seem to be working since 17.4...

There is a work around for it but it is not working on iPad OS 17.4 and iPhone SE, Many of our users are angry, they just gave us 1 star and bad commend. Some other guy using MAUI https://github.com/dotnet/maui/issues/20930 report it too.

We are seeing the same issue: https://github.com/justinchuby/barometer-project/issues/8.

Looks like CMAltimeter.authorizationStatus() shows notDetermined, and I have not found a good way to request this authorization.

Found a workaround.

Apparently the issue is that as of 17.4, CMLAltimeter startRelateiveAltitudeUpdates not needs "Motion & Fitness" permission. However, normally in iOS just using a service requiring the permission will initiate the permission prompt by iOS to the user.

The trick it to force requesting permission. let recorder = CMSensorRecorder() recorder.recordAccelerometer(forDuration: 0.1)

will prompt the user for permission. Once granted, relative altitude data works.

Found a workaround. Apparently the issue is that as of 17.4, CMLAltimeter startRelateiveAltitudeUpdates not needs "Motion & Fitness" permission. However, normally in iOS just using a service requiring the permission will initiate the permission prompt by iOS to the user. The trick it to force requesting permission.

let recorder = CMSensorRecorder() recorder.recordAccelerometer(forDuration: 0.1)

will prompt the user for permission. Once granted, relative altitude data works.

Found a workaround but my post is being reviewed.

let recorder = CMSensorRecorder() 
recorder.recordAccelerometer(forDuration: 0.1)

Requests permission and gets it working.

I have submitted feedback FB13680923 on this issue, as I see no correct way to solve the problem from the developer side (proposed workaround is not a universal fix since not all devices support sensor recording).

I suggest that everybody who has the issue, files a bug report to Apple, in order to get some priority on this.

Note that the following is a work-around. I urge everybody to file a bug-report with Apple, to make sure there is pressure on Apple to fix this.

Others have suggested the CMSensorRecorder work-around. It turns out that the "Fitness Tracking" setting in the Settings App needs to be enabled for that to work.

When the authorizationStatus is .restricted, then the user first needs to switch on Settings > "Privacy & Security" > "Motion & Fitness" > "Fitness Tracking"

When the authorizationStatus is .notDetermined, then start the CMSensorRecorder. A "Motion & Fitness" privacy settings will be added to your app's settings, and the user will be asked to authorise by iOS. When the user accepts, authorizationStatus changes to .authorized and you can start the CMAltimeter.

When the authorizationStatus is .denied, the user needs to switch on the "Motion & Fitness" privacy setting of your app.

The following code worked for me:

            let status = CMAltimeter.authorizationStatus()
            switch status {
            case .notDetermined:
                // trigger a authorization popup
                let recorder = CMSensorRecorder()
                DispatchQueue.global().async {
                    recorder.recordAccelerometer(forDuration: 0.1)
                }
            case .restricted:
                popupText = "Please switch \"Fitness Tracking\" on, in the Apple Settings app, under \"Privacy & Security\" > \"Motion & Fitness\""
                showingPopup = true
            case .denied:
                popupText = "Please switch \"Motion & Fitness\" on, in the app settings"
                showingPopup = true
            default:
                print("authorized")
            }
            Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { timer in
                let status = CMAltimeter.authorizationStatus()
                if status == .authorized {
                    timer.invalidate()
                    self.altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) { (data, _error) in
                       // handle altimeter data
                    }
                }
            }

@baraupp I file bug before it release 1 day but not communication on the feedback and they still release it.

The CoreMotion team is on the case, and is looking for a solution. But I am sure you would all appreciate that fixing and releasing a problem in an operating system is not a matter of a day or two.

I would like to thank everyone here who has been suggesting workarounds to get the authorization prompt to popup, which in turn enables CMAltimeter to start working. That is indeed a good solution. Although, the API suggested here, CMSensorRecorder has a large power impact, and we do not recommend to use that as your temporary fix. CMPedometer is not only less power hungry, but also has the widest availability on iOS versions and actual devices.

So, if you were to use

CMPedometer().queryPedometerData(from: Date(), to: Date()){ (data, error) -> Void in }

somewhere in your code as appropriate, this should temporarily solve your issue. @baraupp 's solution is a clean encapsulation, and could be used by replacing CMSensorRecorder calls with CMPedometer calls.

Also to confirm @baraupp 's findings, "Fitness Tracking" must indeed be turned on in Settings for the pedometer solution to work as well.

[@Gualtier Malde](https://developer.apple.com/forums/profile/Gualtier Malde) Thanks for your response here! At this point, do you think it's worth making the effort to release a build with a workaround? Or should we wait and see if a fix is in the upcoming 17.4.1 update? We could probably only handle a couple more weeks before this issue impacts a significant enough number of our users that we will have to do the workaround, but we don't want to push it out if it's not necessary.

Thanks!

Latest 17.4.1 not solve the problem, sadly. [@Gualtier Malde](https://developer.apple.com/forums/profile/Gualtier Malde) is there any timeline for this bug? I lost many customer and revenue due to this bug.

Hello all, as you may have realized by now, 17.4.1 has not fixed the problem you have been seeing.

I would like to first clarify what problem we are talking about, and for what problem we are recommending a workaround and waiting for a fix. The "problem" is twofold:

  1. Starting with iOS 17.4 using CMAltimeter requires the declaration of NSMotionUsageDescription, authorization by the user, and have not turned off Fitness Tracking in settings:

This is not a bug. This is a permanent change per privacy requirements, and it is not going to go back to a state as before iOS 17.4, so you must change your app to include this privacy change.

  1. Along with the above change, there was a behavior mismatch where if the app is only using CMAltimeter APIs like startRelativeAltitudeUpdates() in a simple pattern, this was not triggering the authorization prompt necessary for the altimeter data to be accessed. Apps that were already using other APIs that required this permission earlier, do not run into this issue.

This behavior is the one we are looking to change, where simply using CMAltimeter in a simple pattern will be enough to obtain the authorization. This change was not made in 17.4.1 but is being investigated for a future version.

To alleviate this, I had suggested a workaround using the CMPedometer API that was going to trigger the authorization prompt, after which apps only using CMAltimeter would work without issues. While that workaround we came up with quickly still works, we now have a better recommendation that does not require the use of another API, and we believe is more power efficient and has wider support of devices. The new recommended workaround is this:

func startAltitudeUpdatesViaMotionManager() {
    self.motionActivityMotionManager.queryActivityStarting(from: .now, to: .now, to: .main) { _, _ 
    in
    self.altimeterManager.startRelativeAltitudeUpdates(to: .main) { altitudeData, error
        // Handle altitude updates
    }
  }
}

If you call startRelativeAltitudeUpdates() using this pattern, this will solve the issue of the authorization prompt not appearing when using a more simple pattern. Also, this does not require the use of an unrelated and API which you would want to rush to remove from your code once a change is made to have the simple call patterns to trigger the authorization dialog.

I learned that this issue also prevents independent Watch apps from accessing CMAltimeter if their parent iPhone has been updated to 17.4-17.4.1, since iPhones manage privacy settings for their companion Watches. The workaround suggested above using "CMMotionActivityManager queryActivityStartingFromDate" works for Watch apps, with the caveat that I could not find any way for my Watch app to determine the iOS version of the parent iPhone, thus it's not possible to be selective about when to invoke the workaround.

I have long thought it was somewhat disjointed the way an independent Watch app still depends on the parent iPhone to manage privacy settings -- for many reasons -- and this is one more example why it's a bad arrangement.

iOS 17.4 (21E217) CMAltimeter not working
 
 
Q