<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" version="2.0">

<channel>
	<title>Web Developer's Life in Beta</title>
	
	<link>http://nachbaur.com</link>
	<description>Making broken software somewhat less broken</description>
	<lastBuildDate>Fri, 13 Nov 2009 04:44:44 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/nachbaur" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="nachbaur" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">nachbaur</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
		<title>Last minute talk on automated Perl builds using Hudson tonight</title>
		<link>http://nachbaur.com/blog/last-minute-talk-on-automated-perl-builds-using-hudson-tonight</link>
		<comments>http://nachbaur.com/blog/last-minute-talk-on-automated-perl-builds-using-hudson-tonight#comments</comments>
		<pubDate>Thu, 12 Nov 2009 19:29:32 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[perl]]></category>
		<category><![CDATA[ContinuousIntegration]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[shell scripting]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[Unit testing]]></category>
		<category><![CDATA[Web development]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=191</guid>
		<description><![CDATA[My friend Scott McWhirter, who heads up the Vancouver Perl Monger&#8217;s group, asked me yesterday to give a last-minute talk on anything in particular at tonight&#8217;s Vancouver.pm meeting.  He wasn&#8217;t exactly begging, but I know he&#8217;s short on speakers this month, and he wanted something interesting to show.
So I decided I&#8217;d talk about building [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Flast-minute-talk-on-automated-perl-builds-using-hudson-tonight"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Flast-minute-talk-on-automated-perl-builds-using-hudson-tonight" height="61" width="51" /></a></div><p>My friend <a href="http://cloudtone.ca/">Scott McWhirter</a>, who heads up the <a href="http://www.socialtext.net/vanpm/index.cgi">Vancouver Perl Monger&#8217;s group</a>, asked me yesterday to give a last-minute talk on anything in particular at <a href="http://www.socialtext.net/vanpm/index.cgi?meeting_november_12th_2009">tonight&#8217;s Vancouver.pm meeting</a>.  He wasn&#8217;t exactly begging, but I know he&#8217;s short on speakers this month, and he wanted something interesting to show.</p>
<p>So I decided I&#8217;d talk about building and testing Perl-based projects using Hudson.  I&#8217;ve been planning on writing a blog post on the subject for the past month, but haven&#8217;t found the time to finish off the post properly.  So if you&#8217;re interested in the topic, and you don&#8217;t want to wait for me to get around to writing about it online, please feel free to drop by tonight!</p>
<hr /><strong>Update:</strong> The talk went well! Until I have time to put a more comprehensive post up on the topic, you can always read <a href="http://www.slideshare.net/nachbaur/automating-perl-deployments-with-hudson">the slides from tonight&#8217;s talk</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Flast-minute-talk-on-automated-perl-builds-using-hudson-tonight&amp;linkname=Last%20minute%20talk%20on%20automated%20Perl%20builds%20using%20Hudson%20tonight"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=dpxjidgnQmk:bZVd53inMJ8:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dpxjidgnQmk:bZVd53inMJ8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dpxjidgnQmk:bZVd53inMJ8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dpxjidgnQmk:bZVd53inMJ8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=dpxjidgnQmk:bZVd53inMJ8:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/last-minute-talk-on-automated-perl-builds-using-hudson-tonight/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>I’m in Movember this November</title>
		<link>http://nachbaur.com/blog/im-in-movember-this-november</link>
		<comments>http://nachbaur.com/blog/im-in-movember-this-november#comments</comments>
		<pubDate>Wed, 04 Nov 2009 17:39:50 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[life]]></category>
		<category><![CDATA[movember]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=185</guid>
		<description><![CDATA[Just like most of the men at my office, I&#8217;m participating in Movember this year, largely due to the razzing I got last year when I didn&#8217;t participate.  Yes, I&#8217;ve succumbed to peer pressure&#8230;what would my mom say?  At least it&#8217;s for a good cause.  Of course, the first question I asked [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fim-in-movember-this-november"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fim-in-movember-this-november" height="61" width="51" /></a></div><p>Just like most of the men at my office, <a href="http://ca.movember.com/mospace/28361/">I&#8217;m participating in Movember this year</a>, largely due to the razzing I got last year when I didn&#8217;t participate.  Yes, I&#8217;ve succumbed to peer pressure&#8230;what would my mom say?  At least it&#8217;s for a good cause.  Of course, the first question I asked is &#8220;What&#8217;s Movember?&#8221;  It&#8217;s a fundraising event for prostate cancer where men grow mustaches during the month of November.</p>
<p>While I can grow a mustache fairly well, I really don&#8217;t look good with one.  So hopefully I won&#8217;t have too many pictures taken of me this month.  And if you want me to feel better about it all so I don&#8217;t feel like it was a total waste, please head on over to my Movember profile page and donate a few bucks, or more.</p>
<p><a href="http://nachbaur.com/wp-content/uploads/2009/11/p_1600_1200_20A3FB5B-C558-4B88-95FD-504BD78D06DD.jpeg"><img src="http://nachbaur.com/wp-content/uploads/2009/11/p_1600_1200_20A3FB5B-C558-4B88-95FD-504BD78D06DD.jpeg" alt="" width="225" height="300" class="alignnone size-full wp-image-364" /></a></p>
<p>As you can see, it&#8217;s a few days and it&#8217;s at a respectable and not-yet-annoying length. If you contribute, you get a vote on what style my mustache should be. I figure of I&#8217;m going to have nasty facial hair, I might as well go for it wholeheartedly. So <a href="http://ca.movember.com/mospace/28361/">donate to a good cause</a>, frustrate my wife, and get a few good laughs in.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fim-in-movember-this-november&amp;linkname=I%26%238217%3Bm%20in%20Movember%20this%20November"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=v-1FB6s-S-Y:-n6ZYlusN1w:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=v-1FB6s-S-Y:-n6ZYlusN1w:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=v-1FB6s-S-Y:-n6ZYlusN1w:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=v-1FB6s-S-Y:-n6ZYlusN1w:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=v-1FB6s-S-Y:-n6ZYlusN1w:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/im-in-movember-this-november/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Telling your user that a PhoneGap application is busy</title>
		<link>http://nachbaur.com/blog/telling-your-user-that-a-phonegap-application-is-busy</link>
		<comments>http://nachbaur.com/blog/telling-your-user-that-a-phonegap-application-is-busy#comments</comments>
		<pubDate>Mon, 26 Oct 2009 17:00:09 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=169</guid>
		<description><![CDATA[Plenty of times in applications, especially on mobile devices, you just need to tell your users to hold their horses and wait while your application processes something in the background.  Maybe you need to query some data from a remote server, save a file to disk, or maybe you just need to do some number [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Ftelling-your-user-that-a-phonegap-application-is-busy"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Ftelling-your-user-that-a-phonegap-application-is-busy" height="61" width="51" /></a></div><p>Plenty of times in applications, especially on mobile devices, you just need to tell your users to hold their horses and wait while your application processes something in the background.  Maybe you need to query some data from a remote server, save a file to disk, or maybe you just need to do some number crunching.  Whatever the reason, you don&#8217;t want your user to think the program has crashed if you don&#8217;t give them some sort of visual feedback that you&#8217;re busy and they just have to wait a few seconds.</p>
<p>PhoneGap provides a few methods to handle just this task. There&#8217;s four methods within the Notification class that are of interest.</p>
<ol>
<li>navigator.notification.loadingStart()</li>
<li>navigator.notification.loadingStop()</li>
<li>navigator.notification.activityStart()</li>
<li>navigator.notification.activityStop()</li>
</ol>
<h3>Modal loading messages</h3>
<div id="attachment_171" class="wp-caption alignright" style="width: 310px"><a href="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-Notification-Loading-1.png"><img class="size-medium wp-image-171" title="PhoneGap Modal loading notification" src="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-Notification-Loading-1-300x121.png" alt="Modal loading indicator" width="300" height="121" /></a><p class="wp-caption-text">Modal loading indicator</p></div>
<p>The easiest approach to take when making your users wait is to show a modal loading dialog, one that doesn&#8217;t let the user interact with the application until you&#8217;re done.  There&#8217;s a lot less for you, as a developer, to manage when the user isn&#8217;t allowed to poke around on buttons when you&#8217;re updating the display.  Asynchronous operations are a lot simpler when you&#8217;re in control.</p>
<p>The loadingStart() and loadingStop() methods do just this.  They put up a modal semi-transparent layer over top of your application, with a &#8220;Loading..&#8221; spinner message. You simply call the first method when your application is about to do something, and when it finishes you call the second.</p>
<p>Here&#8217;s an example of how to use it.  This will load a remote HTML document and place its contents into a node in your PhoneGap application.</p>
<p><script src="http://gist.github.com/212444.js"></script></p>
<p>Not only does this make it easier to integrate external content into your PhoneGap application, but it guarantees your user is informed that it&#8217;s actively working.  As a final bonus, if your external web site doesn&#8217;t respond, or if the user doesn&#8217;t have an Internet connection, the modal loading screen will close after a timeout.</p>
<h3>Asynchronous loading messages</h3>
<div id="attachment_170" class="wp-caption alignright" style="width: 217px"><a href="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-Notification-Activity-1.png"><img class="size-full wp-image-170" title="PhoneGap Activity loading notification" src="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-Notification-Activity-1.png" alt="Asyncronous activity loading indicator" width="207" height="89" /></a><p class="wp-caption-text">Asyncronous activity loading indicator</p></div>
<p>Sometimes you want to tell your user that the application is busy, but you still want to continue using the app anyway.  If your app doesn&#8217;t turn off the top statusbar (where the time, reception, and battery status is displayed), you can control the busy indicator from within PhoneGap.  Just like the above example, you just have to call the appropriate PhoneGap JavaScript methods.  In this case, just update the above example with these messages:</p>
<pre style="padding-left: 30px;">navigator.notification.activityStart();
// Do something that might take a while...
navigator.notification.activityStop();</pre>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Ftelling-your-user-that-a-phonegap-application-is-busy&amp;linkname=Telling%20your%20user%20that%20a%20PhoneGap%20application%20is%20busy"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=CYqUkH6Xzm8:6yqp8DLOGSM:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=CYqUkH6Xzm8:6yqp8DLOGSM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=CYqUkH6Xzm8:6yqp8DLOGSM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=CYqUkH6Xzm8:6yqp8DLOGSM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=CYqUkH6Xzm8:6yqp8DLOGSM:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/telling-your-user-that-a-phonegap-application-is-busy/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>How to use the native Alert dialog in PhoneGap</title>
		<link>http://nachbaur.com/blog/how-to-use-the-native-alert-dialog-in-phonegap</link>
		<comments>http://nachbaur.com/blog/how-to-use-the-native-alert-dialog-in-phonegap#comments</comments>
		<pubDate>Mon, 19 Oct 2009 17:00:28 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=163</guid>
		<description><![CDATA[An important part to any application is issuing a simple alert to your user.  Whether it&#8217;s to tell them about an error that just occurred, or if you need to ask them a simple question, giving a message to your user is about the most basic part of any app.
Sadly, when you try to [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-native-alert-dialog-in-phonegap"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-native-alert-dialog-in-phonegap" height="61" width="51" /></a></div><div id="attachment_167" class="wp-caption alignleft" style="width: 166px"><a href="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-AlertExample-1.png"><img class="size-medium wp-image-167 " title="PhoneGap Alert notification" src="http://nachbaur.com/wp-content/uploads/2009/10/PhoneGap-AlertExample-1-156x300.png" alt="PhoneGap's custom alert notification is nicely customizable" width="156" height="300" /></a><p class="wp-caption-text">PhoneGap&#39;s custom alert notification is nicely customizable</p></div>
<p>An important part to any application is issuing a simple alert to your user.  Whether it&#8217;s to tell them about an error that just occurred, or if you need to ask them a simple question, giving a message to your user is about the most basic part of any app.</p>
<p>Sadly, when you try to rely on the ever faithful &#8220;alert()&#8221; function in JavaScript inside a PhoneGap application, you&#8217;ll notice the alert box it shows is titled with a very unprofessional &#8220;index.html&#8221; across the top.  Not only does it make it obvious that the app they&#8217;re interacting with is actually HTML-based, but you can&#8217;t convey the importance of one message or another with a title.  Most people only ever read the title anyway, so in order to provide this capability to your application, PhoneGap has an answer for this problem.</p>
<p>Inside PhoneGap there&#8217;s a class called &#8220;Notification&#8221; which is used for, well, sending notifications to your user.  And, by calling:</p>
<pre style="padding-left: 30px;">navigator.notification.alert(
  message,
  title,
  buttons...,
  options);</pre>
<p>Everything, except for the message, is optional.  The more arguments you provide, the more you can customize the alert box.  For instance, if you don&#8217;t supply a button label, one single &#8220;OK&#8221; button will be created.  Want to ask a Yes/No question?  Simply pass two labels for their respective button names.</p>
<p>Like other functions in PhoneGap, the alert notification can be passed an &#8220;options&#8221; object that allows you to give it more information, such as an onClick callback.</p>
<p><script src="http://gist.github.com/212064.js"></script></p>
<p>That example shows how to ask your user what to do in the event of an Internet connection problem.  You&#8217;ll notice that I&#8217;ve decided to pass two button labels.  In the onClick callback function I supplied in my options argument, I&#8217;m checking the &#8220;buttonIndex&#8221; variable it passes.  This tells your function which button was pressed.  If you want more than 2 buttons, just list multiple labels and it will show as many as can fit on the screen.</p>
<p>A very simple function, but invaluable as a developer resource.  And, more importantly, a very easy and professional way to get feedback from your user.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-native-alert-dialog-in-phonegap&amp;linkname=How%20to%20use%20the%20native%20Alert%20dialog%20in%20PhoneGap"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=dHuC43nIwj4:sy-wD2cqwFs:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dHuC43nIwj4:sy-wD2cqwFs:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dHuC43nIwj4:sy-wD2cqwFs:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=dHuC43nIwj4:sy-wD2cqwFs:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=dHuC43nIwj4:sy-wD2cqwFs:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/how-to-use-the-native-alert-dialog-in-phonegap/feed</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Device.saveScreenshot added to PhoneGap</title>
		<link>http://nachbaur.com/blog/device-savescreenshot-added-to-phonegap</link>
		<comments>http://nachbaur.com/blog/device-savescreenshot-added-to-phonegap#comments</comments>
		<pubDate>Sun, 18 Oct 2009 22:26:40 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=179</guid>
		<description><![CDATA[One of the integral features of the next application I&#8217;m releasing (I&#8217;ll write a post about it soon, honest) is the capability of saving a copy of the user&#8217;s work in my app to their Photo Library.  For a while now I&#8217;ve been wanting to be able to save screenshots from within PhoneGap for [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fdevice-savescreenshot-added-to-phonegap"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fdevice-savescreenshot-added-to-phonegap" height="61" width="51" /></a></div><p>One of the integral features of the next application I&#8217;m releasing (I&#8217;ll write a post about it soon, honest) is the capability of saving a copy of the user&#8217;s work in my app to their Photo Library.  For a while now I&#8217;ve been wanting to be able to save screenshots from within PhoneGap for two main reasons:</p>
<ol>
<li>Be able to export the user&#8217;s work and allow them to email it, import it into other applications, etc.</li>
<li>Save a screenshot to their splash-screen image, that way when the application restarts it shows their previous state while they wait (for example, the Notes application on the iPhone).</li>
</ol>
<p>I&#8217;ve implemented #1 right now, meaning with a simple non-blocking call you can save the current view to the photo library.  In the future I&#8217;ll add another three options: Save to the default splash-screen image, save to a file, and save and upload to a remote location.</p>
<p><a href="http://github.com/NachoMan/phonegap/commit/2aa71cf15d1a51a0f4ebb742603034e8dd3b3101">Check out the check-in I&#8217;ve made</a> and if you have any comments, please let me know!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fdevice-savescreenshot-added-to-phonegap&amp;linkname=Device.saveScreenshot%20added%20to%20PhoneGap"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=05L-V41xMpk:CyYLWx-58cw:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=05L-V41xMpk:CyYLWx-58cw:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=05L-V41xMpk:CyYLWx-58cw:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=05L-V41xMpk:CyYLWx-58cw:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=05L-V41xMpk:CyYLWx-58cw:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/device-savescreenshot-added-to-phonegap/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to use the ActionSheet in PhoneGap</title>
		<link>http://nachbaur.com/blog/how-to-use-the-actionsheet-in-phonegap</link>
		<comments>http://nachbaur.com/blog/how-to-use-the-actionsheet-in-phonegap#comments</comments>
		<pubDate>Fri, 16 Oct 2009 17:00:16 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=157</guid>
		<description><![CDATA[The ActionSheet is a handy control on the iPhone, and is a very intuitive way of getting a multiple-choice answer from a user in a modal but unobtrusive way.
Using it in PhoneGap makes interacting with your user easy, while keeping the display responsive.  And as an added bonus, you don&#8217;t need to update any [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-actionsheet-in-phonegap"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-actionsheet-in-phonegap" height="61" width="51" /></a></div><p>The ActionSheet is a handy control on the iPhone, and is a very intuitive way of getting a multiple-choice answer from a user in a modal but unobtrusive way.</p>
<p>Using it in PhoneGap makes interacting with your user easy, while keeping the display responsive.  And as an added bonus, you don&#8217;t need to update any HTML or CSS to get the buttons to look right.  The native iPhone codebase handles it for you.</p>
<p>So the question is, how do you use it effectively?  As most Web2.0-style developers are aware, the only sensible way to develop flexible applications that don&#8217;t bog down the browser is to make your applications behave asynchronously, and make use of callback functions to get feedback from external systems (HTTP requests, users, etc).  The ActionSheet on PhoneGap is no different.</p>
<p>The ActionSheet is grouped into the PhoneGap &#8220;Dialog&#8221; class, and is called like so:</p>
<pre style="padding-left: 30px;">dialog.openButtonDialog(title, buttons..., options);</pre>
<p>The title property lets you specify the label to show at the top of the ActionSheet.  If you don&#8217;t want a title, then simply pass in a null value.</p>
<p>The list of buttons is specified as a series of objects, which I&#8217;ll describe below.</p>
<p>Finally, the options let you customize how the ActionSheet is displayed (via the &#8220;style&#8221; property) and lets you set an onClick handler for the entire ActionSheet.</p>
<p><script src="http://gist.github.com/211046.js"></script></p>
<p>The example above illustrates several options of the ActionSheet PhoneGap control.</p>
<ol>
<li>On a per-button basis you can specify your own onClick callback which will be run when that button is pressed.</li>
<li>A global onClick handler can be specified in the openButtonDialog options argument, which will get called no matter what button is pressed.</li>
<li>You can choose what the appearance of the dialog should be (currently only &#8220;opaque&#8221; and &#8220;translucent&#8221; are supported)</li>
<li>A button requires a label property, but you can optionally specify a &#8220;type&#8221; property (can be &#8220;normal&#8221;, &#8220;cancel&#8221; or &#8220;destroy&#8221;).</li>
</ol>
<p>The callback functions are simply called with two arguments, the index of the button being clicked, and the label of the button the user clicked on.  So if it&#8217;s easier for you to work with array indexes, or with text labels, you can easily find out which button was pressed and when.</p>
<p>So go ahead and try out the ActionSheet control.  Either you can use my latest release in <a href="http://github.com/NachoMan/phonegap" target="_blank">my branch of PhoneGap</a>, or you can use these more advanced features once my changes have been merged in with <a href="http://github.com/phonegap/phonegap" target="_blank">the official branch</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-use-the-actionsheet-in-phonegap&amp;linkname=How%20to%20use%20the%20ActionSheet%20in%20PhoneGap"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=NO9840LVBL0:Ek3Bi5OwE-o:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=NO9840LVBL0:Ek3Bi5OwE-o:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=NO9840LVBL0:Ek3Bi5OwE-o:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=NO9840LVBL0:Ek3Bi5OwE-o:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=NO9840LVBL0:Ek3Bi5OwE-o:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/how-to-use-the-actionsheet-in-phonegap/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>In-App purchases allowed for free apps on the App Store</title>
		<link>http://nachbaur.com/blog/in-app-purchases-allowed-for-free-apps-on-the-app-store</link>
		<comments>http://nachbaur.com/blog/in-app-purchases-allowed-for-free-apps-on-the-app-store#comments</comments>
		<pubDate>Thu, 15 Oct 2009 21:20:20 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=161</guid>
		<description><![CDATA[Finally, what we&#8217;ve all been waiting for.   Apple just announced that they&#8217;re allowing In-App purchases for free apps, and not just paid apps.  This means, as an app developer, I can develop a single app for the app store for free, but can allow my users to upgrade to the full paid version [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fin-app-purchases-allowed-for-free-apps-on-the-app-store"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fin-app-purchases-allowed-for-free-apps-on-the-app-store" height="61" width="51" /></a></div><p>Finally, what we&#8217;ve all been waiting for.   Apple just announced that they&#8217;re allowing In-App purchases for free apps, and not just paid apps.  This means, as an app developer, I can develop a single app for the app store for free, but can allow my users to upgrade to the full paid version without having to split it up into a &#8220;Lite&#8221; and &#8220;Full&#8221; version.</p>
<p>I can&#8217;t wait to apply this to my apps!</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fin-app-purchases-allowed-for-free-apps-on-the-app-store&amp;linkname=In-App%20purchases%20allowed%20for%20free%20apps%20on%20the%20App%20Store"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=tpFgcYYnxEg:B4pLKDnIGcM:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=tpFgcYYnxEg:B4pLKDnIGcM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=tpFgcYYnxEg:B4pLKDnIGcM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=tpFgcYYnxEg:B4pLKDnIGcM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=tpFgcYYnxEg:B4pLKDnIGcM:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/in-app-purchases-allowed-for-free-apps-on-the-app-store/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>How to automate your iPhone app builds with Hudson</title>
		<link>http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson</link>
		<comments>http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson#comments</comments>
		<pubDate>Mon, 12 Oct 2009 17:00:30 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[build]]></category>
		<category><![CDATA[debugging]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[testing]]></category>
		<category><![CDATA[Unit testing]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=139</guid>
		<description><![CDATA[As any iPhone application developer who&#8217;s released at least a single app to the App Store will tell you, releasing your app is a terrible pain in the&#8230;well, it&#8217;s not a fun experience.  After your second or third app you start to get the hang of things, but there&#8217;s still pain and suffering involved.  Managing [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-automate-your-iphone-app-builds-with-hudson"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-automate-your-iphone-app-builds-with-hudson" height="61" width="51" /></a></div><p>As any iPhone application developer who&#8217;s released at least a single app to the App Store will tell you, releasing your app is a terrible pain in the&#8230;well, it&#8217;s not a fun experience.  After your second or third app you start to get the hang of things, but there&#8217;s still pain and suffering involved.  Managing certificates, getting settings configured properly, and iterating between development, AdHoc beta builds, and the final App Store release builds, all make the process seem tediously manual and prone to human error.</p>
<p>In professional software development shops, you would use a Continuous Integration server to monitor your source control repository, check out changes as they&#8217;re submitted, compile, test and package up builds, and notify developers of the build&#8217;s health via emails and a web-based &#8220;Dashboard&#8221;.  I missed having this while developing my PhoneGap-based iPhone applications, so I decided to once and for all bring good development practices to my iPhone work.</p>
<h2>Why do I need to configure automated builds anyway?</h2>
<p>I get this a lot from people when I&#8217;m trying to convince them of the need for automated builds.  I personally find it hard to imagine people getting by without them in a single-developer project, let alone when multiple developers contribute to a project.</p>
<h3>Monitoring the health of an application</h3>
<p>Lets face it, we&#8217;re human, and we make mistakes.  It&#8217;s alright to break code from time to time, but what really sucks is when you find out far too late.  Did your recent changes accidentally eliminate your Entitlements.plist file, thus breaking distribution or release builds?  Do you have a file or library you forgot to check in, meaning when you delete the project from your working directory all those changes will just vanish?</p>
<p>Instead of having to remember to check each of those things manually (which, lets face it, you&#8217;ll forget at least half of the things you&#8217;re supposed to do inevitably), why not have an automated system tell you every time you make a change?  And if you&#8217;re in a multi-developer project, you&#8217;ll be able to see who broke the build and what change specifically broke it.</p>
<h3>Always be ready for distributing your application</h3>
<p>Many times in the natural course of development you&#8217;ll break code.  You&#8217;ve gotta break something in order to improve it.  But sometimes someone (your wife, a client, a beta tester) will want to try out your application before you have an opportunity to finish off your recent changes.  Instead of spending ages back-tracking your work to get your application to compile, why not rely on your automated build system to keep archives of previously successful builds?</p>
<h3>Release what you test</h3>
<p>Since you want to test an application before you release it to the App Store, you&#8217;ll probably create an Ad-Hoc distribution build to give to friends, family, or official beta testers before you bundle your application up to send to the App Store.  Maybe your testers will find bugs, maybe they won&#8217;t.  But at the end of the day that compiled app bundle you just created isn&#8217;t actually what you submit to Apple.  You need to compile a completely different app bundle with very different files stored in a Zip file, and if you&#8217;re not careful you could potentially be releasing something different than what you tested.</p>
<p>Why not have your automated build system create both your Ad-Hoc distribution build as well as an App Store release build every time?  That way you&#8217;re not only always ready to release something to the App Store, but you can be guaranteed that you&#8217;re submitting to Apple the exact code that your testers evaluated.</p>
<h3>More benefits than I can list</h3>
<p>If you&#8217;re really serious about best practices, you&#8217;ll probably want to write unit tests for your code and have those run after your code has been compiled, but before your build is packaged and archived.  Just because your code compiles doesn&#8217;t mean that it will behave correctly.  And lets face it, if you have a lot of tests, you&#8217;ll never wait for all of them to run throughout the course of your work.  So by running your tests as a prerequisite to a build succeeding, you&#8217;re guaranteed that you&#8217;ve got a safety net.</p>
<p>There&#8217;s plenty of other best practices that having an automated build system can help with, so what I&#8217;m discussing here will just cover the tip of the iceberg.  If I&#8217;ve convinced you that automating your builds, read on.</p>
<h2><span id="more-139"></span>Getting started with Hudson</h2>
<p>After evaluating a few solutions, I ended up settling on <a href="http://hudson-ci.org/">Hudson</a> for my build server.  It&#8217;s Open Source, is built in Java so it runs almost anywhere, and it supports Slave build agents which is a must-have for compiling iPhone applications.  You can most likely use anything you want, though the amount of work you&#8217;ll need to do to make it work will vary.</p>
<p>Your first step will be to download and run Hudson itself.  It&#8217;s a self-contained Jar file, so the installation procedure is very simple.  You might want to run it inside its own user account on your computer, but you can decide where and how you want it run.  I have a Linux server that runs my email, websites and contains my source code repository, so I decided to run Hudson there.  I use Hudson to build not only iPhone apps, but my Perl-based webapps and its dependencies, so having it in a central location makes life easier for me.</p>
<p>After you get it up and running, you might want to install a few plugins to help you connect to your source code repository, or to enable you to do different styles of notification (for instance, my build sends me an instant message on GTalk when I break a build).  Play with its configuration options and see what it can provide.</p>
<h3>Create your build job</h3>
<p><a href="http://nachbaur.com/wp-content/uploads/2009/10/hudson-newjob.jpg"><img class="alignright size-medium wp-image-147" title="Hudson: New Job" src="http://nachbaur.com/wp-content/uploads/2009/10/hudson-newjob-300x166.jpg" alt="Hudson: New Job" width="300" height="166" /></a>Of course for your first step you&#8217;ll actually need to build your project is to create a build job.  Go to the dashboard and click &#8220;New Job&#8221;.  Give it a name, and tell it that you want to create a &#8220;Freestyle software project&#8221;.  This means it will simply run a shell script that describes how your build should be done.</p>
<p>Tell the job how to find your source code by pointing it at the proper source code control repository.  It has support for Git, Subversion, Perforce and even CVS.  Most of the defaults for which branch to build from should be fine, but you&#8217;re the best judge of what options to pass to the job.</p>
<p>Once you give it information about where to find your source code, you need to tell it what to do with it.  Under the &#8220;Build&#8221; section, click on &#8220;Add build step&#8221; and select &#8220;Execute shell&#8221;.  This will allow you to enter the name of a script to execute.  Just type in:</p>
<pre style="padding-left: 30px;">"$WORKSPACE/build/build.sh"</pre>
<p>Hudson will check your code out into a directory where it will be built, and the $WORKSPACE variable will be set to the full path where that directory exists.  There are other variables it defines for you, which are described on the job&#8217;s configure page.  By telling the job to run the above command, it will run the &#8220;build.sh&#8221; script that you&#8217;ll add to your project&#8217;s source code repository.  This way the way you build your project can be versioned alongside your actual code.</p>
<h3>Create your build script</h3>
<p>Of course you actually need a script that will call all the necessary commands to build your application.  Luckily Apple provides a command-line tool called &#8220;<a href="http://developer.apple.com/TOOLS/Xcode/xcodebuildsettings.html">xcodebuild</a>&#8221; which is used to build applications.  In fact, this is the exact command that XCode calls when you click the &#8220;Build&#8221; button in the GUI.<br />
<script src="http://gist.github.com/204459.js"></script> This is the full version of my build script, which might not work well for you.  This is almost a drop-in script for PhoneGap apps though, and supports packaging up Release and Distribution builds automatically.  Along with this build script (which can be reused for different iPhone projects), you create a per-project build configuration file that looks like so: <script src="http://gist.github.com/204461.js"></script></p>
<p>This way you can specify the specific certificates each build uses, and which builds you want to create and archive.  The build script will package up the certificate for Distribution builds (that way your beta testers can add the .mobileprovision file to iTunes) and will package up the app&#8217;s icon file with the Release build (so the zip file can just be submitted as-is to Apple).</p>
<p>One of the steps in the build script above is to specify a custom build version number at build-time, based on the Hudson build number.  This means, as a developer, you don&#8217;t have to manually increment version numbers in order for your test application to install through iTunes. I followed <a href="http://www.innerexception.com/2008/10/iphone-app-version-and-build-numbers.html">these instructions on auto-incrementing XCode build version numbers</a>, and altered them to suit my build script.  All the guesswork and human-error is avoided.</p>
<h3>Slave and remote builds</h3>
<div id="attachment_151" class="wp-caption alignright" style="width: 310px"><a href="http://nachbaur.com/wp-content/uploads/2009/10/hudson-macslave1.jpg"><img class="size-medium wp-image-151" title="Hudson: Configuring a Mac Slave" src="http://nachbaur.com/wp-content/uploads/2009/10/hudson-macslave1-300x223.jpg" alt="Screenshot of Hudson's Add Slave screen" width="300" height="223" /></a><p class="wp-caption-text">Screenshot of Hudson&#39;s Add Slave screen</p></div>
<p>One of the limitations of building iPhone applications is that they must be compiled on a Mac with the XCode developer tools installed.  This means in my environment, where Hudson is running on a Linux server, I have to perform my builds on a remote computer.  Luckily at home I have an iMac running in a DMZ of my home firewall, both of which are always running.  So for my builds I configure my iMac to be a slave build server.  I enter its hostname, username and password, and Hudson automatically SSH&#8217;s into my home computer, SFTPs the appropriate Jar files down, and spawns the processes remotely.</p>
<p>At that point you can configure a job to use a specific build machine, or you can tag a set of machines with certain keywords and can bind a job to those tags.</p>
<h3>Publishing build artifacts</h3>
<p>One of the configuration options I specify within my Hudson jobs is I tell it to publish my successful build artifacts (the packaged Zip files for my application releases) over SCP to my web site into a password-protected directory.  From here I can give my beta testers a password to log into my website and to download the latest build, simplifying the beta test cycle.  I just point my testers at a URL and let them test to their heart&#8217;s content.  This is especially useful since a lot of mail servers block iPhone app bundles, thinking they&#8217;re malware or spam of some kind.</p>
<h2>Automatically start builds from your version control system</h2>
<p>The final step needed before you can fully automate your builds is to tie Hudson into your version control system.  The way you tie scripts into your version control system depends on what you use, but for Git, you simply create the following script somewhere in your user&#8217;s account and invoke it from your post-receive hook.</p>
<p><script src="http://gist.github.com/204667.js"></script></p>
<h2>Next Steps</h2>
<p>As I improve my build infrastructure more, I have plans to support pushing releases straight to Apple&#8217;s iTunes Connect interface for me.  My plan is to run a &#8220;Parameterized Build&#8221;, where I can supply options to a build, indicating that I would like to issue a full release.</p>
<p>I also have plans to improve my testing infrastructure, and would even like to try to run tests of my application by interactively controlling the iPhone Simulator.  If anyone has suggestions or experience on doing this, please let me know.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fhow-to-automate-your-iphone-app-builds-with-hudson&amp;linkname=How%20to%20automate%20your%20iPhone%20app%20builds%20with%20Hudson"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=QKz4OPkuYB4:LXjV0FDQwhM:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=QKz4OPkuYB4:LXjV0FDQwhM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=QKz4OPkuYB4:LXjV0FDQwhM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=QKz4OPkuYB4:LXjV0FDQwhM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=QKz4OPkuYB4:LXjV0FDQwhM:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/how-to-automate-your-iphone-app-builds-with-hudson/feed</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>PhoneGap officially permitted on the App Store</title>
		<link>http://nachbaur.com/blog/phonegap-officially-permitted-on-the-app-store</link>
		<comments>http://nachbaur.com/blog/phonegap-officially-permitted-on-the-app-store#comments</comments>
		<pubDate>Wed, 07 Oct 2009 16:15:25 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=135</guid>
		<description><![CDATA[Its been a while since I&#8217;ve made an update to my blog, and I figured it&#8217;s far overdue for a new post.  My life over the past little while has been divided up into 4 chunks: my family, my work, my weekend consulting, and my own personal application development.  Somewhere around the second [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fphonegap-officially-permitted-on-the-app-store"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fphonegap-officially-permitted-on-the-app-store" height="61" width="51" /></a></div><p>Its been a while since I&#8217;ve made an update to my blog, and I figured it&#8217;s far overdue for a new post.  My life over the past little while has been divided up into 4 chunks: my family, my work, my weekend consulting, and my own personal application development.  Somewhere around the second half of that list is sprinkled a bit of PhoneGap development.</p>
<h2>PhoneGap vs Apple, resolved</h2>
<p>First, I&#8217;d like to announce that I&#8217;ve made headway with <a href="http://nachbaur.com/blog/updates-on-apple-phonegap">my interactions with Apple</a>.  They were convinced by my argument that PhoneGap-based apps, just like any other apps developed by users who have access to a rich API, should be judged by their own merits and not prejudged based on what tools were used to built them.  This is fantastic news, and means that apps submitted to the App Store will not be rejected solely because they&#8217;re built on PhoneGap.  Now, if the application is buggy or if a developer tries to do something underhanded with it (for instance, changing the behavior of the app after Apple approves it) that is still cause for a rejection or worse consequences, but the same goes for any application released to the App Store.</p>
<p>Apple did have some requests though.  To ensure that apps are released with a &#8220;Known Good&#8221; version of PhoneGap that they can trust as not having a fundamentally bad design, they wanted to have a version number that would be considered stable and acceptable.  Additionally, they would like to have some way of easily identifying the version of PhoneGap used, so they can easily check that little box that says &#8220;Don&#8217;t reject it just because of its framework.&#8221;</p>
<p>I had a meeting with the good folks at <a href="http://nitobi.com/">Nitobi</a> over a few beer, and ended up <a href="http://github.com/phonegap/phonegap/tree/0.8.0">updating the version number to 0.8.0</a>, and added a version tag that is added at build-time to the compiled iPhone application bundle.  This will make it quicker for Apple to approve your apps, as well as remove any guesswork on their end about whether or not to trust your application.</p>
<h2>The catch&#8230;</h2>
<p>As with all good things in life, there is a catch.  Since Apple doesn&#8217;t have any idea what version of PhoneGap any apps already submitted to the App Store for approval may be running on – and as a result has no idea whether it&#8217;s a safe version of PhoneGap or not – they&#8217;ll have to reject all the PhoneGap applications in their queue, and kindly request that you resubmit your apps once you&#8217;ve updated to the newer version of PhoneGap.</p>
<p>I want to stress that they&#8217;re rejecting these apps only to ensure they&#8217;re running the first Apple-approved PhoneGap version, and not for any other reason.  Once you update and re-submit your apps, they&#8217;ll reenter the queue and will be reviewed just like any other iPhone application.  This doesn&#8217;t mean they won&#8217;t reject your app for some other reason, but at least PhoneGap won&#8217;t be a blocker anymore.</p>
<p>I have some additional announcements and general thoughts on PhoneGap and my use of it to post, but since this news is so big, and since I&#8217;ve been too busy lately to update my blog in a while, I thought I&#8217;d open with this post first.  I&#8217;ll hopefully resume my regular blog posting soon, so please check back later.</p>
<p><strong>Update: </strong>For more information about the origins of my conversations with Apple, see my posts titled <a href="http://nachbaur.com/blog/updates-on-apple-phonegap">Updates on Apple / PhoneGap</a> and <a href="http://nachbaur.com/blog/open-letter-to-apple-iphone-developer-support">Open letter to Apple iPhone Developer Support</a>.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fphonegap-officially-permitted-on-the-app-store&amp;linkname=PhoneGap%20officially%20permitted%20on%20the%20App%20Store"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=U0N9xlN4OSE:MAAy5W56i0A:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=U0N9xlN4OSE:MAAy5W56i0A:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=U0N9xlN4OSE:MAAy5W56i0A:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=U0N9xlN4OSE:MAAy5W56i0A:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=U0N9xlN4OSE:MAAy5W56i0A:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/phonegap-officially-permitted-on-the-app-store/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Updates on Apple / PhoneGap</title>
		<link>http://nachbaur.com/blog/updates-on-apple-phonegap</link>
		<comments>http://nachbaur.com/blog/updates-on-apple-phonegap#comments</comments>
		<pubDate>Mon, 22 Jun 2009 16:38:14 +0000</pubDate>
		<dc:creator>Michael Nachbaur</dc:creator>
				<category><![CDATA[PhoneGap]]></category>
		<category><![CDATA[apple]]></category>
		<category><![CDATA[business]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[software]]></category>

		<guid isPermaLink="false">http://nachbaur.com/?p=124</guid>
		<description><![CDATA[Things have been busy over the past few days, which is the reason why I haven&#8217;t had a chance to post about this until now. But for the PhoneGap community, I have some good news and some bad news.  First, the good news: I got a phone call from the Apple app reviewer that was [...]]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;"><a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fupdates-on-apple-phonegap"><img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fnachbaur.com%2Fblog%2Fupdates-on-apple-phonegap" height="61" width="51" /></a></div><p>Things have been busy over the past few days, which is the reason why I haven&#8217;t had a chance to post about this until now. But for the PhoneGap community, I have some good news and some bad news.  First, the good news: I got a phone call from the Apple app reviewer that was reviewing my test app.  And before I go any further, I want to say a few things.</p>
<p>When I crafted <a href="http://nachbaur.com/blog/open-letter-to-apple-iphone-developer-support">my original letter to Apple</a>, I was very cautious how I wrote it, because I don&#8217;t want to give anyone the wrong impression. I don&#8217;t have any problems with Apple or the fact that they have an app review process. I actually think the strict regulations Apple has with its review process is a good thing for users. If left to their own devices, app developers would release anything and everything whether it had merit or not, in the hopes of earning even a tiny bit of a buck.</p>
<p>That&#8217;s not to say that I have nothing but a big warm and fuzzy feeling for the review process, just that it&#8217;s like going to the dentist. It&#8217;s painful, but you&#8217;ll thank them later in life when your teeth would otherwise be falling out – or, in the case of the App Store review process, when the app store would otherwise be overrun with endless seas of buggy and non-functional crap.</p>
<p>Most developers out there seem to vilify the app reviewers, making them out to be legions of sadistic bureaucrats who like nothing more than to waste developer&#8217;s time. I&#8217;ve never been comfortable with that, because people simply don&#8217;t work that way. The app reviewers don&#8217;t have an easy job.  They&#8217;re not developers, they don&#8217;t know how to write apps, they just review them to ensure they meet the guidelines Apple sets forth.</p>
<p>So when they reject your app, it&#8217;s not because they&#8217;re out to get you, they&#8217;re just enforcing policy.  If they make some assumption about your app, perhaps you&#8217;re not giving enough information to help them along?  There&#8217;s a comments field that you can use to help the reviewer of your app do their job, instead of throwing an app over the fence and saying &#8220;Here, take that&#8221;.  They don&#8217;t owe you anything, and are simply making sure that they cover their asses.  Could you imagine how bad it looked on the guy who reviewed the &#8220;<a href="http://www.techcrunch.com/2009/04/22/feel-like-shaking-a-baby-to-death-theres-an-app-for-that/">Shaking Baby</a>&#8221; app? I&#8217;m not sure if he lost his job, or just got seriously reprimanded, but this is the sort of thing these guys are trying to prevent.  But because of the black-box nature of the whole process, it&#8217;s easy to jump to conclusions.</p>
<p>Finally, before I dig into the meat of my conversation with my App Store app reviewer, I want to point out a few things that many developers seem to have forgotten in their haste to get their apps released:</p>
<p>1.    The app store is a voluntary process; you don&#8217;t want to play by their rules, you don&#8217;t have to.<br />
2.    All developers signed an agreement that states Apple can choose to reject any apps they want based on their own reasons. There&#8217;s no human right&#8217;s violations committed when Apple decides that your app isn&#8217;t fit for the store for some reason.<br />
3.    Apple is a business, whose goals are to advance their stock and market position for their investors. While some of Apple&#8217;s decisions may seem confusing from outside the black box, keep in mind that they are prone to keeping secrets until they throw down their big announcements at whatever annual conference they&#8217;re attending. So there are sometimes more reasons why they wouldn&#8217;t want some feature leveraged by app developers if they plan to do something much the same themselves. Is it fair? No. Is this what they&#8217;re doing? I have no idea, this is speculation on my part.</p>
<p>Now that I have that out of the way, I&#8217;d like to relate to you my conversation with Steve from the App Store.</p>
<p><span id="more-124"></span>My test app, <a href="http://acookie.info/">aCookie Fortunes</a>, was released to the app store ages ago, back when I was still learning how to use PhoneGap (and before I even started to extend and improve it). It is full of bugs, and is badly in need of an update. I made my PhoneGap improvements, and subsequently made a bug fix release. At that point, it sat in Apple&#8217;s queue since March 18th.  I sent a few emails asking where things were with it, but never got anything more than the boilerplate responses.</p>
<p>So I suppose the app store reviewers were just chewing through their back-log of apps.  They&#8217;re basically a support department, and they do the best they can.  So when Steve got around to my app, he looked at the notes, saw the words &#8220;PhoneGap&#8221; in it, and was about to click the reject button.  But since it had been sitting in the queue for so long, he thought he&#8217;d do the right thing and picked up the phone to call me.</p>
<p>Let me pause here for dramatic effect.  This is awesome customer service, in my books.  He certainly didn&#8217;t have to do this, and it shows great initiative on his part, as well as wonderful diligence.  All he had to do was click &#8220;Reject&#8221;, and carry on with his day.  It&#8217;s so easy in this day and age to dehumanize the person on the other end of the computer screen.  To some people I was an entry in a FileMaker-Pro database.  Instead of treating me like a number, he called me on my cell.</p>
<p>I was at work at the time, but took the call anyway – hey, this was big news, and I&#8217;d been waiting for over 3 months.  Over an hour later (1:15 to be exact) I quickly sent out a message to Twitter and got back to work.  We&#8217;d covered a lot of ground in that conversation, but what it basically boils down to is this:</p>
<p>Apple has an unfounded hate-on for PhoneGap.  Most likely their misconceptions are based on early releases of PhoneGap, and they haven&#8217;t taken a second look since then.  Perhaps a few bad-apples ruined it for the rest of us (pun totally intended).  But these impressions are difficult to change.</p>
<p>Steve and I went through the list of every problem PhoneGap was perceived to have, and went through every single point of every single one of the Apple app guidelines that were listed as things that PhoneGap violated. It took a long time, but he would read out each problem, and I would explain to him why they were just flat out wrong.  Some of the problems included the misconception that we were linking to and including a custom-compiled version of WebKit, that we had our own code interpreter built-in, and that we were using private and unpublished APIs on the phone.</p>
<p>I pointed Steve at <a href="http://github.com/NachoMan/phonegap/tree/master">my Github source</a>, at my blog, and at <a href="http://groups.google.com/group/phonegap">the PhoneGap mailing list</a>.  He&#8217;s of course busy with his job too, so he didn&#8217;t have the time to read through the glut of articles that have been posted everywhere, but I did mention that I&#8217;d issued <a href="http://nachbaur.com/blog/open-letter-to-apple-iphone-developer-support">an open letter to Apple</a> regarding this, and that it had been <a href="http://ajaxian.com/archives/someone-at-apple-please-review-stance-on-phonegap">picked</a> <a href="http://www.readwriteweb.com/archives/why_is_apple_rejecting_phonegap-built_iphone_apps.php">up</a> <a href="http://digg.com/apple/Apple_is_rejecting_PhoneGap_iPhone_Apps_for_no_reason">by</a> <a href="http://www.appcraver.com/some-iphone-devs-aren%E2%80%99t-hooking-up-with-the-app-store/">a number</a> <a href="http://gadgetsteria.com/2009/05/20/phonegap-built-apps-getting-the-digital-shaft/">of sites</a> <a href="http://www.bugzappy.com/2009/06/01/apple-we-need-phonegap-allowed-in-the-app-store/">around</a> the &#8216;web.</p>
<p>He asked if there was a way to write my app using something other than PhoneGap, so I could just get it released easier.  Certainly, there are alternatives, and since it&#8217;s just code, anything is possible.  But after explaining to him that the goal of PhoneGap is to write cross-platform apps in a Rapid Application Development fashion, there&#8217;s little to no point in creating some of these apps in the traditional way.</p>
<p>And largely, my persistence in this matter is more than for my own benefit.  I&#8217;m trying to help out the community at large, and want to make sure that all the PhoneGap developers can use it to build great apps, and not have to worry (any more than usual) about Apple rejecting their apps.</p>
<p>So Steve and I came to an arrangement.  He&#8217;d agreed to do his best to work with his superiors to try and reverse their impression of PhoneGap, or at the very least evaluate each PhoneGap-based app on its own merits.  I have no problems with Apple rejecting a crappy PhoneGap app, nor do I have a problem with Apple permanently banning a developer from the App Store if they try and do something subversive, like change the behaviour of an app remotely after an app has been released to the store.  But those are things that any developer can do, whether based on PhoneGap or not.  And if Apple comes back with a list of things that are problems still, then we can fix them.  As I put it, &#8220;I can can fix almost anything with it.  I have a hammer, I just need to see where the nail is so I can hit it.&#8221;</p>
<p>I&#8217;ll post more about this later, after I talk with Steve next.  I have a few experiments I&#8217;m going to run, and Steve will keep an eye on the apps I release over the next few weeks, to see what happens with them as the percolate through the app review process.  He&#8217;ll also be filling me in later if he was able to make any progress with his superiors.</p>
<p>Before I finish up this post, I&#8217;d like to say a big thank you to Steve.  If any of his supervisors are reading this, I want to let you know just how great he is.  He treated me with courtesy, listened to my problems, and didn&#8217;t prejudge me or my app based on any preconceived notions about PhoneGap or app developers as a whole.  He listened to what I had to say, and went above and beyond the call of duty to help me get my app released, and to help me in getting PhoneGap acceptable to the developer community at large.  These are all things he didn&#8217;t have to do, and his day would undoubtedly have been easier had he just clicked the &#8220;Reject&#8221; button.</p>
<p>And in the end, he actually thanked me for being so friendly and willing to help him through getting my app released.  Steve, right back at you, and I look forward to working with you again.</p>
<a class="a2a_dd addtoany_share_save" href="http://www.addtoany.com/share_save?linkurl=http%3A%2F%2Fnachbaur.com%2Fblog%2Fupdates-on-apple-phonegap&amp;linkname=Updates%20on%20Apple%20%2F%20PhoneGap"><img src="http://nachbaur.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share/Bookmark"/></a><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/nachbaur?a=PNcV4xEqnUo:SfuumfYMao4:bcOpcFrp8Mo"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=bcOpcFrp8Mo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=PNcV4xEqnUo:SfuumfYMao4:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=PNcV4xEqnUo:SfuumfYMao4:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/nachbaur?d=qj6IDK7rITs" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/nachbaur?a=PNcV4xEqnUo:SfuumfYMao4:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/nachbaur?i=PNcV4xEqnUo:SfuumfYMao4:V_sGLiPBpWU" border="0"></img></a>
</div>]]></content:encoded>
			<wfw:commentRss>http://nachbaur.com/blog/updates-on-apple-phonegap/feed</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
	</channel>
</rss>
