ios/xcode: Possible to send notification when app is in foreground (as alternative to alert) - ios

This may be contrary to HIG...it is not standard..but it occurred to me that after a user sends feedback from withinmy app, it might be nice to flash a quick unobtrusive message "Thank you for your feedback" or something. I don't want to hit the user with a full blown alert. But a discreet notification banner along the top might be nice.
Is it possible to do this or is it disallowed?
Thanks for any suggestions.

If this notification is initiated from an action from within your app, an Apple notification may not be necessary. You want to simply show a thank you message, so it doesn't even have to wait for a response from a server, but you may want to check if you have Internet connectivity, just to be able to say that the message couldn't be sent, and offer the option to retry.
These are good options for a Toast-style alert that Android uses and is unobtrusive:
https://www.cocoacontrols.com/controls/toast
https://github.com/scalessec/Toast
You can configure it to slide in from the top or bottom. And, it slides away without user interaction.

Local notification will be received in this case but will not be displayed as you want it. However you can make a custom view similar to iOS view. Also please check https://github.com/OpenFibers/OTNotification

Unless the notification is from other application in background,
your currently active app has every right and responsibility in interacting with user with any types of visuals.
There are no class from iOS SDK to allow you to use the same notification banner used for Push Notification. To achieve the same result while your app is active, you may need to adopt your own solution or a module.

Related

Is anybody else seeing duplicate calls to handleActionWithIdentifier:forLocalNotification: in WatchKit?

I am getting some very strange behavior with my WatchKit handling of local notification actions that I'm pretty sure is a system bug. I'm wondering if anybody else is seeing the same thing.
(This is using iOS 8.4 and WatchKit 1.0, with an Objective-C app build with Xcode 6.4)
It's too much code to post, and the code is property of the client, so I'll have to describe it.
The background:
I am adding custom "long look" notification support to a client's app.
The app creates geofences around vendor locations. When the user enters one of the geofences, the location manager send a didEnterRegion message to my class that handles geofences.
I turn around and generate a local notification of a defined category. That category is defined as having 2 different UIMutableUserNotificationActions attached to it, one for showing more info about the vendor, and one for displaying driving directions to that vendor's location. (We won't talk about the fact that the user is in shouting distance of the vendor when the geofence fires, so they can SEE the vendor's shop. This is what the client wants, and he's paying me to do it this way.)
The local notification is set to fire immediately (or for testing, I create notifications set to fire in a few seconds.)
The system can do one of 3 things when the notification fires.
1. If the app is running in the foreground, it will send the app delegate a `application:didReceiveLocalNotification:` message.
2. If phone is awake but the app is in the background, it displays the local notification with a system banner/alert (depending on the user's settings.) That banner/alert has buttons for my 2 actions.
3. If the phone is locked and the user has a paired Apple Watch that is allowed to receive notifications, the local notification is sent to the watch.
The Apple Watch app has a custom subclass of WKUserNotificationInterfaceController that is set up to handle this category of user notifications. It adds an image, a title, and a message body to a custom interface controller, with data it gets from the the userInfo dictionary attached to the local notification.
If the user taps one of the action buttons on the WKUserNotificationInterfaceController ("more info" or "directions"), the watch's main interface controller gets a handleActionWithIdentifier:forLocalNotification: message. The code is set up to then send an `openParentApplication:reply:error:' message to the iPhone app. It passes along the user info dictionary it received in the local notification.
The iPhone app responds to the openParentApplication:reply:error message by either requesting driving directions from the location manager (which launches the maps app) or displaying the appropriate info page from the app for the specified vendor.
If the phone is locked when the watch sends the `openParentApplication:reply:error: message to the iPhone, the user doesn't get any feedback, since the phone is locked and Apple doesn't allow a phone to wake itself up.
In that case I therefore invoke the reply block with a dictionary entry of #{#inBackGround: #(YES)}. The watch's reply block checks for inBackground==YES, and if it is, it displays a message to the user that they nee to open the iPhone app in order to see the info/directions.
The problem:
If I launch the iPhone app and trigger a local notification when the phone is locked the first time, the message goes to the watch, the watch displays my custom long look with "more info" and "directions" buttons, and tapping one of the action buttons invokes the watch's handleActionWithIdentifier:forLocalNotification: method, as expected. The watch's handleActionWithIdentifier:forLocalNotification: method sends an openParentApplication:reply:error message to the phone, and the phone displays the appropriate response to the user when the user goes back to the app.
However, the problem comes in if I then trigger a new local notification (also with the phone locked) for a different vendor, with different GPS coordinates and userInfo that points to a different screen of information to display on the phone. When my watch buzzes and I raise it to my wrist, as the "long look" notification for the new local notification is displayed, the watch's handleActionWithIdentifier:forLocalNotification: method fires again, with the identifier and userInfo dictionary from the previous local notification. (I haven't tapped any action buttons on this new notification, or responded to a local notification message on the phone.)
Then, if the user clicks the "more info" action button on the watch's new long look notification controller, that action fires.
The result of this is that when the user goes to his phone, he sees the information for the new vendor he asked about, but when he clicks that away, there is a duplicate copy of the info for the first vendor on his screen.
I've debugged this very carefully, and confirmed that the watch app's interface controller's handleActionWithIdentifier:forLocalNotification: method is being called spuriously. I added a unique NSDate timestamp to the userInfo in the local notification that the iPhone posts, and I see that exact same timestamp repeated in the second (spurious) invocation of the first handleActionWithIdentifier:forLocalNotification: when the second long look notification is displayed.
Has anybody else run across this problem? I guess it's time to file a Radar bug, but I'm not sure what set of steps from my client's app triggers the problem, and it might take me a full day or more to work out a minimum demo app to demonstrate the problem. I know from experience that Apple won't pay any attention to my bug report unless I give them an app that lets them create a repeatable fail-case, along with painfully detailed instructions on how to use it.
The fix:
The fix I have come up with is a dreadful hack. On the phone, I embed a unique "actionFireDate" NSDate into the userInfo dictionary for the local notification. On the watch, I create an empty NSMutableSet "actionFireDates" at startup. When I get a handleActionWithIdentifier:forLocalNotification: call, I get the userInfo for the local notification, get the timestamp NSDate I put in the userInfo dictionary, and check to see if that unique NSDate is in my "actionFireDates" set. If it is, I simply ignore the action. If it's not, I add the new NSDate from the userInfo dictionary in to my set of action fire dates.
I'm pretty sure this is a system bug, and have opened a bug at Apple's bug reporter website (A.K.A. Filed a "radar bug".)
The fix I came up with for this was to add code to my custom WKInterfaceController class's awakeWithContext method that calls dispatch_after to call dismissController 10 seconds after the alert is displayed. If the user does nothing, the alert goes away on it's own.
I'm not going to accept my answer for another couple of days in case somebody else has insights to share on the subject.
EDIT:
Apple closed my Radar bug as a duplicate. I take that to mean that this really is a system bug.

iOS - Play ringing sound when "called" in background

I was wondering if it was possible to play a continues sound in my Skype like application when a user is called an the other user has the app installed but the app is in the background in the moment.
It would be really awesome if it could could show an "accept / decline" on the lock screen. But that might not be possible is it?
I have looked around on the internet, but I could not find it. (I think I saw something related to this on a keynote once, but that might just be my memory hoping it exists.)
That is possible to show an "accept / decline" on lock screen or notification itself. The only thing that is not possible to do is to make input field for quick response (as it's done in Messages app)
There is nice guide to interactive notifications for iOS8.
To play sound i suggest you to use possibilities provided by UILocalNotification instead of implementing custom sound/vibration.
Also, if your app is in background, it must use push notifications, so for VoIP apps i suggest you to take a look into PuskKit framework and special type of pushes - VoIP pushes

ios, Is there a change in push notification authorization callback

In ios, if I authorize or reject Location Services when prompted, there is a delegate method that gets called immediately:
- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status;
I'm wondering if a similar method exists for accepting or rejecting Push Notifications. I'm aware of how to prompt, as well as how to test for status, but not how to do something immediately after a user accepts or rejects the notification.
I would like to prompt the user for Push Notification, and based on their response do a certain action, such as redirect the ViewController one way or another.
I've done a great deal of research on this and - unfortunately - the status of that accept/decline option appears to be entirely opaque.
You can determine that the user doesn't have push notifications enabled (using UIApplication's isRegisteredForRemoteNotifications), but not why it isn't enabled (ie. determine whether it's a "never prompted" or "prompted and then declined or later disabled" state).
I strongly suspect that this was a conscious design decision by Apple to make it more difficult for developers to hound users who've opted out. There are legitimate reasons to have this information, though, so I hope in the future they reconsider.
I hope this helps.
You can not do that but you can check that every time the app gets into foreground. This would solve your case when you can take action at the moment the user opens the app.
If you want to do that on background (in case you want to report your server that user has been disabled notification for example) you can always run some background task (like "Background fetch") to check the status.

ios xcode : checking live updates using a .net API

I'm trying to look for a way as to how I can notify a user of new updates based off of a .Net API that I created. Much like that notification you get on facebook, I just need to alert the user that something has been updated. So I'm thinking I need a function that runs in the background while my user uses the app combined with a NSTimer.
Based on my research (and on this question https://stackoverflow.com/a/14835300/639713) apparently you can only achieve such a thing for VOIP and location services. And that using push notification is the only way. Is it really the only option that I can use for such a need? Or are there any other ways?
Thank you for your time.
You have two options:
While your app is open, poll the server every so often to see if there are any updates to report.
This will work only as long as the user has your app open, and as you note, your app will only be allowed to stay open for a long time if it happens to be a VOIP or navigation app.
Use push notifications to push updates to the user’s device.
The disadvantage here is that you will need to write some server-side code to talk to Apple’s push notification servers (as described in this tutorial). This may or may not be a big deal in your particular situation, but it’s the only way to get data to the user when your app isn’t open.

Programmatically sending an iOS app to background [duplicate]

How can I suspend my application or send a suspend message to my application?
I want to simulate pressing the home button.
There is a private instance method for UIApplication:
The following code would work, (tested in an iPhone 3GS):
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:#selector(suspend)];
In swift:
UIControl().sendAction(#selector(NSURLSessionTask.suspend), to: UIApplication.sharedApplication(), forEvent: nil)
Edit Swift3:
UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
Quitting your application or sending it to the background programmatically is a violation of the iOS Human Interface Guidelines, 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.
The philosophical reason for this is explained earlier in that document:
People, not applications, should
initiate and control actions. Although
an application can suggest a course of
action or warn about dangerous
consequences, it’s usually a mistake
for the app to take decision-making
away from the user. The best apps find
the correct balance between giving
people the capabilities they need
while helping them avoid dangerous
outcomes.
Users feel more in control of an app
when behaviors and controls are
familiar and predictable. And, when
actions are simple and
straightforward, users can easily
understand and remember them.
People expect to have ample
opportunity to cancel an operation
before it begins, and they expect to
get a chance to confirm their
intention to perform a potentially
destructive action. Finally, people
expect to be able to gracefully stop
an operation that’s underway.
There should be no reason that you need to force your application into the background during its operation. It should remain fully functional when displayed onscreen and it should be up to the user when they want to switch away from your application.
You can't do this.
If you want to exit your app, don't fear rejection and love false positive crash report emails from users you could call exit(0);
Use :
sleep(15)
it will suspend your app for specific time
When the application is suspended, a UIApplicationWillResignActiveNotification notification is posted.
I would guess you could try to post this notification manually. Didn't try this myself though.

Resources