iOS Backgrounding Not Working - ios

I am in the process of writing a VoIP application for iOS but when App is in background it stops accepting calls. When the app is active again all the queued up messages start getting processed.
The following is what I have done.
When building the app I add Voice over IP as well as Audio and AirPlay to the plist file. Then I mark the websocket connection with NetworkServiceTypeVoIP as you can see here.
I have not set the keep alive timeout handler because registration doesn't matter if the app won't wake up to answer the call. Any help would be greatly appreciated.
It should be noted that this is my first Swift project and I'm not very familiar with the iOS platform.

To allow to work your app in background mode, you need to enable Voice over IP flag ON(Path : Go to target --> capabilities --> Background Modes). like as below.
And add following code in your project to support in background:
Step 1: Declare __block UIBackgroundTaskIdentifier bgTask as global variable.
Step 2: To add following code in applicationDidEnterBackground.
- (void)applicationDidEnterBackground:(UIApplication *)application {
bgTask = [application beginBackgroundTaskWithExpirationHandler:^{
bgTask = UIBackgroundTaskInvalid;
}];
}
Step 3: Stop background task handler once apps come in foreground mode.
- (void)applicationWillEnterForeground:(UIApplication *)application {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
}

Take a look at Apple documentation, you're probably interested in UIBackgroundModes=voip.
UPD:
From documentation:
To configure a VoIP app, you must do the following:
Enable support for Voice over IP from the Background modes section of
the Capabilities tab in your Xcode project. (You can also enable this
support by including the UIBackgroundModes key with the voip value in
your app’s Info.plist file.)
Configure one of the app’s sockets for
VoIP usage.
Before moving to the background, call the
setKeepAliveTimeout:handler: method to install a handler to be
executed periodically. Your app can use this handler to maintain its
service connection.
Configure your audio session to handle transitions
to and from active use.

You may find your answer or some clue --> here <--
Properly have to research the following:
applicationDidEnterBackground
beginBackgroundTaskWithExpirationHandler

Related

Performing Activity, When the App is Terminated

i am new in iOS Development so pardon me for asking this question in advance.
I am trying to post some data through API (after a specific time, lets say 30 minutes), I am able to achieve this when the app is in foreground or in background but is it possible to achieve even when the App is terminated ? I can perform this activity while the App is in background through this piece of code
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
But once the app gets terminated everything stops. I have found out that the thread of an iOS App gets killed after 3 minutes of its termination.
Presenting UIView after an interval
If the above is possible then is it possible to animate a particular UIView to appear on the screen after a specific time even if the app is terminated.
Thanks in advance.
When your app is terminated it can't execute any code; You can execute some code as the app terminates in applicationWillTerminate, if it is called. In many cases it won't be.
On iOS, you cannot execute code at a specific time or after a specific interval if your app is suspended.
You can schedule a local notification to prompt your user to return to your app, but if they don't tap the notification or launch your app from its icon in response then you cannot execute any code.
Have a look at the applicationWillTerminate: method of the UIApplicationDelegate protocol here. Once the system decides to shut down your application, this method is invoked giving you the possibility to do everything your app needs to do before it can be finished. This could be posting API data to your server as you desire.
Please note that according to the documentation this method is not guaranteed to be called when the user presses the home button but only when the system decides to kill the application:
For apps that support background execution, this method is generally not called when the user quits the app because the app simply moves to the background in that case.
If you don't know about the concept of Delegates in Cocoa Programming think of them as a special connection between one instance object (controller in the MVC design pattern) of your application (it has to be the app's delegate) and your app itself. The app will tell your controller if something interesting did/will happen like application startup or shutdown. Note: This is also available for macOS programming.

iOS task when application is closed

I am building an app which uploads files to the server via ajax.
The problem is that users most likely sometimes won't have the internet connection and client would like to have the ajax call scheduled to time when user have the connection back. This is possible that user will schedule the file upload when he's offline and close the app. Is it possible to do ajax call when the application is closed (not in background)?
When app is in the background, we can use background-fetch but I have never faced a problem to do something when app is closed.
The short answer is no, your app can't run code after being terminated.
You can run code in your AppDelegate's applicationWillTerminate, but that method is mainly intended for saving user data and other similar tasks.
See this answer also.
Yes you can do stuff in the background. You are limited to several different background modes of execution. Server communication is one of the modes that is allowed (background fetch). Make sure you set the properties correctly in Xcode per the guidelines (i.e. don't say you are a audio app when you are doing data transfer). See the details here:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
I found your question because it has the Cordova tag associated with it. If you are using Cordova you can use this plugin here to manage things in the background:
https://github.com/katzer/cordova-plugin-background-mode
Edit: If the user is FORCE closing / terminating the app then there is nothing you can do. If they are just exiting the app to the home screen and use other apps, then you can run in the background.
The other option you can do is schedule a local notification to upload the file. If you app successfully uploads the file because it is open / has a connection / did it in the background, then you cancel the local notification.
If the local notification isn't cancelled it will remind the user the file is not uploaded and when they open the notification your app will start back where it left off.
- (void)applicationWillTerminate:(UIApplication *)application {
if (application) {
__block UIBackgroundTaskIdentifier backgroundTask = UIBackgroundTaskInvalid;
backgroundTask = [application beginBackgroundTaskWithName:#"MyTask" expirationHandler:^{
backgroundTask = UIBackgroundTaskInvalid;
}];
[self doSomething];
[application endBackgroundTask:backgroundTask];
backgroundTask = UIBackgroundTaskInvalid;
}
}
I have already answered a similar question:
https://stackoverflow.com/a/57245917/6157415
You can implement notification, when user receive notification part of your code can be executed.
in particular there are Silent Push Notification to do this:
Sometimes, you may want to use a Silent Push Notification to update
content inside you app in the background. A silent push notification
is defined as a push that does not have an alert, badge or sound, and
just has Key-Value data.
From: https://docs.mobile.sailthru.com/docs/silent-push-notifications

Asynchronous code doesn't execute until app foregrounded in application:didReceiveRemoteNotification:fetchCompletionHandler:

In our app, we want to download a small amount of data in response to a push notification. So far, push notifications are working smoothly, launching the app in the background and causing didReceiveRemoteNotification to be called.
The problem is that, after this method returns, the app doesn't get any more CPU time until it's foregrounded again, so there's no opportunity to fetch that data asynchronously in the background.
Reducing this to the simplest case, I'm still unable to get asynchronous code running.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
[application setApplicationIconBadgeNumber:1];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[application setApplicationIconBadgeNumber:9];
completionHandler(UIBackgroundFetchResultNewData);
});
}
In response to a push, the app launches in the background and the badge count is set to 1, but the badge number is not set to 9 until the app is launched from the home screen.
Shouldn't iOS keep running the app until that completion handler is called, up to 30 seconds?
The Info.plist has the remote-notification background mode specified, the push payload contains 'content-available' : '1', and I'm not quitting the app by swiping up in the app switcher.
To add, we're using Parse to send this push notification using the following Javascript:
Parse.Push.send({
where: installationQuery,
data: {
"content-available": 1,
}
}, { success: function() {},
error: function(error) {}
});
First take a here and make sure you enabled push notification and added the content-available field:
Using Push Notifications to Initiate a Download
If your server sends push notifications to a user’s device when new content is available for your app, you can ask the system to run your app in the background so that it can begin downloading the new content right away. The intent of this background mode is to minimize the amount of time that elapses between when a user sees a push notification and when your app is able to able to display the associated content. Apps are typically woken up at roughly the same time that the user sees the notification but that still gives you more time than you might have otherwise.
To support this background mode, enable the Remote notifications option from the Background modes section of the Capabilities tab in your Xcode project. (You can also enable this support by including the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file.)
For a push notification to trigger a download operation, the notification’s payload must include the content-available key with its value set to 1. When that key is present, the system wakes the app in the background (or launches it into the background) and calls the app delegate’s application:didReceiveRemoteNotification:fetchCompletionHandler: method. Your implementation of that method should download the relevant content and integrate it into your app.
When downloading any content, it is recommended that you use the NSURLSession class to initiate and manage your downloads. For information about how to use this class to manage upload and download tasks, see URL Loading System Programming Guide.
Next, is there a reason your using "dispatch_after" with 2 seconds delay?
It is possible that since you call "dispacth_after" by the end of the run loop iOS "thinks" there's no pending work to do and puts the process to sleep so by the time the block is dispatched no one is listening to it.
Replacing it with "dispatch_async" might solve this.
Finally, if you do need to delay, you should tell iOS you need some time in the background, like this -
UIApplication *application = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier __block backgroundTaskId = [application beginBackgroundTaskWithExpirationHandler:^{
if (backgroundTaskId != UIBackgroundTaskInvalid) {
[application endBackgroundTask:backgroundTaskId];
backgroundTaskId = UIBackgroundTaskInvalid;
}
}];
Then do your background work.
Don't forget end the task when your work is done. call something like -
if (backgroundTaskId != UIBackgroundTaskInvalid) {
[application endBackgroundTask:backgroundTaskId];
backgroundTaskId = UIBackgroundTaskInvalid;
}

How to Execute a task continuously when application is in Background state in iOS 8

I Write the below code for executing a task when application is in background state it is working fine in iOS 7 but it is not working in iOS 8.
Can someone give me solution to execute a task continuously in iOS 8 when application is in background state.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}
There is no way to execute task continuously in background (except in few cases).
Most apps can move to the extended state easily enough but there are
also legitimate reasons for apps to continue running in the
background. The techniques offered by iOS fall into three
categories:
Apps that start a short task in the foreground can ask for time to
finish that task when the app moves to the background.
Apps that initiate downloads in the foreground can hand off management of those downloads to the system, thereby allowing the app to be suspended or
terminated while the download continues.
Apps that need to run in the background to support specific types of tasks can declare their support for one or more background execution modes.
For tasks that require more execution time to implement, you must
request specific permissions to run them in the background without
their being suspended. In iOS, only specific app types are allowed to
run in the background:
Apps that play audible content to the user while in the background,
such as a music player app
Apps that record audio content while in the
background
Apps that keep users informed of their location at all
times, such as a navigation app
Apps that support Voice over Internet
Protocol (VoIP)
Apps that need to download and process new content
regularly
Apps that receive regular updates from external accessories
Apps that implement these services must declare the services they
support and use system frameworks to implement the relevant aspects of
those services. Declaring the services lets the system know which
services you use, but in some cases it is the system frameworks that
actually prevent your application from being suspended.
yes i have implement the background condition while implementing ibeacon. delegate was set in interface
#interface HomeMainVC ()<ESTBeaconManagerDelegate>{
and i was able to send local notification if user enters or exist the beacon region throug following function. So there must be some way to send user location to.
//Beacon manager did enter region
- (void)beaconManager:(ESTBeaconManager *)manager didEnterRegion:(ESTBeaconRegion *)region
{}
//Beacon Manager did exit the region
- (void)beaconManager:(ESTBeaconManager *)manager didExitRegion:(ESTBeaconRegion *)region
{}
You have used following code but it is called only once when application is send to background mode so there is no use of it for you. If you want to do some things only once a time while going in background mode then it is useful for you.
- (void)applicationDidEnterBackground:(UIApplication *)application
{
UIApplication *app = [UIApplication sharedApplication];
UIBackgroundTaskIdentifier bgTask;
bgTask = [app beginBackgroundTaskWithExpirationHandler:^{
[app endBackgroundTask:bgTask];
}];
}

What is the best way to repeatedly call a method that fetches json from a remote server(iOS)

Im a newbie to iOS. I need some guidance on which is the best way to retrieve json every 5 sec from a remote server both, when in foreground or background, so that the UI gets updated properly regardless of the state. For example: Similar to a live cricket score app for iOS.
Any leads will help me. Thanks.
You should use background fetching, a system-supplied way of efficiently polling. Think in terms of minutes to hours between each poll. Otherwise, use silent push notification: it will wake up the app to do actual downloading. Read on if you are trying to do this for an actual app that you want in the app store.
Facebook app uses this push-to-download AND also abuses this feature to poll to often, thus draining the battery. That is why most people will turn this feature off for Facebook and hence there is then NO polling at all anymore. So be careful with how much energy you consume for a real app.
For fetching data from background you can use BackgroundFectch mechanism.
All you need to do is
In appdelegate class you have to set the time interval.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];//default fetch interval is never,
return YES;
}
Enable the app for background fetch
Target->Capabilities->backgroundModes->backgroundFetch
3.Final step is implement the following method in app delegate class.
-(void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
Hope this will help you .
There is one sample app in Gitgub in which NSXmlParser is used .You can refer that .
You should use NSTimer for repeatedly performing actions::
The following class method will help you:
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti
target:(id)aTarget
selector:(SEL)aSelector
userInfo:(id)userInfo
repeats:(BOOL)yesOrNo;
Use repeats:YES.
In iOS 7 you have a new background execution method which helps in a situation like this.
Apps that use push notifications to notify the user that new content is available can fetch the content in the background. To support this mode, include the UIBackgroundModes key with the remote-notification value in your app’s Info.plist file. You must also implement the application:didReceiveRemoteNotification:fetchCompletionHandler: method in your app delegate.
So you could send push notification from a server in a timely manner so app can be configured to do the background execution and fetching data.

Resources