Not authorized, skipping filter predicate application - ios

Upon launch on an iOS10 device, I get the following output:
[MC] Reading from public effective user settings.
[SDKPlayback] MPMusicPlayerController] MPMusicPlayerController: Server is not running, deferring check-in
[SDKLibrary] Not authorized, skipping filter predicate application
The app plays music from the user's library and therefore must ask permission, so I have updated info.plist with the required key strings for NSAppleMusicUsageDescription but the app crashes as soon as the predicate is called. When the app is stopped and the launch screen disappears, the permission window is finally displayed. If I tap allow, subsequent launches will work just fine.
My question is: Does the "server not running" error have anything to do with the permissions window not being shown? If so, how do I start it?

So, the way an MPMusicPlayerController works is:
You have to have the key in the Info.plist, as you already know.
In your code, check authorization with MPMediaLibrary.authorizationStatus.
If you don't have authorization, you request authorization using MPMediaLibrary.requestAuthorization. You cannot proceed until you have authorization. Be careful because the call is asynchronous and the completion is called on a background thread.
Now you make an MPMediaItemCollection and call setQueue(with:) and then play.

Related

iOS // CLLocationManager // didFailWithError is triggered with kCLErrorDenied while there are permissions

I have a navigation app that supports CarPlay connection.
When running with CarPlay, some users report that they appear to not have GPS connection.
Looking at the logs I noticed that on app launch we're getting didFailWithError with error code kCLErrorDenied, so according to Apple's recommendation we stop updating location.
This comes immediately after receiving locationManagerDidChangeAuthorization with kCLAuthorizationStatusAuthorizedWhenInUse with accuracy=0.
In this flow we also check CLLocationManager.locationServicesEnabled which returns true, CLLocationManager.authorizationStatus which returns kCLAuthorizationStatusAuthorizedWhenInUse and CLLocationManager.accuracyAuthorization which returns CLAccuracyAuthorizationFullAccuracy.
Users also confirm that they did give location permissions to the app and had location services enabled, also this issue was resolved after a few restarts of the app.
All the cases I encountered were on CarPlay using iOS 16.
Any idea why kCLErrorDenied could be triggered when there are location permissions?
Just in case someone else encounters this issue - this happens when we start location updates while the app is still in the background and we only have permissions for "While Using".
This is more prominent on CarPlay since it's possible to go to the home screen and disconnect. When reconnecting the app would wake up while in the background and try to start updating location.
The solution was to only start updating location when the app is in active state.

App Tracking Transparency reset after user choice

I've just implemented the ATT request in my applications. It appears at the app first opening but I would like to show it again if the user wants to change his preferences from the app settings (internal).
I tried to call the requestTrackingAuthorization method again but it enters immediately to the completion handler. Is there a way to reset the status?

iOS 13 check for provisional authorization status of CLLocationManager

As per the WWDC video, https://developer.apple.com/videos/play/wwdc2019/705/, when you ask for "AlwaysAuthorization" permission you will see only "When In Use, Once and Don't allow". Even if you tap on "When In Use", the delegate call back will come back as kCLAuthorizationStatusAuthorizedAlways. This is working as expected. But is there a way to find out that the request is still provisional or actually-always-allow?
There is no enum associated to this permission. The only allowed enums are:
kCLAuthorizationStatusNotDetermined, kCLAuthorizationStatusDenied, kCLAuthorizationStatusAuthorizedAlways, kCLAuthorizationStatusAuthorizedWhenInUse
Because I want to show an alert as soon as user grants the "While In Use" permission, to tell them that the app will only work if you provide "Always Allow" via system preferences and I can navigate them to the system settings page of my app via a tap, just like how Zenly is doing it: https://www.macrumors.com/2019/08/16/app-developers-tracking-restrictions-ios-13/
You can check if you're getting location updates in the background for more than 10 seconds after the application gets in the background. If yes, then you have the permanent Allow Always. If not, then you have the provisional Allow Always (or any other authorization that you can check explicitly).

How to check application state under swift UI Test

Some background
I am currently writing a UI Test for a settings pane, and click on buttons to enable certain permissions such as push notifications and location services.
However, if the alert for the permission has been displayed before (regardless of the user allowing or denying access to the permission), the alert will not display again, and will just take the user to the settings app. Unfortunately, these settings do not reset, meaning the first time I run the UI tests, alerts will show; and on all subsequent UI test runs, the buttons will take me to the settings app unless I reset the device before the tests begin.
My issue
Thus, my test needs to know if the app went into the background, and attempt to foreground it to continue the testing:
if app.state == background {
foregroundApp()
}
// continue with other tests
Is there any way to determine if the app is in the background?
What I tried
I researched methods to determine the state of the application (running/background/etc) from a UI test, and was not able to find much. I tried to check whether certain elements exist:
if (app.navigationBars.element.exists) ...
but this gives me runtime errors[1] if the user is taken to the settings page because the app under test is in the background, and the test cannot lookup the navigationBars (or other elements).
I tried using some of the methods from Facebook's private headers for XCUIApplication() and XCUIElement().
XCUIApplication().state always returns 3 no matter what state the app is currently in, and any attempts to call XCUIApplication().resolve() to foreground the app give me the same errors as before[1]
I tried to rewrite the logic to foreground the app before resuming the tests, but methods such as XCUIApplication().launch() kill the app before restarting, which I cannot do. Only siri service seems to work for me, but I cannot access the siri service through the corporate proxy, and modifying proxy permissions is not possible.
Is there any other way to check the app state?
Errors
[1] This error is printed every time I try to do something involving state. I do not call snapshotView anywhere, and thus the suggestion to use afterScreenUpdates is useless.
Failure to get snapshot within 15.0s
Cannot snapshot view (<UIKeyboardImpl: 0x7febcc75d000; frame = (0 0;
414 226); layer = <CALayer: 0x608000625720>>) with
afterScreenUpdates:NO, because the view is not in a window. Use
afterScreenUpdates:YES.`
tl;dr
I need to check whether the app I am UI testing has entered the background (i.e. user pressed the home button). Checking for existence of particular elements such as navigation bars doesn't work, neither do most methods from Facebook's private headers for XCUIApplication/XCUIElement. Foregrounding the app also causes issues, and relaunching the app is not an option; neither is siri service.
You can do this in Swift 4, using XCUIApplication.state, which will give you information about the state of the app - whether it's in the foreground or background etc. however, it's not possible to find this information in Swift 3 and below. Essentially, UI testing in Swift 3 doesn't support leaving the app.

Is there a method to simulate (.NotDetermined) status from ABAddressBookGetAuthorizationStatus?

I am developing an App and testing on my physical iPhone.
At some point, the app checks if it is authorized to view the contacts (address book) of the phone using ABAddressBookGetAuthorizationStatus().
That call returns a status which can either be .Denied,.Authorized,.Restricted, .NotDetermined.
The last one is returned if you run the app for the first time, and have never approved or denied the app from accessing the device's address book.
Once you answer that authorization question, that answer is stored somewhere, and in the future, you will either get a .Authorized or .Denied status. Never again a .NotDetermined.
I tried deleting the app, and installing again. I tried changing the compile settings and changed the target build iOS. I did a Clean build, but I failed to get that status again.
I know I can copy the Xcode project and name the app something different to trick the iPhone into thinking this is a new app. But what is a straight forward way to let the app receive a .NotDetermined status again?
Go into the General settings and Reset Location and Privacy. (This will have other side effects, but there's nothing you can do about that.)

Resources