Create and document a reference app for the 'trampoline' technique for testing backgrounding/foregrounding
See this thread for details: https://groups.google.com/d/topic/frank-discuss/P_GBguSux_s/discussion
The mentioned trampoline technique is a bit too complicated. Why not use Safari as the Trampoline app instead?
I am sorry for my ruby, still learning. The following code works in my tests.
When /^I send the app to background for ([\d\.]+) second(?:s)?$/ do |num_seconds|
# you have to define a scheme to start your application, let's use app-scheme://
#this code creates a html page redirecting immediately to the given URL
html_format = "<!DOCTYPE HTML><html><head><title></title><meta http-equiv=\"refresh\" content=\"0;URL='%{LINK}'\"></head><body></body></html>"
html = html_format % { :LINK => 'app-scheme://launch' }
# let's save the HTML to a temporary file
file = Tempfile.new(['launch', '.html'])
begin
file.write(html)
ensure
file.close
end
# let's send the app to the background and wait the specified time
press_home_on_simulator
# I had some an exception when I returned too fast, so I am setting minimum duration
sleep [num_seconds.to_f, 5.0].max
# open the html file in the simulator
%x( /usr/bin/open "#{file.path}" -a "iPhone Simulator" )
# Need to give some time to process the html and redirect us back to the app
sleep 5
file.unlink
end
That's really neat!
I really like this Safari technique, but unfortunately it's restricted to only working on the Simulator, and only working if your ruby code is running on the same machine as the Simulator.
It's feasible that SimLauncher could be extended to solve the second issue, but I don't think there's a way to use this technique if you're running on a physical device (or is there?).
That's very true. The entry point is a click on the home button and that's impossible on device. I was thinking it could be possible to create a html file in the app (or in the temp folder), open it in safari with openURL: and let it redirect back to the app but as far as I know, this is impossible.
Creating the file on the device and writing it to disk sounds like it could work on the device. Did you confirm that this isn't possible on a device?
The problem is how to open the file in Safari. The scheme would have to be http:// because Safari cannot be opened by file://.
Another idea could be to use the frank HTTP server to share the html and then open safari using http://localhost:.../....
I thought I had a cunning solution using the javascript: scheme, but apparently you can't open a javascript: URL with [UIApplication openURL] :(
Cheers,
Pete
Typed on a little bitty keyboard
On Apr 19, 2013, at 12:59 PM, ondrejhanslik [email protected] wrote:
The problem is how to open the file in Safari. The scheme would have to be http:// because Safari cannot be opened by file://. Another idea could be to use the frank HTTP server to share the html and then open safari using http://localhost:.../....
— Reply to this email directly or view it on GitHub.
I was experimenting a bit and I have successfully opened a file in Safari from the application installed on device.
The trick is to publish the file using frank server and then use openURL: with localhost:37265/.... However, it's also necessary to call -[UIApplication beginBackgroundTaskWithExpirationHandler:] otherwise Frank won't be able to receive requests.
When I have more time, I will try to make a patch.
This sounds like a fine approach. Nice find!
If you do get a chance to work on it, it'd be good to make the return URL configurable, along with how long the trampoline pauses before bouncing back to the return URL.
Cheers,
Pete
Typed on a little bitty keyboard
On Apr 29, 2013, at 3:32 PM, ondrejhanslik [email protected] wrote:
I was experimenting a bit and I have successfully opened a file in Safari from the application installed on device. The trick is to publish the file using frank server and then use openURL: with localhost:37265/.... However, it's also necessary to call -[UIApplication beginBackgroundTaskWithExpirationHandler:] otherwise Frank won't be able to receive requests.
When I have more time, I will try to make a patch.
— Reply to this email directly or view it on GitHub.
Thanks for the code, @ondrejhanslik! I made some changes to your step definition to remove the need to explicitly sleep.
https://gist.github.com/rhgills/5761416
@rhgills Hi, there is a reason I have an explicite sleep. In theory, it should be possible to use wait_for_frank_to_come_up. However, when the application goes to the background and then opens up again, there is a short period of collision when a new server is being started and any request you send during that moment will make the application crash (the reason is - the old server is accepting requests and FrankCommandRoute is a singleton shared by both servers => the old server is iterating command routes while new server is modifying them).
Also, if you happen to send a request when the application is on the background, you'll get a connection exception.
[I will fix the collision problem sooner or later but I dont' currently have the time]
@ondrejhanslik Thanks for your reply. I ran into the 'collection mutated while being enumerated' issue when tinkering with that code, but not in the version that I posted. Sounds like I'm just getting lucky; thanks for the heads up. I did spend a bit of time looking for the cause and found that a new server is started whenever the application becomes active, as you mention - but looking at the console logs, the new server seems to fail to bind the address that is still in use by the old server. If I'm understanding right, the problem is that the new server is setting up its routes as part of initialization while the old server is handling a query (which, I wonder, was sent before going to background or after returning from the background?). This raises the question: why start a new server when the app returns from the background? Is the old server invalidated by moving to the background? I changed the notification from UIApplicationDidBecomeActive to UIApplicationDidFinishLaunching and it didn't seem to break anything.
After this is all sorted out, wait_for_frank_to_come_up and a future wait_for_frank_to_go_down seem like an even better solution for waiting than what I was playing with.