Flurry: how to call -logEvent:withParameters:timed: when session ends? - ios

I'm working with the Flurry API for iOS and I've come across a use case that doesn't seem to be supported:
I'm starting a timed event with -logEvent:timed: to track how long a user spends on a view. While the user is on that view a few parameters are being tracked that I plan to pass along to -endTimedEvent:withParameters: when the user navigates away from the view).
Here is the tricky part, if the user backgrounds the app while on the view, Flurry will automatically end the timed event after 10s without setting any parameters. One solution of course is to observe UIApplicationWillResignActiveNotification and call -endTimedEvent:withParameters: myself. However, I'd like to respect Flurry's setSessionContinueSeconds property and not end the event until the session is over. This way if the user returns to the app within 10s they are still under the same event that is tracking their time on the view.
Is there a way to do this?
For instance, is there a delegate method called when the session willEnd/didEnd where I could manually call -endTimedEvent:withParameters: before Flurry does? or alternatively is there a way to append parameters to a timed event while it is active (without ending it). That way when Flurry ends the session, the event already has the parameters set.

1) Flurry has a feature (only on iOS) to allow sessions to continue into the background that you can try for this use case.
[Flurry setBackgroundSessionEnabled:Yes]
You can find more details about these and other methods in the Analytics readme document that is included with our SDK.
[Flurry setBackgroundSessionEnabled:(BOOL)backgroundSessionEnabled];
This option is disabled by default. When enabled, Flurry will not finish the session if the app is paused for longer than the session expiration timeout. The session report will not be sent when the application is paused and will only be
sent when the application is terminated. This allows for applications that run in the background to keep collecting events data. The time application spends in the background contributes to the length of the application session reported when the application terminates.
[Flurry pauseBackgroundSession];
This method is useful if setBackgroundSessionEnabled: is set to YES. It can be called when application finishes all background tasks (such as playing music) to pause the session. A session report is sent if setSessionReportsOnPauseEnabled is set to YES. If the app is resumed before the session expiration timeout, the session will continue, otherwise a new session will begin.
2) You can keep the data in an array and place the parameters into a separate event that triggers after the timed event instead.

Related

Track Google Analytics Event in applicationWillTerminate

I want to track when the user closes the app. For this I send an event to google analytics in applicationWillTerminate. However this event never reaches the server. However the documentation states:
If a user loses network access or quits your app while there are still hits waiting to be dispatched, those hits are persisted in local storage. They will be dispatched the next time your app is running and dispatch is called.
Hence I would assume, that even if it does not manage to dispatch the tracked event in applicationWillTerminate it would do so on restart, after some time. Unfortunately it does not.
Next I tried to call GAI.sharedInstance().dispatch() to force Google Analytics to dispatch the event, but it also did not.
Do I miss something, or is it simply not possible to track events in applicationWillTerminate?
If your application terminates, there is simply no time to make a network connection. applicationWillTerminate is for frontend uses for most occurrences.
You might store a variable in UserDefaults when the application terminates and send the request with the data stored there after the next app launch.

Will download resume after closing my app in Background Mode

I figured out about it is possible to download in background mode of application. I have implemented Background Fetching Mode in XCode and registered background task and its working fine.
Is it possible to resume downloading task after force closing my application by user? How?
No, you can't continue download when your app get terminated by user! Your app must require to remains in background state!!! Because if user force close app that means, he doesn't want to run it anymore. If your app is suspended by system then it can be wake up but not if it's terminated by user!
If an iOS app is terminated by the system and relaunched, the app can use the same identifier to create a new configuration object and session and retrieve the status of transfers that were in progress at the time of termination. This behavior applies only for normal termination of the app by the system. If the user terminates the app from the multitasking screen, the system cancels all of the session’s background transfers. In addition, the system does not automatically relaunch apps that were force quit by the user. The user must explicitly relaunch the app before transfers can begin again.
Update : (As asked in comment)
Refer the apple documentation, It states,
This method lets your app know that it is about to be terminated and purged from memory entirely. You should use this method to perform any final clean-up tasks for your app, such as freeing shared resources, saving user data, and invalidating timers. Your implementation of this method has approximately five seconds to perform any tasks and return. If the method does not return before time expires, the system may kill the process altogether.
For apps that do not support background execution or are linked
against iOS 3.x or earlier, this method is always called when the user
quits the app. 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. However, this method may
be called in situations where the app is running in the background
(not suspended) and the system needs to terminate it for some reason.
After calling this method, the app also posts a
UIApplicationWillTerminate notification to give interested objects a
chance to respond to the transition.
When any task completes, the NSURLSession object calls the delegate’s URLSession:task:didCompleteWithError: method with either an error object or nil (if the task completed successfully).
If the task failed, most apps should retry the request until either the user cancels the download or the server returns an error indicating that the request will never succeed. Your app should not retry immediately, however. Instead, it should use reachability APIs to determine whether the server is reachable, and should make a new request only when it receives a notification that reachability has changed.
If the download task can be resumed, the NSError object’s userInfo dictionary contains a value for the NSURLSessionDownloadTaskResumeData key. Your app should pass this value to call downloadTaskWithResumeData: or downloadTaskWithResumeData:completionHandler: to create a new download task that continues the existing download.
If the task cannot be resumed, your app should create a new download task and restart the transaction from the beginning.
checkout here: Life cycle of URL Session
Yes—if I understood your need right—Apple allows this with State Preservation and Restoration APIs:
Return your app to its previous state after it is terminated by the system.
Check Apple's article: Preserving Your App's UI Across Launches, for an overview of this framework.
Details about preservation process can be found in article: About the UI Preservation Process
Details about restoration process can be found here: About the UI Restoration Process
Raywenderlich have—a little outdated—tutorial implementation of this framework # State Restoration Tutorial: Getting Started

why are my new flurry parameters not showing up?

I have been tracking flurry events in my iOS app and they show up in the dashboard. I tried to add a new parameter to an existing event, and then activated the event on my phone a bunch of times yesterday, but I still don't see any occurrences of the new parameters on that event in the dashboard.
Does flurry not allow you to add new parameters to an existing event?
We noticed this too a little bit ago, and emailed support#flurry.com about it. Here's what they said:
Typically, Flurry sessions never completely report back to Flurry until the next time the app is launched. So, be sure to launch the app one more time after you complete a testing session. Furthermore you should make sure you launch the same build of the app. If you make a new build between sessions you may be removing incomplete sessions before they get reported. If you are running tests via an emulator, please ensure that the home button is pressed before closing the app. Then you should relaunch the app one more time with the same build to ensure all session data is reported.
If the app pauses or moves to the background for more than 10 seconds, the NEXT time the app runs, Flurry agent will automatically create a new session and end the previous session. Otherwise, Flurry agent will continue the same session. This can be updated via the setSessionContinueSeconds method. If the app is terminated, a new session will be created when the app runs again.
When we receive the complete session data (after the app is relaunched) the event logs should update first within 10 minutes or so. Please allow about 6 hours for this to populate to the dashboard, parameters pie chart etc.
Basically, what we were doing is just booting up the app, doing the thing that would send an analytic event, then quitting the app or whatever. Which wasn't giving the flurry agent enough time to actually send the event. (turns out that, contrary to the log events, flurry wasn't sending the log event right then :/)
Hope that helps!
The Flurry SDK only communicates with our servers twice per session. The first time is when the session is started and sets the timestamp for the session, counts a new user or updates an existing user as active. The second time is when the session ends and all event data is sent in one batch.
In cases where we do not receive the second report we refer to this as an "incomplete session". This arises in a few scenarios but mainly
-No network connection when the session ends
-The app is sent to the background for >10 seconds and the session continues running
In these cases the event data is stored on the device's disk and sent the next time the app is launched.

Is Facebook Caching FBAppEvents

I'm trying to integrate FBAppEvents. I've already created my app and all I need to do now is call FBAppEvents logEvent:
However, I want to know if I need to cache my Events just in case logging wasn't successful due to sudden connection loss or something. If I'm caching them, my app could resend the events.
If FB is caching events and handling failed events on their own, then that would be awesome.
If not, then I would need to create my own event caching. Sadly, I couldn't find callback methods to inform me that events were successfully logged or not. Is there a way I could do to achieve what I want?
From the FBAppEvents documentation page: https://developers.facebook.com/docs/reference/ios/current/class/FBAppEvents
Events are not sent immediately when logged. They're cached and
flushed out to the Facebook servers in a number of situations:
when an event count threshold is passed (currently 100 logged events). when a
time threshold is passed (currently 15 seconds). when an app has gone
to background and is then brought back to the foreground.
Events will be accumulated when the app is in a disconnected state,
and sent when the connection is restored and one of the above 'flush'
conditions are met.

applicationDidEnterBackground and network request

I have an iOS game in which I track the number of levels a player plays in a session. A session corresponds to the period between the user pressing the app icon on the home screen and pressing the home button to leave the app.
Surprisingly I don't seem to be getting the leave event for a large fraction of my users. I have implemented the log transmission as follows:
- (void)applicationDidEnterBackground:(UIApplication *)application
{
...
[[EventLogger sharedEventLogger] pushEvent:LEAVE_GAME];
}
...where EventLogger sends an asynchronous HTTP POST request using the ASIHTTP library.
Could it be that the system preempts the transmission before it finishes? It could be that the app crashes and never gets to this point, but that is unlikely.
Have you read the documentation for this method?
" You should use this method to release shared resources, save user data, invalidate timers, and store enough app state information to restore your app to its current state in case it is terminated later. You should also disable updates to your app’s user interface and avoid using some types of shared system resources (such as the user’s contacts database)...Your implementation of this method has approximately five seconds to perform any tasks and return. If you need additional time to perform any final tasks, you can request additional execution time from the system by calling beginBackgroundTaskWithExpirationHandler:. In practice, you should return from applicationDidEnterBackground: as quickly as possible. If the method does not return before time runs out your app is terminated and purged from memory."
Sounds to me like what you're doing is not suggested for this method, but you can try using this beginBackgroundTaskWithExpirationHandler.
I can't be certain that this is the explanation for your issue, but it seems plausible and is consistent with the fact that it isn't being logged only for a portion of your users.
May also be of use:
The system sends a UIApplicationDidGoToBackground notification when the home button is pressed.

Resources