ios7: how to track system internals like notifications - ios

We are developing application which rely on new IOS7 functionality - remote-notification background updates.
According to docs system can "skip" calls to didReceiveRemoteNotification:fetchCompletionHandler: if it finds that background processing power-consuming and lengthy, etc and we see this in practice - user can get push notification on the screen, but calls to didReceiveRemoteNotification:fetchCompletionHandler: are simply not happening at all
The question is - how we can check what happeping in ios with push? is there some ways to see internal system logs with real information from ios services? We need this for debug purposes of course, not in released application. just to double-check and fine tune our background processing. There is should be the way for developer to see what is really happening on device.
I found application "appswitcher" that shows similar stuff, but on ios7 it shows only active application logs (appswitcher itself), not system-wide. so it is useless for us...
To be clear: push notifications are working correctly, they are always received by the program in Debug mode for example. But in release/adhoc build we see that some notifications are sent to applications (waking it from background) and some are not. Documentation stating that fetch callback is used to calculate cpu/data usage and ios reserve right to "skip" notifications when it feels to do so, we just want to find the way to see is this is the case
Any help is welcome

I've never tried it but I saw this a while back. By looking at it, it seems like it will help your case but unfortunately, you gotta give it a try to find out if its worth it or not.
https://developer.apple.com/downloads/index.action
Go to that website, and login using your developer account.
Go to page 2 (or find Oct 4, 2013 post Bug Reporter Logging Profiles (iOS)).
In the description, Apple has a link that tells you how to use these profiles. As the title of that post suggest that it is used for bug reporting, hopefully it gives you some details so you could fix your bugs.
Try it and see if it works and let other people know if it's useful or not. Since it says 'Logging', my guess is that it will output detail info on the console about push messages and not secretly log and sends the log to apple.

Firstable you need to check if your push notification working correctly. What i would do is temporary disable background fetching, and simply check if i get push.
If everything is ok i will turn background fetch back in Capabilities and try to send one in Debug. Even app is in background you can still have a breakpoints. If method is not called try look at the console.
I think you have a problem with push notification other than backgroundFetching.
If you are willing to try what happen when application is not in background mode but wass 9-killed you should put NSLogs in method. If you see NSLog in console then (Xcode -> ⌘⇧2 -> your device (connected) -> Console) you're good to go.
The production console is in background fetching useless to you unless you put NSLogs in your methods. But then you can only check if you successfully enter method and log a parameters.

Related

Intermittent & Temporary iOS Keychain Failure

We have an app that heavily relies on being able to access a user's session token using iOS's Keychain. When our app opens, the first thing that's checked is whether the token is available - and if not, we show the user a login screen. We do not use any 3rd party library for this, and use Keychain's SecItemAdd() / SecItemCopyMatching() directly with the following options:
kSecClassGenericPassword
kSecAttrAccessibleAlwaysThisDeviceOnly
We see little to no issues with this during normal usage.
The Problem
We've had users reporting that upon opening their app, they're shown the login screen (suggesting Keychain could not find a value), when they were in fact logged in. We found that in this instance, we found that upon killing and relaunching the app, users were back to normal (session was found in Keychain). Once we found this, we tried added an exponential backoff to keep querying Keychain, thinking that it may had only been unavailable for the first few seconds. This did not work, and proved to us that Keychain seems to be unavailable for the entire app launch session. We are not able to reproduce this issue. It seems to happen very intermittently.
Upon further investigation, we found that commonly, users had received VoIP Pushes prior to having this issue. We're still not able to reproduce this issue reliably, but upon debugging, found that our Keychain.session was found to be nil when receiving these pushes (we rely on it there as well), which is before the user would open their app to see that they are pseudo- "logged out."
We use PushKit and PKPushRegistry in order to do VoIP Push. This requires our app to have "Background Modes: Voice over IP" enabled. We use all of this as suggested by Apple's documentation. Here's a sample:
func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, for type: PKPushType) {
guard let _ = Keychain.session else {
print("Session token not available")
return
}
handle(notification: payload.dictionaryPayload)
}
This code relies on Keychain.session being immediately available upon receiving a VoIP Push. As mentioned before, we've seen instances where it is not available, and so this function logs out and simply returns.
I've also found this relevant Apple forum post, suggesting that this could be an iOS bug.
Can anyone help us with this issue? Any help would be greatly appreciated. Even if this is in fact an iOS bug, we're open to workarounds.
I think this topic is driving the iOS dev community literally crazy since long time. I've read so many articles and thread about this that I lost the count.
So, I'm dealing with this issue too, and based on the #naqi answer, I started moving in that direction and I might have found a working solution.
Assumptions:
The issue seems to happen when the app is getting suspended, due any sort of reason (eg. the app in background from long time and due memory pressure the OS send it in suspended state, or the app is in bg and user upgrades to a new version from the store or automatic app update does it). I'm no longer fully sure what suspended means, but I strongly suspect that the app may get resumed/awaken without actually getting presented on the screen (due bg task, but not necessarily).
One Apple stuff member on the Apple developer forum, had the brave to reply saying something like "try to put a delay between addDidFinishLaunchingWithOptions and appDidBecomeActive". Apart from the madness here, reading that comment made me consider that maybe when the app gets resumed it triggers the addDidFinishLaunchingWithOptions but of course not the appDidBecomeActive (as it may not be resumed by the user but from any sort of event handled by the OS in background, for which we may not have the control seems, or any other feature like bg task or silent push notifications etc).
Extra info:
According with a quite old penetration test article I've found on the web (https://resources.infosecinstitute.com/iphone-penetration-testing-3/) querying the keychain actually would address the query to another process called securityd running on the device, which magically schedule the queries and performs them to the keychain db and, finally returns back the content to the requesting app, assuming that the app is still alive when the query gets completed on the keychain db. This made me think that, if that is still true, such process may fall in sort of "DDoS" attack where your app (or maybe all the apps in execution? Not clear how it actually works) performs too many queries. This may lead to false positive errors like secItemNotFound or similar. Again, as nobody confirmed this, keep it as my personal consideration.
Approach:
From the #Naqi answer, I could exclude the points 2,3 and 4, keeping the point 1 as only still valid reason. Said that, I decided to move any CRUD operation dealing with the keychain, from the addDidFinishLaunchingWithOptions to appDidBecomeActive, by handling the app setup instructions (whatever needed by your app) in there, in order to make sure that eventual background events of suspending/resuming actions won't affect the keychain at all as the appDidBecomeActive would not get called unless user actually makes the app to get opened and shown on the screen. Of course this should happen only on app launch, so you can use a bool flag or similar semaphore approach in appDidBecomeActive to make sure your setup logic is executed only once.
Combined with the above approach, In the App Delegate I also explicitly implemented application(shouldSaveApplicationState:) by returning false and application(shouldRestoreApplicationState: still returning false (Even though I assume by default should be already like this). This may not necessarily be useful but it was worth it to try too.
Summarising, on some affected devices which were randomly failing the keychain access, seems now not to happen anymore since weeks and, consider this was happening for some, almost every 2/3 days let's say, I assume it might have attenuated the issue at least.
I can say that the monitored devices were all in different configurations, with a lot of apps installed or not, with storage memory almost full or not, with a lot of apps in bg or none at all, any form factor and different iOS versions. Keychain backup to cloud not enabled, and items attribute on the keychain at least as kSecAttrAccessibleWhenUnlockedThisDeviceOnly
Open point not fully verified: Supposedly the access to keychain should be thread safe, but I found different thread on the web contradicting each other. Maybe that could somehow impact your logic and cause unexpected state
(Congrats if you managed to read up to here :) )
Hope this helps to further understand what's going on with this keychain tragedy in iOS
I was having similar issues and after talking to engineers at WWDC we identified few issues that is leading to this behavior.
We were calling Keychain too often and this can lead to a situation where it gets expensive and some calls would not finish or timeout
If an app does not provide Access Group for keychain or does not add it in save transaction with keychain then Xcode generates one but this is dynamic and can change between dev environments
If you provided an access group later in the life of your app, then your old keychain value will remain associated with the app and a new value will be created with the access group you will now provided
This also means that when you query keychain you have to provide an access group otherwise you will get a reference to what ever was found first.
Edit: formatting

Apple push notifications are no longer received

We released our phonegap application about a week back and everything was tested and working fine. Fast forward a few days and suddenly people start to report that they aren't receiving any push notifications. I go back to my test devices and fail to reproduce the error for a time but all of a sudden my device just stops receiving them.
I've gone on a debugging spree to try and identify the issue. I stepped through the server side code to ensure that the PushSharp code is being used correctly. I've checked the database to ensure that the user has an up-to-date device token and now I'm going though the steps listed here:
https://developer.apple.com/library/ios/technotes/tn2265/_index.html
When I enabled logging and sent a push notification a log was created with the appropriate timestamp so I know that SOMETHING happened. However, I'm still not receiving a pop-up on the interface and I can't see anything in the log that suggests it's gone awry.
Here is a pastebin of the log I extracted.
http://pastebin.com/KiCJEsDs
If this doesn't help is there anything else I can do to help identify the issue?

Update ios app every time more data is available on server

I have an app that needs to update every time a java web application creates more data. Simple enough, right?
But I found out that my app can`t run in background to ask for more data periodically, and I think I need to use the push notification system. That seems to be overly complicated for a really small thing.
And then, reading about it, I found out that the push notification can never arrive! For example, if the app is offline when the push notification is sent but is online a few moments later.
So, in that case, how can I update the data? I only bring data from the server when the user logs in. I didn't want to do that every time the application became active...
I guess there is a simple solution but this is my first app, any help would be appreciated.
You see why you should read your question before posting it?
And then, reading about it, I found out that the push notification can
never arrive! For example, if the app is offline.
So, in that case, how can I update the data?
Guess what, if you are offline, there is not much you can do... Moving on to serious things:
iOS7 allows you to do periodic background fetchs (check the Multitasking Enhancements). Have this tutorial.

Is there any way to programmatically send my iPhone app to the background

I have an iPhone app that I need to send to the background automatically. The app is defined with the VOIP key in its background modes so it should continue running when in background. I specifically need the app to keep running so calling exit(0) is no good.
The app will not be distributed via app store so using a private API is ok.
I have read about UIApplication terminate and UIApplication terminateWithSuccess but they don't seem to be available anymore
Already answered quite well here:
Suspend the application
As that poster wrote:
Quitting your application or sending it to the background programmatically is a violation of the [iOS Human Interface Guidelines][1], which usually doesn't bode well for getting through the review process:
Don’t Quit Programmatically
Never quit an iOS application
programmatically because people tend
to interpret this as a crash. However,
if external circumstances prevent your
application from functioning as
intended, you need to tell your users
about the situation and explain what
they can do about it. Depending on how
severe the application malfunction is,
you have two choices.
Display an attractive screen that describes the problem and suggests a
correction. A screen provides
feedback that reassures users that
there’s nothing wrong with your
application. It puts users in control,
letting them decide whether they want
to take corrective action and continue
using your application or press the
Home button and open a different
application
If only some of your application's features are not working, display
either a screen or an alert when
people activate the feature. Display
the alert only when people try to
access the feature that isn’t
functioning.
In Swift 3 Use below code, working charm
DispatchQueue.main.asyncAfter(deadline: .now()) {
UIApplication.shared.perform(#selector(NSXPCConnection.suspend))
}
While I agree with the other answer that you "shouldn't" exit programatically. There is a way to exit programatically.
*disclaimer - You shouldn't do this.
exit(0);
There is no way to put the application into the background without pressing the home button. If there is, you might want to add the jailbreak flag to your question and ask them.
For more, check this duplicate question, Proper way to exit application.

How to show "Would like to send you Push Notifications" Alert View again?

I was able to show an Alert View like the image above after registering for Remote Notifications.
But when i delete my Project App and build it again, it will not show anymore.
Will there be any chances to show the alert view again to the same device?
What i like is to get my device token again because I failed to store the device token temporarily in the NSUserDefaults.
Delete your app from the device.
Turn the device off completely and turn it back on.
Go to Settings > General > Date & Time and set the date ahead a day
or more.
Turn the device off completely again and turn it back on.
reference: https://developer.apple.com/library/ios/technotes/tn2265/_index.html
Addressing the question of presenting the push notifications permissions dialog again as needed for testing -- this is certainly a workaround, but here goes:
Having just finished work on an app that uses Push Notifications extensively, and having tried all the usual permutations, without success ... I ultimately realized that the most streamlined way to work around that issue was to get a device to use only for testing (i.e., a low-end iPod Touch).
To reset the dialog, do a Settings > General > Reset > Erase All Content and Settings. Go thru the device's setup process, reinstall the app and Go.
This was the only way I found to test the 'first launch' experience on demand, as needed during the course of development/testing. It also added a lot of additional versatility to the process.
Shouldn't have needed to resort to all this, but I'm very glad I did, as it turned out to be a real godsend. FWIW.
[P.S. It will probably also prove handy in the future for testing beta versions of the OS, etc.]
At launch, your app should be requesting a token via:
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types
and will get a token from iOS in the delegate message:
– application:didRegisterForRemoteNotificationsWithDeviceToken:
iOS will prompt the user to allow notifications only when necessary. If remote notifications are already authorized for your app the alert will not appear and your app will get a valid token.
Net is you can't force the alert but you don't need to.
Yes.
http://developer.apple.com/library/ios/#technotes/tn2265/_index.html
If you want to simulate a first-time run of your app, you can leave the app uninstalled for a day. You can achieve the latter without actually waiting a day by setting the system clock forward a day or more, turning the device off completely, then turning the device back on.
Temporarily change your package id.
com.mycompany.app - > com.mycompany.app1

Resources