As I’ve mentioned many times before, iOS had a pretty terrible privacy flaw in that apps didn’t need any permissions in order to read through your media library. This was an issue as it meant you could be fingerprinted easily and tracked across various apps1. Thankfully, this has now been fixed in iOS 102.
In this article, I’ll explain how to update your apps to support this new privacy requirement. Before I do that, I’m going to show you what happens if you run an app built against the iOS 9.3 SDK (or earlier) on iOS 10:
You’ll be prompted3 to allow permissions as soon as any media library code is encountered be that on app startup or in a background process such as that used by Music Tracker. If you decline to give permission then the app will quit to the home screen and you will not be able to use it. This is a big change from previous permission switches whereby apps built against the old SDK would be exempt from new permissions (i.e. if your iOS 7 SDK compiled app ran on iOS 8, it wouldn’t crash because it wasn’t using the new location privacy options). Personally I like this change as it allows you to see clearly which apps were abusing these APIs such as Canary and Google Calendar.
Bottom line: If you are using
MPMediaQuery or similar in your app, you’d better update it with the iOS 10 SDK as soon as possible as otherwise you are going to get a lot of crashes if your users don’t allow the permission (or a lot of awkward questions if you shouldn’t be using this API).
How do you update your app to request permission for these APIs? First of all, lets whip up a basic example with Swift 3 that will pull the title of the first track in your music library:
In keeping with other permissions based APIs such as photos, contacts, and calendars, iOS 10 requires that you add a new key to your Info.plist file to explain why you want to use this permission; for music library access, this key is
NSAppleMusicUsageDescription. If you don’t add this key, your app will crash as soon as you try and access an
MPMediaQuery with the following message:
This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSAppleMusicUsageDescription key with a string value explaining to the user how the app uses this data.
NSAppleMusicUsageDescription key in place, you will now be given a standard permission dialogue when you first try and access the users media library. If the user chooses “Don’t Allow”, then the media query will fail and any subsequent calls will request in the
query.items property being nil. If they choose “OK”, then nothing happens (as execution of the code is not suspended and there is no callback). To fix this, we need to use the
requestAuthorization((MPMediaLibraryAuthorizationStatus) -> Void) APIs that were added in iOS 9.3 to do something like this:
You first need to request authorization and then run your code only if the status is
authorized. If not, then you should display an error specific to whether or not the request was
restricted (usually by corporate or parental controls).
I’ve put an example project on GitHub which uses the code above by way of demonstration.
I’m extremely grateful to everyone that has helped share my posts about this issue and to the engineers at Apple for fixing this privacy flaw. I’ll update this post should anything change between now and the expected public release of iOS 10 in September.
Whilst I had no concrete proof of this at the time of writing those articles, it looks like I was right that this was a widespread problem. ↩︎
I don’t want to take all the credit for this but I honestly don’t think this would have been fixed if I hadn’t raised the issue repeatedly over the last 7 months. ↩︎
In earlier builds of iOS 10 you’d be asked “[App Name] Would Like to Access Apple Music” (as shown in screenshots above) but as of iOS 10 beta 4 this has been changed to the more appropriate “[App Name] Would Like to Access Apple Music and Your Media Library”. ↩︎