The app I'm working on is used on an iPad in a retail display. The device has auto-lock turned off, and the app will show a video loop as a type of screensaver after a minute of inactivity. We are using the GA iOS SDK 2.0 beta to track sessions, with a session timeout of 60 seconds. The app starts a session on startup, and also when the screensaver is dismissed by a touch. This is all working fine except for the multiple 0-10 second long sessions we get, with average duration of 0:00. We can start the app, go through a couple of 60 sec. sessions, then get those sessions reported along with 2-3 of the 0-10 sec. sessions. From what I can see the app only starts sessions when it is supposed to, so I'm wondering if this is related to how Google calculates a session. I haven't seen anything in the documentation that explains this and I'm stumped.
Just found this answer from my friend
http://support.google.com/analytics/bin/answer.py?hl=en&answer=1144430&topic=1011345&ctx=topic
In my app I only have one view controller that uses [tracker trackView:#"my screen name"] and I have this stuck this in the AppDelegate.m for now as I hadn't got around to tracking views/screens yet. According to the linked material, the way GA calculates session duration is based on time between views. Since I only have one view defined (and not properly within the viewController), this may be the reason I'm getting so many 0-10sec sessions. Going to explore.
It might possible you are initiating a new session before tracking a event/pageview. Please Ensure that you are not starting new session everytime.
Refer this link
https://developers.google.com/analytics/devguides/collection/ios/v3/sessions
Related
I have done some research on the iOS widget refresh mechanism:
1 With containing app in the foreground, the widget refresh is not limited
Read the apple developer docs, I learned that the widget refresh is controlled by the WidgetKit budgets. As it states:
For a widget the user frequently views, a daily budget typically includes from 40 to 70 refreshes
But in the following cases, the reload doesn’t count against the widget’s budget:
The widget’s containing app is in the foreground.
The widget’s containing app has an active audio or navigation session.
The system locale changes.
Dynamic Type or Accessibility settings change.
2 We can use WidgetCenter.shared.reloadTimelines to refresh widget from containing app
The same doc says:
In the game widget example above, if the app receives a push notification indicating a teammate has given the character a healing potion, the app can tell WidgetKit to reload the timeline and update the widget’s content.
3 I have seen some great implementation on this
Apps like LiveIn gives me a smooth user experience with widget refresh timely when I got a post from my friends (as long as the containing app is in the foreground, guess they can improve this with Background Refresh).
This product is not limited by the daily 40 to 70 refreshes budget limitation, and I get a little delay (little enough to be ignored) between the picture display in containing app and the widget.
4 But I'm still stuck here
But when I tried to build an app using the above API WidgetCenter.shared.reloadTimelines or WidgetCenter.shared.reloadAllTimelines to notify the widget to refresh with data stored in UserDefaults, my widget does not respond to the API call timely. Sometimes, it may be stuck for more than 10 minutes, which is a terrible case far far away from the product I mentioned above.
5 Some hack attempts
I have looked through so many Stackoverflow QAs & blogs and do find some tricky things in the iOS widget. For example, the View._clockHandRotationEffect(.secondHand, in: .current, anchor: .center) API can be used to refresh the widget view without limits (usually used to build clock based applications).
But it seems to have nothing to do with the message notification between the containing app and the widget (or it is just I have not figured it out yet).
6 My question
So here comes my question. As some apps existing on the iOS store already have the capability to notify widgets timely, why can I still not get the smooth user experience guided by the official documentation? Do I miss some things important here, or they are just using other private APIs that are out of my sight?
The code is not complex and the Xcode signing is annoying, so I do not prepare a minimal project to reproduce this. You may take pawello2222/WidgetExamples as a demo if you want to give it a try. Any hints or clues will be highly appreciated!
Finally, we get a smooth user experience. The solution is quite strange at first glance but works like a charm compared to our earlier implementation.
All you need to do is to call WidgetCenter.shared.reloadTimelines or WidgetCenter.shared.reloadAllTimelines after the application goes into foreground as soon as possible.
Why? As the doc Managing Your App's Life Cycle states:
a foreground app has the user’s attention, so it has priority over system resources, including the CPU
The doc is clear but the time is also important, there are some phenomenons we test to be as is but cannot be found in any official documentation (running app in release, not debug mode with xcode connected):
Launch the app in the foreground all the time, notifying the widget to refresh the view by calling WidgetCenter.shared.reloadTimelines or WidgetCenter.shared.reloadAllTimelines constantly, the delay will increase significantly as time goes by
When calling WidgetCenter.shared.reloadTimelines or WidgetCenter.shared.reloadAllTimelines after the app starts ASAP, the widget view will refresh instantly (almost 100% success rate)
I've seen many developers stuck in the refresh mystery of the iOS widget and give up using it finally. Hope my experience will help others a better understanding and make a decision more quickly.
#Lebecca I just want to add more insights from my side. Hope you find it helpful.
In my app I call WidgetCenter.shared.reloadAllTimelines just before my app goes to background. I have no problem with this Reload at all. Reload success rate is 100%.
From my experience, when app goes to background, you have few seconds to do some work, after that the process is killed. It is possible that your widget need more time to reload than the time allowed. That's why you do not see the Reload consistently. And that the solution that you call WidgetCenter.shared.reloadTimelines as soon as application goes into foreground fix this because you give the widget "more" time for it to finish the Reload. (When app in foreground, you do not have limit on processing time.)
There are 3 parts involving widget reload.
Data for the widget: if your app need to run some code or retrieve some information from the network. Be sure it doesn't take too long, otherwise the widget reload process can be killed.
Complexity of the widget: Here I mean whether your widget view is complex or not. Many Stacks, many elements will potentially cause the widget Reload to fail.
How many timeline entries you have: Say if you have 100 timeline entries for a day, this might cause some problems as well. You need to find the balance of timeline entries and number of Reloads you plan to run on a day.
Widget Reload budget. I always try to keep it around 40-50 times per day, just to be safe.
Widget is really a mystery. Above are all from my experience.
I want to stop users from launching my app if Auto-Lock time is set to Never on iPhone. Any thoughts on how I can find out the value for Auto-Lock?
It is currently not possible to do this via the available public APIs so you probably won't be able to implement this functionality.
You can however track the last user input, so that you could for example "log out" your app after a period of inactivity. This has been described for example in this SO question.
We use the v3 Google Analytics iOS SDK. We are currently using google's automatic session management in production. Every screen on the app is tracked. My average session time is 25 minutes. Session time is skewed either very low or very high. 30% of sessions are 0-10 seconds and 60% are 181+ seconds.
Google's documentation says that they count each screen view, even if the user comes back to the same screen after the app is in the background. I verified that is true based on testing in a controlled environment. First I added manual session tracking to the app using this. I opened the app for the first time in a brand new Google Analytics app-id at 12:36pm. Then I put it in the background. Then opened it again and backgrounded it again. After 15 minutes I had a correct session count of 2 and a screen count of two. Then I removed the manual session counting and did two more sessions at 12:55pm. After about 10 minutes, my session count was 3 and my screen count was an accurate 4. The session count with the automatic tracking seemed to be off by one, but on the low side. Given this test, I can't understand what's going on in production.
Logically, each session necessarily requires at least one screen view. So how could the session count be greater than the screen count in production? What I'm seeing is that the session count is about double the screen count. How could this be?
So it turns out that if you're using background fetch or background location services, thedidFinishLaunchingWithOptions AppDelegate method is called - and the Google Analytics libraries tell you to put the session startup code there. If you gate that code around the UIApplicationState, you can avoid the phantom sessions. (See more here: http://mikethinkingoutloud.com/issues-with-google-analytics-and-ios-7-background-fetch/)
We are using GA for Flash in our iOS app ported over with Adobe Air and are seeing some funky numbers being collected in Google Analytics. We ran some tests and saw that every time the app was opened it would count both a new visit and a new unique visit, even if it was just a minimize and re-open.
We would assume that the 30 minute time out would be in effect here and that even on a quick minimize and re-open that GA would count that as one visit. This doesn't seem to be the case.
Does anyone know how we could set-up the GA implementation to record unique visits based off of a user ID given on first launch of the app, and/or have it accurately count visits?
Has anyone seen something similar to this before?
Google Analytics allows you to set up Custom Events to track user interactions so this could be dispatched depending on a flag stored in a config file (to determine if it is the first time the application is run).
Depending on your implementation of Air, i.e AS3 / Javascript, if you are using AS3 you may have to utilise the ExternalInterface api to call a javscript method from the application.
This would then allow you to track these custom events and ignore the erroneous default visits?
It's straight forward to add a web page as a web application. Find here a nice article.
The issue know is keeping a session open. Once switching to another app the session is closed and the user needs to re-enter his credentials.
I've found a similar entry without answer in stack-overflow.
Some hints ?
Instead of storing the login info in a $_SESSION variable, store it in a $_COOKIE. The cookie will be saved depending on when you set it to expire. As long as they log in "inside" the web app, or the regular web version (and the cookie is the same) they will not have to log in every time or when switching between the two.
The trick is to do this:
// Start or resume session
session_start();
// Extend cookie life time by an amount of your liking
$cookieLifetime = 365 * 24 * 60 * 60; // A year in seconds
setcookie(session_name(),session_id(),time()+$cookieLifetime);
I tested this to work on iOS 4.2.1, 5.1.1, 6.0 and 6.1. The session is even restored after turning off and restarting the device.
For a more elaborate discussion of this strategy you can take a look at my answer of this question:
Maintain PHP Session in web app on iPhone