Implementing a persistent clock - iphone

I'm currently working on a new game for iOS using Cocos2D. The game needs to advance states after x amount of time since the first launch. So for example:
State - Time
initial launch
24hrs
48hrs
My first idea was to just get the data and time on first launch and save it to a file. Then I could check it ever now and again to see how much time has passed. The problem with this is I need it to be in realtime so that the changes will take effect immediately once the state is reached. It also needs to continue when the user is not using the app. The functionality I'm looking for is kind of similar to how the iOS strategy games work where you build structures that take x amount of time.
Anyway my question(s) is; is there some sort of library that can accomplish this and how can I get it to continue after the user exits the app?

It can't. There is - apart from kind of misusing video/music playing etc. no way for your app to do work while it is not running.
You have two things you can do to simulate that behavior (and I suppose the strategy games do this, too):
You can calculate at any time while a user is still running your app the points in the future when something should happen (eg a housing structure is finished). When the user leave your app, store these future times as local events - then the user will get notified that something has happened in your game (eg message "The church has been built. Do you want to go to church now?)". Pressing yes will open your app, and you can do whatever is necessary to indeed build the church. So in fact you don't do it at the time when it occurred, but when the user opens your app the next time.
Like 1, but without notification. Just remember when the user leaves the app (eg in your settings, I would use a property list; set it when the app delegate gets the appWillResignActive event), and the next time he starts do whatever would have been done in the meantime - he won't be able to tell the difference :-).
It's all about make believe here :-).

Related

Restrict user to use only network provided time

I made an attendance app in Flutter in which I want to restrict employees to use only network provided time so that employees won't be able to temper the date and time.
Is there any option or solution to implement this in android and iOS as well?
Using this package datetime_settings we will get the settings of Automatic date & time of mobile so when automatic date & time is on mobile will give us an accurate network time otherwise we will show an error to turn on the automatic date & time in settings. That's how I used to restrict users to use only network-provided time.
I'll tell you what worked for me. Hope this can help you. I don't know if it's the most optimized way to do it, but it worked very well for me:
You need to create an internal clock for your app, and from this, use it instead of the DateTime.now() function. For this, you must take the server time when opening the app, and keep it updated with a timer that runs every 1 second.
Please note that the app goes to sleep (or closes) when the device is locked or the app is minimized for a certain amount of time (this depends on the operating system and battery saver settings), thereby stopping the internal clock, and consequently, it is delayed when the app is activated again. In my case, I got around this problem by using a foreground service that I designated to perform this task (I used flutter_foreground_task). Another advantage of using a foreground service, is that the user can close the app and the clock keeps running (and in my case, I also perform other simple tasks periodically).
If the user does not manipulate the system time, the difference should never reach 1 second.
Optionally, you could check when retrieving the server time, the difference with the device time, and if it is greater than a certain gap that you determine, warn the user, so that he can correct it if he prefers, so that he does not see a discrepancy with the time recorded and displayed by the application.
Regards.

Wake app at regular intervals while using UIBackgroundModes=location

I'm developing a navigation app which uses the UIBackgroundModes=location setting and receives CLLocationManager updates via didUpdateToLocation. That works fine.
The problem is that the intervals between location updates are very hard to predict and I need to make sure the app is called something like once every few seconds to do some other (tiny) amounts of work even if the location did not change significantly.
Can I do that? Am I allowed to do that? And how can I do that?
I found a blog post, but I'm not sure if this is really the way to proceed.
Permissible background operations are pretty limited in scope. You cannot, for example, just leave an NSTimer running to perform some arbitrary code while your application is in the background - so the simple answer to your question is no, you cannot. Definitely read the Apple documentation regarding what is and isn't allowed (most of what's allowed pertains to apps that "need" specific ongoing services, like the ability to play music, or respond to location changes (GPS type apps...). You may be able to construct a viable solution by responding to location or significant location change notifications...

iPhone games that continue even when you're away

Let's say, Tiny Tower. On this iPhone game, you can have shops in your tower. You can suspend or turn off the iPhone, but when you return to the game, you will be reported about the shop winnings during your time away.
There are also push notifications when a building is complete etc.
I fear I do not understand how that works, exactly. I'm not asking for the exact solution, I just need to know where to begin researching. One idea I had some time ago was like calculate the amount of seconds the user was away (current time minus the time when you left) and then calculate shop processing for every one of these seconds. But I'm not sure of that.
A better way would be to calculate before you close the app.
Figure out what time it is, then calculate when in the future certain tasks will be completed. This way, you can schedule push notifications to the server ahead of time.
If you calculate after you have re-opened the app, and you can't run processes with the app closed, how will it know when to push?
Take a look at this article about push notifications to understand a little bit better how they work.
http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/
For offline games you add temporal logic to your items and recalculate when game is launched. For online games you retrieve game state from the server, which is constantly recalculating for all users, even disconnected ones.
Game most probably does not actually process in the background (most apps are not allowed to do anything while in background). When you relaunch the game, it calculates how much time has passed, and then processes all the events that would have happened in the meantime.
Additionally, as Paul.s mentioned in comments below, as well as other people in other answers have suggested, on iOS4 you can use local push notifications scheduled before close.
It is either server side execution of the game or if it is a game of chance or something like Farmville where it's determined by time duration.
If you were to make a server and/or game like this then you would need to decide which route to take.
If it will be something where the user has good days and sometimes bad days then you'll need a lot more server power. however, if it's something like time based then you would be able to tell the last time they were logged in and the next time that they should be awarded. you can also take this idea and for each variable that you store, you store how long it takes to be complete and the start time. Then you would do a simple If then o see if the item is ready. The same thing can work for a number of visitors. Where you have 10 visitors per item per hour. If you have two items then each hour you will receive 20 visitors.

OpenFeint achievements performance

I've decided to integrate OpenFeint into my new game to have achievements and leaderboards.
The game is dynamic and I would like user to be rewarded immediately for some successful results, but as it seems for me, OpenFeint's achievements are a bit sluggish and it shows visual notification only when it receives confirmation from the server.
Is it possible to change something in settings or hack it a little bit to show notification immediately as soon as it checks only local database if the achievement has not been unlocked it?
Not sure if this relates to the Android version of the SDK (which seems even slower), but we couldn't figure out how to make it faster. It was so unacceptably slow that we started developing our own framework that fixes most of open feint's shortcomings and then some. Check out Swarm, it might fit your needs better.
There are several things you can do to more tightly control the timing of these notifications. I'll explain one approach and you can use this as a starting point to explore further on your own. These suggestions apply specifically to iOS apps. One caveat is that these suggestions refer to internal APIs in OFSDK 2.8 for iOS and not ordinarily recommended for high level use and subject to change in future versions.
The first thing I recommend is that you build the sample app with your own product key. Use the standard sample app to experiment before applying the result to your own code.
You are going to get the snappiest response by separating the notification pop-up UI from the process of submitting the achievement. This way you don't have to worry about getting wrapped up in the logic for deciding whether the submission is going just to the local db or is doing the full confirmation on an async network transaction.
See the declaration of "showAchievementNotice" in "OFNotification.h". Performing a search in the sample app, you will see that this is the internal API used for displaying the achievement pop-up when an achievement is earned. It does not actually submit the achievement. You can call this method directly as it is called from "OFAchievementService.mm" to directly control when the message appears. You can then use the following article to disable the pop-up from being called when the actual submission occurs:
http://support.openfeint.com/dev/notification-pop-ups-in-ios/
This gives you complete freedom to call the submission at a later time provided you keep track of the need to do so. For example, you could locally serialize a flag to take care of the actual submission either after the level is done or the next time the app starts up. Don't forget that the user could quit out of a game without cleanly finishing a level.

iPhone: How to Implement a HTML Welcome Panel

I'd like to integrate something like a welcome panel (welcome screen) into our iPhone application to inform our users about updates and new offers when they launch the application. I have the following thoughts and doubts:
No user input required
Shows generic HTML without any action from the user point of view, the thing closes after 2 or 3 secs and has a close button if you want to close it manually. This is for advertising and tips.
This should be very simple to implement
User input required
Shows generic HTML with an action required from the user point of view, for example a survey. The user should be able to skip it
same as above, but is it possible that the user submits something on a HTML page and that causes also something to happen within the iPhone app (maybe via Java Script)? For example the user submits a survey on the HTML page and then app closes the current screen and continues to the next screen (i.e. the real application)?
Is it also possible to receive parameters (e.g. an ID) via a HTML website? e.g. if the user receives an offer on the HTML welcome panel, then he clicks on it and it takes him directly to a screen in the iPhone app with content loaded from a server (via JSON) depening on the offer id retrieved through the HTML page.
We prefer implementing it via HTML, because it gives us more flexibility. But I'm also open to hear other suggestions.
Thanks
Rengers answer is the correct one to accomplish what you want. However, the real correct answer is "Don't do that in the first place."
From a design perspective, a "Welcome Panel" or any kind of startup/splash-screen is a bad idea and the Apple Documentation tells you explicitly not to use them. Even for games, they're a bad idea that should be avoided if possible.
It's not a "Welcome Panel" it's a "wade-through-all-our-marketing-crap-before-you-can-actually-use-our-app" panel.
Mobile apps aren't like apps for regular platforms. Non-mobile hardware is faster so the obtrusive startup screens load faster and can be dismissed faster. Non-mobile apps tend to accomplish many task and people use them sitting down for prolonged periods. Users will tolerate a few seconds wasted clicking through startup screens so they can get into an app they will use for many minutes or even hours.
By contrast, mobile apps are often used by people on the go and in a hurry. The apps are small and ideally perform a single task. As quickly as possible, people need to be able to get into the app, perform what ever task the app accomplishes and then get back out again. If you're only using an app each time for 30 seconds or so, having to spend 5 seconds each time wading through startup screens is massively annoying.
Mobil hardware is slower and operations can take longer. Depending on its complexity and resources an app can take as much as 10 seconds to launch. In your case you want to add to a startup screen that has to load, connect to a url, display and then have the user perform an operation. That will take another 5-10 seconds minimum. So you're looking at users having to spend 20 seconds or more just getting into your app.
That doesn't sound like much but try mocking up your app and then using it on the go i.e. while walking, waiting for an elevator, going up the stairs, waiting for a red light etc. Test it in social situations. In the middle of conversation say, "Let me check on that" then take out the iPhone launch your app and try to get some information from it. 20 seconds becomes a very long time in all these circumstances.
Even shorter launch times are very annoying if you have to take some action every single time you open the app just to get to the functional part of the app. It's arguably even worse to spring a startup screen on them intermittently so they never know when they open your app how long it will take to get in it. User surprise is not good design.
Instead of forcing users to do something, you should embed advertisements and update notices unobtrusively in the app itself so that people can see them while they are using the app. In the case of advertising, this has the added advantage of putting the adds in view the entire time the user is looking at the app.
I don't know how many times some idiot from marketing has come in and started a feature request with, "We need to force the user to..." The only response to those types of request is to set the marketing weeny on fire. Do that several times and they'll stop trying to systematically alienate your customers.
UIWebViewDelegate has a method that allows you to respond to interaction in a HTML page:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
Using this, you can catch any links clicked and respond to them in your application by presenting a different view.
Recieving parameters like an id can be done in a few different ways.
1) You can parse the HTML and determine it from the source.
2) You can have a javascript function in the HTML that returns the id. Call it by using
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
3) You can also use the delegate method I mentioned.
If you make a link like this: get offer you can catch it in the delegate and retrieve the id from the NSURLRequest.
I hope this will point you in the right direction.
If you do need some kind of startup screen a good option is to use the default.png. The app loads and displays that image before it does anything else.
It's usually used to display the illusion of the user interface before the UI loads completely. However, you could use it to display startup information. Since it displays almost instantly (within 1 sec) it does give your user something to look at while the app loads. In the case of a mock interface, it lets the user see the location of the interface elements and begin moving to activate them before the elements finish loading.
The catch is that the image disappears as soon as the first view loads so you have to load a view behind it that is a duplicate of the image (more ofter the image is screenshot of the view)
In your case you would need to dynamically generate the default.png when the web page updated. Upon launch it would display the information and buy the time the user read it, made a decision and touched the interface, the real web page would have replaced it.
Of course, this system won't work if you want new info at the start of each launch. Instead you'll have to generate the image during one run for use in the next.
In any case, if you launch into a web page the user did not select, I advise that you create a default.png that displays a message along the lines of "Checking for Updates and Info" (or whatever your doing) so the user won't think your app launched and hung.