Background Service in Appcelerator titanium for iOS - ios

I am facing some problem in background service.I have registered the backgrond service like:var service = Ti.App.iOS.registerBackgroundService({url:'/bgservice.js'});
in bgservice.js :I actually want to check the DB(where the data execution time is>8mins) and trigger local notification.But it is not working.So tried a sample first like this,to see how much time the app is active in background:
var timer = setInterval(startsampletest, 6000);
startsampletest();
function startsampletest(){
count=count+1;
Ti.API.info("1.!!!!!*******startsampletest is called for"+count);
}
which gives me only 5 times every 6 seconds so it is executing only for 30 min(please correct me if I am wrong)But in axway documentation it says the bgservice will be active for 10 mins.
Can anyone pls help me on this.I want the app to be active in background for 10 mins.pls let me know if I have made any mistakes.

It is not guaranteed that a background task created by Ti.App.iOS.registerBackgroundService() will run up to 10 minutes,
see: https://titaniumsdk.com/api/titanium/app/ios/backgroundservice.html#background-service-limitations
... typically to no more than 10 minutes.
But more crucial is that
The OS may terminate the background service at any point to reclaim resources.
For longer background tasks under iOS you have to use
the Ti.URLSession module (com.appcelerator.urlSession).
In general, see https://titaniumsdk.com/guide/Titanium_SDK/Titanium_SDK_How-tos/Platform_API_Deep_Dives/iOS_API_Deep_Dives/iOS_Background_Services.html

Related

withSessionContinueSeconds method doesn't work in Flurry

I have the following code:
let builder = FlurrySessionBuilder.init()
.withAppVersion(appVersion)
.withLogLevel(FlurryLogLevelAll)
.withCrashReporting(true)
.withSessionContinueSeconds(20)
I wanted to increase the number od seconds before the session times out because of the nature of the app I am writing. However, the session timeout is still after 10 seconds rather than the 20 I have specified in my code.
How can I fix this?

How can I get location from background?

My problem is:
Save the user's location every 1 minute and after 15 minutes, push it to the server once. My approach is to create an underground thread. After 1 minute, call the function to save into sqlite 1 time. But how to run the function every 1 minute, in case the application is in the background then how to handle it.
I found the plugin: background_fetch.
But it takes at least 15 minutes to run once.
I've try this and it's working foreground & background (but not terminated):
background_location

Replacement for deprecated UpdateSystemActivity() to reset timers used to measure idle time.

The deprecated UpdateSystemActivity() works by "notifying the Power Manager that activity has taken place and the timers used to measure idle time should be updated to the time of this call."
The documentation recommends using IOPMAssertionCreateWithName(...) but this method doesn't reset the timer for the idle time; it prevents the machine from sleeping forever until IOPMAssertionRelease(...) is called. Using IOPMAssertionCreateWithName(...) is unsuitable for my current codebase.
Are there any non-deprecated methods that reset the timer for measuring idle time?
Thanks!
"it prevents the machine from sleeping forever until IOPMAssertionRelease(...) is called"
I don't observe this behavior with macOS 10.15, not for IOPMAssertionCreateWithName(...) . In contrast to documentation IOPMAssertionDeclareUserActivity(...) seems to behave like UpdateSystemActivity() and needs to be called periodically.
See snippet of Screen Saver timer event
examples/common/ScreenSaver.cpp
I ran into this same problem and discovered this closely related question which points to the IOPMAssertionDeclareUserActivity function.
You can use this:
IOPMAssertionID assertionID;
IOPMAssertionDeclareUserActivity(CFSTR(""), kIOPMUserActiveLocal, &assertionID);
Here is the answer in Swift 3.x:
var assertionID : IOPMAssertionID = 0
_ = IOPMAssertionDeclareUserActivity("TeslaWatcher" as CFString, kIOPMUserActiveLocal, &assertionID)

UIApplicationDidEnterBackgroundNotification remaining time for execution

In my app using iOS 9.2, Swift 2.1 I need to save some data into core data when the app goes to background. For this I registered each of the view controllers in the call path for UIApplicationDidEnterBackgroundNotification notification, with an instance method each for saving respective data.
I read on multiple places that by default the app gets about 5 seconds to finish off the execution and hence we need to use beginBackgroundTaskWithExpirationHandler to extend it to about 5 minutes. Following is an example of the selector method that responds to the above notification.
func applicationEntersBackground()
{
print("Before Extension: \(UIApplication.sharedApplication().backgroundTimeRemaining)")
let taskID = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler(nil)
print("During Extension: \(UIApplication.sharedApplication().backgroundTimeRemaining)")
saveCoreData()
if(taskID != UIBackgroundTaskInvalid)
{
UIApplication.sharedApplication().endBackgroundTask(taskID)
}
print("After Extension: \(UIApplication.sharedApplication().backgroundTimeRemaining)")
}
Following is the results of print() statements
Before Extension: 179.933103708318
During Extension: 179.930266333336
After Extension: 179.922843541659
My doubts are
Why is the remaining time about 180 seconds even before I requested for time extension? I tried multiple times. It is always close to 180 seconds and not the 5 seconds as suggested.
Why doesn't the call to beginBackgroundTaskWithExpirationHandler have any impact on the remaining time?
Once the applicationEntersBackground method of a VC returns, similar notification is sent to another VC's corresponding method. Suppose 180 seconds is the total extended duration and VC1 spends about 10 seconds on notification handling, does VC2 notification handler get around 170 seconds between its beginBackgroundTaskWithExpirationHandler - endBackgroundTask calls?
Between successive invocations of the notification handlers of different VCs, there is obviously a very short period where the extension request is not active. How does the timing play out in this case? Does the 5 second counter (provided it is true) come back to life as soon as an endBackgroundTask call is made, and possibly terminate the application before the next VC can get its notification?
Appreciate any help.
By looking at the documentation for backgroundTimeRemaining:
While the app is running in the foreground, the value in this property remains suitably large. If the app starts one or more long-running tasks using the beginBackgroundTaskWithExpirationHandler: method and then transitions to the background, the value of this property is adjusted to reflect the amount of time the app has left to run.
To answer your questions:
backgroundTimeRemaining stays around 180 while the application is in foreground so you can tell what time you'd have once you start a background task. This value is not an indicator of how long are you allowed to run without a background task.
beginBackgroundTaskWithExpirationHandler has an impact, as you can see, the remaining time decreased (by a small value as the method doesn't take much time)
What matters here is the time passed between the call to beginBackgroundTaskWithExpirationHandler and the one to endBackgroundTask. You can split whatever you need the time interval between your calls, providing you don't exceed the 180s limit
Once you call endBackgroundTask the application will be suspended, regardless it took 2 seconds or 179 seconds.
You can find out more details about application entering background here. I'd recommend going through the documentation, it might clarify other questions you might have on this matter.

Execute a line of code after a certain amount of time in the background on iOS 7

To provide some context, the application I'm working on allows the user to record a series of events along a timeline. One important piece of feedback we received from beta testers was that when the user exits the app while recording they'd like the timer to keep up to date for a set amount of time.
For example if the user has recorded 5 minutes and then leaves the app to check an email for 20 seconds, the timer should be 5:20, but it was actually still 5 minutes.
So we've fixed that - the app now would now show 5:20, and this works in the background.
However we can't figure out a way to stop it after a certain amount of time. A user might want the timer to resume if the app is in the background for a short amount of time, but if you leave it in the background for 30 minutes, the timer will update, and I'd like to be able to give the users an optional cut-off time so that the app pauses after a set amount of time.
I've tried listening out for UIApplicationDelegate notifications, but the problem is I'm looking for a point between applicationDidEnterBackground: and applicationWillTerminate, but there's sadly nothing to cater for my needs there.
To summarise, I'd like to have a grace period of 30-60 seconds from applicationWillResignActive: to determine whether or not to pause the timer, or let it keep going.
Would this be possible?
Thanks in advance
It's generally a bad idea to assume your app will be running in the background.
A better way to think about it IMO would be to set a variable to the current time in applicationDidEnterBackground: and check the time interval to now in applicationWillBecomeActive: :
If the interval is bigger that your grace period, have the time backup to when the app was paused.
If it is smaller, update it as if the app was never in the background.
Use dispatch_after to execute a block of code after a certain number of second:
int64_t delay = 30.0; // In seconds
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC);
dispatch_after(time, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0ull), ^(void){
//DO SOMETHING
});
Swift 3.0 Xcode 8.0 Code sample:
Using delegate methods : applicationWillBecomeActive & applicationWillResignActive to capture the time in between.
OR
let deadlineTime = DispatchTime.now() + .seconds(30)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
alert.dismiss(animated: true, completion: nil)
}
Hope this helps.

Resources