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

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.)

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.

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.

Not authorized, skipping filter predicate application

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.

Ios Location Permission is displayed even before App is launched and disappears Also didFinishLaunchingWithOptions is not called in this Scenario

When i delete the app from Iphone and Run my project again The app is installed and Location Permission is asked even before the app is launched after that it disappears too quickly before user can interact with it. In this scenario the breakpoints in didFinishLaunchingWithOptions and main.m is not working at all but the app is Loading the first screen And Notification permission is Loading .I cannot forward the app to signup screen since the app requires Location for finding the nearest counties users can register But when I stop the project and run again everything is working as it should be I cannot find the reason for this problem How is the app asking for permission without even entering didFinishLaunchingWithOptions? And proceeding to first page in storyboard without even entering viewdidLoad of that particular class
If you once allow or granted the permission then it will not ask second time. So your flow is normal. Location service asks for permission with high priority so it will shown little bit earlier. If you want this on sign up screen then you should implement that code in your viewDidload of signup screen.
Update : (In response to comment)
If you uninstall or delete app from device or simulator that means you are deleting it's all data and configuration or settings(include your location permission). So, if you install it again then there is no permissions set in your device's setting app for your app. So, you got asked again for permission. that's it.

isRegisteredForRemoteNotifications returning NO even after turning on Notifications

So we have a notification screen where users can customize the push notifications they want to receive. In this view controller, we check if [application isRegisteredForRemoteNotifications], we allow users to use the screen, else we show them the prompt that deep links to settings for the app. Now, what's happing is that certain users are complaining that this prompt never disappears even when they turn on in settings. They have sent us the screenshot of the screen, as well as device settings for the app. We have not been able to reproduce this issue. The view controller is directly checking against the OS flag, so there is not much scope of error there. Also we have gone through the code and haven't found anything. I am assuming that because of network issues, deviceToken is not getting delivered to the app. Not really sure what else might be going here. Appreciate any help or suggestions on this matter.

Resources