<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Talk Funnel</title>
	<atom:link href="http://ramin.firoozye.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://ramin.firoozye.com</link>
	<description>Ramin Firoozye's Public Whisperings</description>
	<lastBuildDate>Mon, 01 Feb 2010 16:30:02 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>AutoPark: my first iPhone app</title>
		<link>http://ramin.firoozye.com/2010/02/01/autopark-my-first-iphone-app/</link>
		<comments>http://ramin.firoozye.com/2010/02/01/autopark-my-first-iphone-app/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 16:30:01 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[autopark]]></category>
		<category><![CDATA[frolicware]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=256</guid>
		<description><![CDATA[There&#8217;s been a lot of behind-the-scenes activity around these parts and I hope to be posting more actively from here on out. But first I&#8217;d like to announce my first iPhone product on the AppStore, published under the FrolicWare label:

AutoPark: Say Goodbye to Parking Tickets. It lets you keep track of time on your meter [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a lot of behind-the-scenes activity around these parts and I hope to be posting more actively from here on out. But first I&#8217;d like to announce my first iPhone product on the AppStore, published under the <a href="http://frolicware.com" target="_blank">FrolicWare</a> label:</p>
<p><img src="http://d1avqodpi540yc.cloudfront.net/i/screenshots/ap06s.png" alt="" /></p>
<p><a href="http://autoparkapp.com" target="_blank">AutoPark</a>: <i>Say Goodbye to Parking Tickets.</i> It lets you keep track of time on your meter so you avoid parking tickets. It uses push notifications to send out an early-warning and a separate meter expiration alarm. The intent behind it, however, was to be an all-in-one driving assistant so it does a few more things, like:</p>
<ul>
<li>Help find a parked car using the GPS.</li>
<li>Remember where you parked in a parking lot (floor, section, color zone, etc).</li>
<li>Work with or without push alarms enabled (if away from the data network).</li>
<li>Track time on parking meters or with pre-paid parking machines.</li>
<li>Attach a text and picture note &#8212; handy for remembering what that rental car looks like.</li>
<li>Email all parking data out via a rich HTML message with embedded map and links.</li>
<li>Get a list of nearby local services (bank, gas station, bathrooms) you might need when you&#8217;re parking your car or right before leaving.</li>
</ul>
<p>it&#8217;s available for $4.99 <a href="http://itunes.apple.com/us/app/autopark/id335354555?mt=8" target="_blank">on the AppStore</a> and the first user reviews have been pretty positive. It&#8217;s already made it into <a href="http://macworld.com/article/145871/2010/01/autopark.html" target="_blank">MacWorld Magazine</a>!</p>
<p>But this isn&#8217;t just about a single iPhone app. There are a lot of posts rattling around my head that I&#8217;ll be rolling out gradually: from the evolution of the UI and graphic design, to running a one-person development shop, the economics of app development, the transition to iPad, tips and tricks on developing a push server, and the process of marketing an iPhone app. From conversations with fellow iPhone developers I get the feeling this is information that could be useful to others in their own efforts. </p>
<p>When the AppStore was first announced, I remember thinking this is the first time an individual or a small team can easily bring a software product to market without having to worry about a lot of the hassles of full-bore software publishing. I still think that&#8217;s the case, but I was off by an order of magnitude on the <i>it&#8217;ll be easy</i> department. I&#8217;m going to write about this experience because I think it&#8217;s good to get these things out there for all those people dreaming about starting their own gig.</p>
<p>In the meantime, here&#8217;s a <a href="http://slideshare.net/raminf/iphone-backend-servers" target="_blank">presentation</a> I gave at the January 2010 Silicon Valley iPhone Developer Meetup on development of back-end servers for iPhone apps. I tried to avoid making it about a specific product but it relies heavily on the experience of putting together the AutoPark push notification server.</p>
<p>This is only the first app out of the chute and this is the first post on what goes on behind the scenes. So stay tuned&#8230;</p>
<hr />
P.S. I&#8217;ll be showing off AutoPark (and maybe a peek of an upcoming app) at <a href="http://macworldexpo.com" target="_blank">MacWorld Expo</a> in San Francisco February 9-13, 2010 at the Mobile Application Showcase. This is the first year they&#8217;re featuring iPhone apps so it&#8217;ll be interesting to see how they&#8217;re received in a historically Mac-only conference. It&#8217;s also my first time as an exhibitor (and yes, I&#8217;ll be blogging about it).</p>
<p>Feel free to pop over and say hi.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2010/02/01/autopark-my-first-iphone-app/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Merry Christmas</title>
		<link>http://ramin.firoozye.com/2009/12/07/merry-christmas/</link>
		<comments>http://ramin.firoozye.com/2009/12/07/merry-christmas/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 23:58:50 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[holiday]]></category>
		<category><![CDATA[humor]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=254</guid>
		<description><![CDATA[
(via SketchySantas)
Happy Holidays to all.
]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://ramin.firoozye.com/wp-content/uploads/2009/12/0EBACF67-F1D4-4966-BAA8-850184127ACE.jpg" alt="0EBACF67-F1D4-4966-BAA8-850184127ACE.jpg" border="0" width="500" height="354" /></div>
<p>(via <a href="http://sketchysantas.com" target="_blank">SketchySantas</a>)</p>
<p>Happy Holidays to all.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/12/07/merry-christmas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eval iPhone apps: the good, the bad, and the ugly</title>
		<link>http://ramin.firoozye.com/2009/10/16/eval-iphone-apps-the-good-the-bad-and-the-ugly/</link>
		<comments>http://ramin.firoozye.com/2009/10/16/eval-iphone-apps-the-good-the-bad-and-the-ugly/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 17:49:32 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=223</guid>
		<description><![CDATA[[ This ended up being a fairly long and somewhat technical post. I edited it down as best I could, but I think it's an important topic in the iPhone world and something that has to be laid out in its entirety. I suspect it won't be of much interest unless you're an iPhone app [...]]]></description>
			<content:encoded><![CDATA[<p>[ <i>This ended up being a fairly long and somewhat technical post. I edited it down as best I could, but I think it's an important topic in the iPhone world and something that has to be laid out in its entirety. I suspect it won't be of much interest unless you're an iPhone app developer, a highly technical end-user, or a masochist masquerading as a layperson. You have been warned. - Ed.</i>]</p>
<p><img src="http://ramin.firoozye.com/i/goodbadugly.jpg" width="160" height="210" alt="" /></p>
<p><a href="http://www.tuaw.com/2009/10/15/apple-relents-in-app-purchase-for-free-apps-allows-demo-to-paid/" target="_blank">The news</a> dropped like a bombshell on the iPhone developer community yesterday: Apple is now allowing In App Purchasing in free applications. <i>Hip Hip Hooray!</i></p>
<p>But wait. What does that mean?</p>
<p>I won&#8217;t repeat what I&#8217;ve already said in a <a href="http://ramin.firoozye.com/2009/03/19/eval-applications-on-the-iphone-appstore/" target="_blank">previous post</a> but the upshot is it&#8217;s now possible to ship a free application on the iPhone appstore then ask the customer to purchase an &#8216;unlock&#8217; token once they&#8217;re done evaluating it. The common consensus (as much as what is said on blogs, mailing lists, and twitter can be considered so) in the developer community is that it&#8217;s a positive move. <a href="" target="_blank">Marco Arment</a> (the developer of Instapaper) called it a &#8220;<i>&#8230; great move for both users and developers.</i>&#8221;</p>
<h3>The Good</h3>
<p><img src="http://ramin.firoozye.com/i/thegood.jpg" class="limg" width="110" height="119" alt="" /></p>
<p>With this seemingly small change in policy consumers can (finally) try out an app before they have to pay for it. No more buying an app then realizing it doesn&#8217;t work and getting stuck with a dud. The immediate effect will most likely be fewer impulse sales&#8211;which means lower short-term revenue&#8211;but in the long-term users are more likely to be happy customers instead of accidental ones.</p>
<p>It&#8217;ll also mean that app developers should be able to increase their asking price for well-made apps, because users will have had a chance to take it out for a test run. On the other hand, there&#8217;s no guarantee this will end up increasing per-app revenue given the low conversion ratio from free to for-pay apps. <i>In fact, I&#8217;d strongly question the logic of $0.99 apps even bothering to offer an evaluation version</i>. All those impulse and <i>let&#8217;s try this</i> purchases probably account for a more substantial portion of sales than most developers care to admit.</p>
<p>But the initial developer reaction seems to be positive. Most indy developers in it for the long run would rather have fewer happy customers vs. a lot of unhappy ones.</p>
<h3>The Bad</h3>
<p><img src="http://ramin.firoozye.com/i/thebad.jpg" class="limg" width="110" height="119" alt="" /></p>
<p>First, let&#8217;s take a little detour and define what we actually mean by an <i>evaluation</i> app.</p>
<p>In the regular computer world (versus, you know, the iPhone Candyland) a developer creates an application then offers it to the user for evaluation in one of two possible ways:</p>
<ol>
<li><b>Degraded mode</b>: this is where the application has some of its features disabled, for example, no saving or only printing with a watermark. The user gets to experience what the app does, but only <i>up to a point.</i> How much functionality is included is up to the developer but it&#8217;s in their interest to allow as much as possible to make the sale without giving up too much.</li>
<li><b>Time-limited mode</b>: this is where the application is fully functional for a limited amount of time (usually two weeks to 30 days). After that either the user buys the app or it stops working. A slight variation is where the app reverts to degraded mode when the eval clock runs out.
</li>
</ol>
<p>The main difference between a <em>Time-Limited</em> and a <em>Degraded</em> app is what the developer allows the user to experience during that period of time. That&#8217;s an important distinction because the end-user experience was noted by Apple as the main reason they initially didn&#8217;t allow In App Purchasing in free apps. The reasoning was that a user should not be told an application is free, then be forced to pay for it. But it appears that concerns for application piracy and loud complaints from developers have overridden those worries. But the problem is still valid. Hopefully Apple will make changes to the Appstore to better communicate the actual <i>fully unlocked</i> price to avoid end-user confusion.</p>
<p>There&#8217;s also a subtle issues unique to the <em>Time-limited</em> app on the desktop and that is what to do when the user tries to get around the evaluation restrictions &#8212; ostensibly to keep using the application in full evaluation mode <em>ad infinitum</em> without having to pay. The two most common methods are settings back the system clock (to make the app think the eval time hasn&#8217;t run out), or to uninstall then reinstall an app to reset the meter.</p>
<p>The solution to both of these problems is fairly simple: the app can write an <em>already run</em> token and periodically save a time-stamp in such a way that persists beyond an application getting uninstalled. Then it&#8217;s fairly easy to detect if the clock has moved back or if an app has been reinstalled.</p>
<p>But that&#8217;s the desktop. What about the iPhone? The problems are the same. Some users may be tempted to keep an eval app (especially a high-priced one) running. Can the clock reset trick work? Yes, it can. Most users leave their phone&#8217;s clock in its default auto-update mode so they can use their phone to keep track of time. But it&#8217;s fairly easy to reset it manually. All you have to do is run the <em>Settings</em> application, go under <em>General</em> tab and disable <i>Set Automatically</i> then set the clock to whatever date and time you want. The down-side to this is that so much of what you do on a typical iPhone relies on the system clock so it&#8217;s unlikely someone will be willing to put up with having a constantly skewed clock on their phone for the sake of just one application. But you never know.</p>
<p>What about the delete/reinstall method? On the iPhone, once an app has been deleted all associated files are also removed so there would have to be a way to save a persistent token that outlasts the app install-delete cycle. On the iPhone, unlike the Mac, no such place exists. The app developer <i>could</i> always save the unique device ID (UDID) of the phone on a server, but the Apple developer license explicitly forbids saving private user data off the phone. Does the UDID count as private data? It certainly is unique. We&#8217;ll have to see. But at the very least, it means each developer has to maintain server infrastructure to track this sort of thing.</p>
<p>So as it currently stands it&#8217;s too easy for a user to simply remove and reinstall an app or to fiddle with their clock and continue using an app in its fully-functional <i>eval</i> mode. I&#8217;m pretty sure this isn&#8217;t what Apple had in mind when allowing In App purchases.</p>
<p>That leaves <i>Degraded</i> mode. This means that the application the user would download from the Appstore for evaluation wouldn&#8217;t be the full version. In an earlier draft of the developer license agreement shipping this type of app was explicitly forbidden. In the newly revised version, well, it&#8217;s not so clear. In Attachment 2.4 it is clearly stated that:</p>
<blockquote><p>2.4	You may not use the In App Purchase API to send any software updates to Your Application or otherwise add any additional executable code to Your Application. An In App Purchase item must either already exist in Your Application waiting to be unlocked, be streamed to Your Application after the purchase transaction has been completed, or be downloaded to Your Application solely as data after the purchase transaction has been completed.</p></blockquote>
<p>This means that the full application functionality must be installed on the phone&#8211;no way to send up updated binaries. So all the code is there ready to go but a little key is needed to unlock it. On the desktop this type of app is derisively (and deservedly) called <i>crippleware</i>. </p>
<p>In other words, as of today, what Apple is allowing app developers to ship is <i>crippleware</i> for your iPhone. I could be wrong on this but this clearly falls under the category of <a href="http://en.wikipedia.org/wiki/Unintended_consequence" target="_blank">Unintended Consequences</a>.</p>
<h3>The Ugly</h3>
<p><img src="http://ramin.firoozye.com/i/theugly.jpg" width="110" height="119" alt="" /></p>
<p>The user plays with the eval app for 30 days (or so) then purchases the unlock token via In App Purchasing. The token is saved on the system so from now on the app launches in its unlocked state. But what form is that token going to take and where is it going to be stored? Given the current sandboxed architecture of the iPhone app, There are two places where an application can actually write data:</p>
<ol>
<li>The filesystem under the application&#8217;s <i>Documents</i> folder. This can be a text file, a user preference plist, a record in a SQLite database, or a CoreData store.</li>
<li>In the keychain as a secure key/value data item.</li>
</ol>
<p>Apple has intentionally stayed out of the business of what shape or form this add-on functionality or unlocking feature should take. It&#8217;s up to the individual developers to decide but odds are it will be one of these two methods. </p>
<p>Trouble is both these methods will actually make it <i>easier</i> for apps to get pirated.</p>
<p>On a regular iPhone no app can cross the sandbox line and access another app&#8217;s private data. But on a jailbroken phone no such lines exist. So a few minutes after the app is installed on a jailbroken phone, that special token can be easily extracted and plastered all over the internet. Now you don&#8217;t even need to resort to apps like <a href="http://www.electronicpulp.net/2009/02/02/download-crackulous-and-crack-any-iphone-app-with-one-click-any-time/" target="_blank">Crackulous</a> to get your free fully-functional apps.</p>
<p>The solution is for each individual app developer to implement tighter security around the application, by implementing secure unlock tokens, perhaps even tied to a specific handset so even if they&#8217;re removed from a single phone they won&#8217;t be usable on any other phone. But that involves knowing quite a bit about the pros and cons of cryptography and your typical iPhone app developer is not going to have the time and patience to implement anything like that. </p>
<p>So they&#8217;ll take the quick and expedient way&#8211;they&#8217;ll offer crippleware and save the token into a user preference plist or keychain &#8212; and hope and pray nobody bothers looking there. Or they&#8217;ll sign up with outfits like <a href="http://urbanairship.com/" target="_blank">Urban Airship</a>, <a href="http://www.ilime.com" target="_blank">iLime</a>, or <a href="http://www.push.io" target="_blank">Push.IO</a> to take care of it for them for a fee.</p>
<p>But this doesn&#8217;t mask the fact that with no Apple-defined standard, it&#8217;s going to be a free-for-all.</p>
<p>The final bit of ugliness heading our way has to do with user reviews. In the early days of the AppStore anyone could leave reviews &#8212; regardless of whether they had bought the app or not. This rendered the system useless since most of the initial write-ups consisted of, um, <i>price-resistant</i> customers (endearingly called <i>freetards</i> by developers) complaining about the price, no matter how low. It didn&#8217;t take long for Apple to clamp down on this by requiring only those who had actually purchased an app to review them. This substantially cut down on the noise and helped keep Appstore reviews an important part of the consumer decision-making process. </p>
<p>But now with the advent of free evaluation apps we&#8217;re going to go back to the halcyon days of price-gripes, where a user will download the free version of the app, take a look at the price for obtaining the unlock token and submit a 1-star review, complaining about, yes you got it, the price of the app. The current AppStore filter will not work since they&#8217;ve officially downloaded the app and technically count as having <i>purchased</i> the app.</p>
<p>One step forward. Two steps back. In other words, it&#8217;s going to get <i>ugly</i>. Again.</p>
<h3>Unless&#8230;</h3>
<p>You&#8217;ve been so patient. I won&#8217;t keep you waiting. Here are a few steps Apple needs to take for this eval system to work:</p>
<ol>
<li><b>Offer a simple, official API for supporting both <em>Time-limited</em> and <em>Degraded</em> evaluations</b>. This means associating some application <i>metadata</i> with each app when it&#8217;s installed and forcing <em>Springboard</em> (the iPhone application launcher) to honor these settings before running the application. Springboard already does this when it installs an app&#8211;that&#8217;s how the App Store application updated can tell what version you&#8217;re running vs. what&#8217;s on the store.
<p>To prevent the remove-reinstall workaround, there has to be a way to save some information that lives outside the sandbox and survives application removal. This can be on the phone or on a server. Again, Apple already does both these things. It saves data to the system keychain and it keeps track of what apps you&#8217;ve &#8220;bought&#8221; on the AppStore (so when you go reinstall, it knows not to charge you twice). So it would be easy for them to let the app-developer mark the application as eval, whether Time-limited (and or how long) or Degraded.</p>
<p>I would even argue that <i>anything</i> having to do with application installation or unlocking belongs in the AppStore/OS domain, not left to individual applications. Anything having to do with In App purchasing of extra grenade-launchers, leave it up to the app.</p>
</li>
<li>Far, far more importantly (and I can&#8217;t emphasize this enough) Apple should <b>provide a simple API for an application to verify that the current user has purchased the app</b>. This will do far more to cut down on application piracy than allowing free evals. The app developer can periodically and at random times invoke this API and ask two simple questions: <i>Has the current user bought this app?</i> and <i>When?</i>.
<p>A developer would be wise to sprinkle calls to the API throughout the app. Yes, the application binary can be patched and the API call removed, but that&#8217;s a higher wall for your typical cracker to climb than <a href="http://thwart-ipa-cracks.blogspot.com/2008/11/detection.html" target="_blank">simply modifying a single entry in a text file</a>.</li>
<p> In the absence of a network connection, the default would be to let the application run a limited number of runs (until the user gets back to the network).</p>
<p>But what about the <i>When?</i> question? The answer would be a timestamp indicating when the user paid for the app. That piece of information is important to app-developers who currently have multiple free/pay versions of applications on the appstore (or who want to continue using that model). For these folks to move from a free/pro model to an eval/buy model means that their end users would have to obtain a new version of their application. There would have to be a way to tell whether the current user paid for the full version of the app during the pre-eval period and not force them to go through the whole purchase cycle again.</p>
<p>I should also emphasize that with this API the application will never have to be given access to any private user-credentials. Something like the following added to UIApplication will work wonders to ward off app piracy:</p>
<pre>
+ BOOL isAppPurchased;
+ NSDate* dateOfPurchase;
</pre>
<p></p>
<li>The last thing Apple could to do help eval/buy apps a success is implement a policy where only users who had purchased the unlock token would be allowed to post comment and reviews on the AppStore. Let&#8217;s maintain the status quo instead of taking a step back. The problem, however, is given the totally unstructured way the current In App Purchase model is implemented, there is no viable way in which an <em>extra rocket-launcher</em> token can be distinguished from an <em>unlock application</em> token.<br />
<br />
I would argue that unlocking eval applications, verifying proper ownership, and restricting access to the review system should be the responsibility of the entities that control application installation and launching&#8211;i.e., the operating system and iTunes&#8211;instead of individual developers. But in lieu of that, Apple should give developer tools to properly implement an evaluation system that welcomes legitimate users and cuts back on potential abuse.
</li>
</ol>
<p><strong>In summary:</strong> The In App Purchase mechanism is a great system for supporting application add-ons. But it&#8217;s wholly unsuited for supporting eval applications and does nothing to fight application piracy. Having properly implemented eval apps is important to the future of this ecosystem. Apple shouldn&#8217;t leave it up to individual developers to figure out how to get there. It should be part of the core functionality of the operating system.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/10/16/eval-iphone-apps-the-good-the-bad-and-the-ugly/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Problems with Push</title>
		<link>http://ramin.firoozye.com/2009/09/30/problems-with-push/</link>
		<comments>http://ramin.firoozye.com/2009/09/30/problems-with-push/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 06:51:22 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[push]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=215</guid>
		<description><![CDATA[
I agree with most everything Karl Adam says about the limitations of the Apple Push Notification Service, especially the problem with its failure to stack notifications so they&#8217;re not missed. 
I posted a bug report a while back (rdar://7054632) offering a simple solution to get around this particular problem: save each incoming push payload into [...]]]></description>
			<content:encoded><![CDATA[<div style="text-align:center;"><img src="http://ramin.firoozye.com/wp-content/uploads/2009/09/pushsad.png" alt="pushsad.png" border="0" width="195" height="212" /></div>
<p>I agree with most everything <a href="http://matrixPointer.com/karl/posts/push-notifications-no-cigar" target="_blank">Karl Adam says</a> about the limitations of the Apple Push Notification Service, especially the problem with its failure to stack notifications so they&#8217;re not missed. </p>
<p>I posted a bug report a while back (<a href="rdar://7054632" target="_blank">rdar://7054632</a>) offering a simple solution to get around this particular problem: save each incoming push payload into Messages.app as a separate entry. That way if I get a push and don&#8217;t have time to get to it I can ignore it and come back to Messages later on and retrieve it and all received Push messages are kept until I choose to get rid of them.</p>
<p>The entry could be in the form of a special URL link that shows the alert message, but when clicked generates the same JSON payload format as a regular push event and invokes the app in the same manner so no extra coding would be needed (OK, maybe just a little bit of code on the server to check against processing duplicate requests). It would take care of a lot of problems with push usability.</p>
<p>An even more pressing issue I have with Push is if you are on a WiFi network behind a bunch of firewalls and more than one NAT server. This happens often in corporations or in homes with multiple routers acting as range-extenders. In these cases pushes fail to reach you &#8212; until you get back to a 3G network.</p>
<p>For some people Push is doubling as a remote event timer (since Apple won&#8217;t let us access the phone&#8217;s alarm database or submit local cron tasks). This makes it really hard  to issue reliable time-based alerts. </p>
<p>If Apple would just open up true background tasks and/or timed alerts and let the user decide whether they trust an app to let it access those services (much like location-based or push services) a lot of these hassles would go away.</p>
<p>Also, a European friend brought up that whereas SMS is included in most phone plans, push incurs data usage charges. Could be a hassle if you&#8217;re traveling and continue getting pushes.</p>
<p>Over all, I&#8217;d say push on the iPhone is a work in progress. As much as I&#8217;m intrigued and excited by its potential, I&#8217;m frustrated by its current implementation and limitations.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/09/30/problems-with-push/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Semi-Modal (Transparent) Dialogs on the iPhone</title>
		<link>http://ramin.firoozye.com/2009/09/29/semi-modal-transparent-dialogs-on-the-iphone/</link>
		<comments>http://ramin.firoozye.com/2009/09/29/semi-modal-transparent-dialogs-on-the-iphone/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 00:50:26 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[iphone]]></category>
		<category><![CDATA[objective-c]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=190</guid>
		<description><![CDATA[Popping up a modal dialog on the iPhone is a fairly straightforward process:


	modalDialogViewController *modalController = [[modalDialogViewController alloc]
            initWithNibName:@&#34;modalDialogView&#34; bundle:nil];
	[self presentModalViewController:modalController animated:YES];
	[modalController release];

Dismissing it then is a simple matter of the modalController invoking:


	[self dismissModalViewControllerAnimated:YES];

But what if you want to show only half a page&#8217;s worth [...]]]></description>
			<content:encoded><![CDATA[<p>Popping up a modal dialog on the iPhone is a fairly straightforward process:</p>
<pre class="brush: cpp">

	modalDialogViewController *modalController = [[modalDialogViewController alloc]
            initWithNibName:@&quot;modalDialogView&quot; bundle:nil];
	[self presentModalViewController:modalController animated:YES];
	[modalController release];
</pre>
<p>Dismissing it then is a simple matter of the <code>modalController</code> invoking:</p>
<pre class="brush: cpp">

	[self dismissModalViewControllerAnimated:YES];
</pre>
<p>But what if you want to show only half a page&#8217;s worth or maybe you need the underlying view to continue being available for user viewing or interaction. Or maybe you want to show a pop-up toolbar where users are asked to choose something before continuing. You might think <em>&#8220;Aha! I&#8217;ll just have my modal dialog view be half as tall and make the background transparent.&#8221;</em></p>
<p>Go ahead, give it a try. We&#8217;ll wait&#8230; (<em>* &#8230; the girl from Ipanema goes walking &#8230; *</em>)</p>
<p>So now you know that the standard modal dialog can only be full-screen and maintains a solid black background. What&#8217;s more you can&#8217;t interact with what&#8217;s behind it because, you know <em>it&#8217;s modal</em> &#8212; and <em>modal</em> means users shouldn&#8217;t be able to do anything else until they&#8217;re done with the front-most task (unless you&#8217;re the search box in the Contacts app in which case apparently it&#8217;s OK to be kindasortamodal).</p>
<p>So what we&#8217;re going to do is have a view that can be modal but takes only part of the top view, the space above it remaining visible. What&#8217;s more, you can choose to have it so tapping on the background view hides the modal view, or even go full-bore and let the background remain responsive to user input. This technically makes the view <em>semi-modal</em> so let&#8217;s ignore the sirens and the UI Police banging on the door and go with that.</p>
<p>The first thing you need is a view that has something interactive on it. The easiest way to build one is in interface builder, so go ahead and make yourself one. For the sake of expedience make it only a fraction of the screen. Here&#8217;s an example of a half-height view along with some user controls. The background is set to fully transparent. The view is connected to a <code>UIViewController</code> that reacts to user input:</p>
<div style="text-align:center;"><img src="http://ramin.firoozye.com/wp-content/uploads/2009/09/modalib1.png" alt="modalib.png" border="0" width="344" height="526" /></div>
<p>In this case, the view is the same height as the whole screen because we want the upper portion to be see-through <em>but not react to user input</em>. If we wanted it to be truly interactive, we could make the view height be as tall as the actual content (i.e. half-screen) but that would make it a bit strange for the user because it would be hard to tell apart the actual content from the modal view. But hey, it&#8217;s your app. You can do what you want. </p>
<p>Another option is to set the background of this view black and partially transparent. That would look cool and show a nice smoky cover while we&#8217;re in modal mode&#8230; unless you&#8217;re mucking with color (like we are in this example) in which case it&#8217;s best to leave it fully transparent.</p>
<p>Next throw the following code in the parent <code>UIViewController</code>. Load up the <code>UIViewcontroller/UIView</code> you just created and pass the view to this routine instead of calling the standard <code>presentModalViewController</code> method (substitute your application delegate for <code>MyAppDelegate</code>):</p>
<pre class="brush: cpp">

    // Use this to show the modal view (pops-up from the bottom)`
    - (void) showModal:(UIView*) modalView
    {
    	UIWindow* mainWindow = (((MyAppDelegate*) [UIApplication sharedApplication].delegate).window);

    	CGPoint	middleCenter = modalView.center;
    	CGSize offSize = [UIScreen mainScreen].bounds.size;
    	CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
    	modalView.center = offScreenCenter; // we start off-screen
    	[mainWindow addSubview:modalView];

    	// Show it with a transition effect
    	[UIView beginAnimations:nil context:nil];
    	[UIView setAnimationDuration:0.7]; // animation duration in seconds
    	modalView.center = middleCenter;
    	[UIView commitAnimations];
    }
</pre>
<p>What this does is add your view as a top-level above the main window, effectively rendering it modal. It also uses Core Animation to move the window from offscreen bottom up until it&#8217;s fully shown. You should adjust the timing to suit your view&#8217;s actual height. I&#8217;ve found that the taller the semi-modal view, the more time you should give it to become fully visible.</p>
<p>Now let&#8217;s go through the hiding action. Note that we use the animation completion handler to do the actual removing of the item from the parent view and cleaning up. We also use the <code>context</code> parameter of the animation call (which was thoughtfully provided for exactly this sort of thing) to keep track of what view to clean up afterward:</p>
<pre class="brush: cpp">

    // Use this to slide the semi-modal view back down.
    - (void) hideModal:(UIView*) modalView
    {
    	CGSize offSize = [UIScreen mainScreen].bounds.size;
    	CGPoint offScreenCenter = CGPointMake(offSize.width / 2.0, offSize.height * 1.5);
    	[UIView beginAnimations:nil context:modalView];
    	[UIView setAnimationDuration:0.7];
    	[UIView setAnimationDelegate:self];
    	[UIView setAnimationDidStopSelector:@selector(hideModalEnded:finished:context:)];
    	modalView.center = offScreenCenter;
    	[UIView commitAnimations];
    }

    - (void) hideModalEnded:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
    {
     UIView* modalView = (UIView *)context;
    	[modalView removeFromSuperview];
    	[modalView release];
    }
</pre>
<p>What I&#8217;m not showing you here is the way to trigger the show/hide action. That&#8217;s entirely up to you. In standard iPhone modal dialogs this is often a button in the toolbar or navigation bar. In the case of the semi-modal dialog, however, you have even more flexibility. Basically it comes down to the show/hide elements being:</p>
<ul>
<li><strong>Explicit</strong>: Provide an <em>Accept</em> or <em>Cancel</em> button on your view.</li>
<p></p>
<li><strong>Implicit</strong>: You can simulate an action toolbar that shows and hides this way. Put a row of buttons on the view and wire it so tapping each one invokes <code>hideModal</code> before going on to the actual action.</li>
<p></p>
<li><strong>Other</strong>: Tapping anywhere else on the screen dismisses the dialog. You can do this by placing a full-screen sized view (or custom transparent button) behind your modal dialog and wiring it so it a tap-down action dismisses the dialog . For best results, try making this full-screen view black and semi-transparent (e.g. opacity=0.2). This way the user&#8217;s main view darkens so they get a sense your modal dialog is in focus but they still get to see what&#8217;s behind.</li>
</ul>
<p>Here&#8217;s a movie of the above semi-modal view in action. It lets the user select a color then confirm or cancel the action. The modal view in this case also has interactive controls on it. As the user changes color the background image changes in real-time so they can visualize what the end-result will be like. Once they&#8217;re done they can tap the checkbox or X/cancel buttons to make the modal go away.</p>
<div style="text-align:center;"><a href="http://ramin.firoozye.com/wp-content/uploads/2009/09/modalmovie1.mov" title="modalmovie.mov"><img src="http://ramin.firoozye.com/wp-content/uploads/2009/09/modalmovie.png" alt="modalmovie.png" border="0" width="161" height="230" />
<p />Play movie</a>
</div>
<p>The semi-modal dialog is a handy UI interaction component but it&#8217;s important to think about how to dismiss the dialog and what to allow in the rest of the visible region on the main window to avoid confusing the user. Also note that there are no restrictions on the shape or size of the overlay view as long as the background color is set to <code>[UIColor clearColor]</code>. You can use the same method for irregularly shaped pop-ups. </p>
<p>Go nuts and have fun.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/09/29/semi-modal-transparent-dialogs-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
<enclosure url="http://ramin.firoozye.com/wp-content/uploads/2009/09/modalmovie1.mov" length="175241" type="video/quicktime" />
<enclosure url="http://ramin.firoozye.com/wp-content/uploads/2009/09/modalmovie1.mov" length="175241" type="video/quicktime" />
		</item>
		<item>
		<title>Push Notification and Python (Django)</title>
		<link>http://ramin.firoozye.com/2009/09/09/push-notification-and-python-django/</link>
		<comments>http://ramin.firoozye.com/2009/09/09/push-notification-and-python-django/#comments</comments>
		<pubDate>Wed, 09 Sep 2009 09:36:25 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Tech]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[push]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=128</guid>
		<description><![CDATA[I&#8217;ve been trying to get the iPhone Push notification services introduced in OS 3.0 working with Python (specifically, Django). It took a while but I figured I&#8217;d post my notes so it&#8217;ll spare someone the suffering I had to go through.
Other attempts at this (apns-python-wrapper (aka APNSWrapper) and Lee Packham&#8217;s code) both use the standard [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been trying to get the iPhone Push notification services introduced in OS 3.0 working with Python (specifically, <a href="http://www.djangoproject.com/" target="_blank">Django</a>). It took a while but I figured I&#8217;d post my notes so it&#8217;ll spare someone the suffering I had to go through.</p>
<p>Other attempts at this (<a href="http://code.google.com/p/apns-python-wrapper/" target="_blank">apns-python-wrapper</a> (aka <code>APNSWrapper</code>) and <a href="http://leenux.org.uk/2009/07/14/push-on-the-iphone/" target="_blank">Lee Packham&#8217;s</a> code) both use the standard <code>ssl</code> libraries which I couldn&#8217;t get to work under Snow Leopard and Python 2.6.</p>
<p>I eventually got it going with Django and <a href="http://sourceforge.net/projects/pyopenssl/" target="_blank">pyOpenSSL</a> libraries. The easiest way is to get the prebuilt <a href="http://www.egenix.com/products/python/pyOpenSSL/" target="_blank">pyOpenSSL binaries from eGenix</a>. If the test server is running on Snow Leopard the <em>Python 2.6 UCS2</em> version seems to work best.</p>
<p>The thing about <code>pyOpenSSL</code> is that it expects the certificate and private key to be in separate <code>.PEM</code> files so you have to export each one from <code>KeyChain Access</code> in <code>.P12</code> format then convert them to <code>.PEM</code> from the command line. For the development key it&#8217;s easier to specify the password during export then strip it out on the command line. In production you may not want to do that.</p>
<pre class="brush: bash">
   % openssl pkcs12 -clcerts -nokeys -out devcert.pem -in devcert.p12
   % openssl pkcs12 -nocerts -out devkey.pem -in devkeypw.p12
   % openssl rsa -in devkeypw.pem -out devkey.pem
</pre>
<p />
<p />
Now copy <code>devcert.pem</code> and <code>devkey.pem</code> (with no password) into the server directory.</p>
<p>The following bit of code is in a file called <code>PushSender.py</code> and does the actual talking to the push server (I heavily edited out project-specific bits and standard exception and error-handling stuff. Hopefully didn&#8217;t bork it too badly <img src='http://ramin.firoozye.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Also, in this example the actual communication runs in a thread. In some cases it might make more sense to run it as a main routine:</p>
<pre class="brush: python">
import os, sys
import struct, binascii, ssl, datetime
import threading
import simplejson as json
from socket import socket
from OpenSSL import SSL

class PushSender(threading.Thread):
def __init__(self, sandbox, token, message, badge, sound):
	super(PushSender, self).__init__()
    		self.token = token
    		self.sandbox = sandbox
    		self.message = message
    		self.badge = badge
    		self.sound = sound
    		self.ctx = SSL.Context(SSL.SSLv3_METHOD)
    		if sandbox:
    			self.apnHost = &quot;gateway.sandbox.push.apple.com&quot;
    			self.ctx.use_certificate_file(os.path.join(PROJECT_ROOT, &quot;devcert.pem&quot;))
    			self.ctx.use_privatekey_file(os.path.join(PROJECT_ROOT, &quot;devkey.pem&quot;))
    		else:
    			self.apnHost = &quot;gateway.push.apple.com&quot;
    			self.ctx.use_certificate_file(os.path.join(PROJECT_ROOT, &quot;prodcert.pem&quot;))
    			self.ctx.use_privatekey_file(os.path.join(PROJECT_ROOT, &quot;prodcert.pem&quot;))

    	def run(self):
    		payload = {}
    		aps = {}
    		if (self.message):
    			aps[&quot;alert&quot;] = str(self.message)
    		if (self.badge):
    			aps[&quot;badge&quot;] = self.badge
    		if (self.sound):
    			aps[&quot;sound&quot;] = str(self.sound)

    		payload[&quot;aps&quot;] = aps

    		token = binascii.unhexlify(self.token)
    		payloadstr = json.dumps(payload, separators=(&#039;,&#039;,&#039;:&#039;))
    		payloadLen = len(payloadstr)
    		fmt = &quot;!cH32sH%ds&quot; % payloadLen
    		command = &#039;\x00&#039;
    		msg = struct.pack(fmt, command, 32, token, payloadLen, payloadstr)
    		sock = socket()
    		s = SSL.Connection(self.ctx, sock)
    		s.connect((self.apnHost, 2195))
    		s.send(msg)
    		s.shutdown()
    		s.close()
</pre>
<p>[ <a href="http://www.firoozye.com/download/PushSender.txt" target="_blank">PushSender source</a> ]</p>
<p>To invoke it in a thread (the first param is <em>True</em> for sandbox and <em>False</em> for production server) from the main routine:</p>
<pre class="brush: python">
	from PushSender import PushSender
	...
	pushsender = PushSender(True, token, pushmessage, pushbadge, pushsound)
	pushsender.start()
</pre>
<p />
<p />
On the phone the token returned by the <code>didRegisterForRemoteNotificationsWithDeviceToken</code> method is in the form <code>&lt;xxxxxxxx xxxxxxxx ...&gt;</code>. To pass it along to the server you have to strip out the <code>&lt;&gt;</code> and spaces. The <code>unhexlify</code> method then converts this string into a 32-byte hex binary value. The easiest way to strip out the extraneous stuff is to just do it on the client-side:</p>
<pre class="brush: cpp">
    NSString *deviceToken = [[[[tokenString description]
			stringByReplacingOccurrencesOfString:@&quot;&lt; &quot; withString:@&quot;&quot;]
			stringByReplacingOccurrencesOfString:@&quot;&gt;&quot; withString:@&quot;&quot;]
			stringByReplacingOccurrencesOfString: @&quot; &quot; withString: @&quot;&quot;];
</pre>
<p />
<p />
One last thing: at least with the sandbox if the phone is running on WiFi sometimes push notices don&#8217;t come through. This may be due to router NAT or firewall configuration issues. One way to check is to go into XCode Organizer while the phone is tethered and run your app, then under the Organizer Console you can check for errors. To get around this you&#8217;ll want to turn off the WiFi on the phone and go with 3G. This usually makes push notices arrive as expected (and strangely enough the WiFi method goes back to working for a few minutes). </p>
<p>There&#8217;s more that needs to be done to make it production-ready but at least it&#8217;s good to know it&#8217;s doable:</p>
<div style="text-align:center;"><img src="http://ramin.firoozye.com/wp-content/uploads/2009/09/cp18s.png" alt="cp18.png" border="0" /></div>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/09/09/push-notification-and-python-django/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Debugging peer-to-peer and wifi apps on the iPhone</title>
		<link>http://ramin.firoozye.com/2009/06/18/debugging-peer-to-peer-and-wifi-apps-on-the-iphone/</link>
		<comments>http://ramin.firoozye.com/2009/06/18/debugging-peer-to-peer-and-wifi-apps-on-the-iphone/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 21:48:53 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=114</guid>
		<description><![CDATA[ 
If you&#8217;re developing an iPhone application that uses WiFi networking or the new Gaming Kit (Bluetooth) at some point you&#8217;ll want to test the code on two devices side-by-side. At this point you will realize that:
a) You can only run one instance of XCode on your machine at a time.
b) Debugging one device at [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://ramin.firoozye.com/i/wifi.jpg" width="119" height="53" alt="" /> <img src="http://ramin.firoozye.com/i/bluetooth.jpg" width="210" height="56" alt="" /></p>
<p>If you&#8217;re developing an iPhone application that uses WiFi networking or the new Gaming Kit (Bluetooth) at some point you&#8217;ll want to test the code on two devices side-by-side. At this point you will realize that:</p>
<p>a) You can only run one instance of XCode on your machine at a time.</p>
<p>b) Debugging one device at a time is a royal PITA.</p>
<p>c) Your only option is to beg, borrow, or steal another Mac then install all of XCode and your code onto it just so you can do some debugging.</p>
<p><img class="alignleft" src="http://ramin.firoozye.com/i/musicman.jpg" width="144" height="199" alt="" /></p>
<p>I&#8217;m here to tell you there&#8217;s a better way.</p>
<p>The solution is to use <a href="http://www.vmware.com/products/fusion/" target="_blank">VMWare Fusion</a> with Leopard or Snow Leopard <em>server</em> as a &#8220;guest OS.&#8221; (In VMWare-speak your regular machine is a <em>host OS</em> while each virtual OS instance running on it is a <em>guest OS</em>.)</p>
<p>The reason this works is because the latest version of VMWare allows you to run OS X Server as a guest OS <em>on top of another OS X host OS</em>. VMWare also allows you to assign specific USB devices to each VM instance so you can tell it that one iPhone/Touch belongs to the guest and the other to the host OS. Now I&#8217;ve only tried this with Snow Leopard Server so I&#8217;ll stick with that but VMWare says it can also install Leopard Server but I have&#8217;t tried that. Since Snow Leopard is still under NDA I&#8217;m not going to go into any specifics of the OS itself. Instead, I&#8217;ll show you how to set up VMWare so it can pull this off.</p>
<p>To start you&#8217;ll want the <a href="http://www.vmware.com/download/fusion/" target="_blank">latest VMWare version</a> (<strike>2.0.4</strike> 2.0.5 as of this writing). Earlier versions may not support OS X as a guest OS. To get access to the Snow Leopard releases you&#8217;ll need to be part of the <a href="http://developer.apple.com/mac/" target="_blank">Apple Mac Developer program</a>. You&#8217;ll want the <em>Server</em> release. During WWDC 2009 some people were reporting having trouble installing Snow Leopard under VMWare from a  disk image file so you might have to sacrifice a blank DVD and burn it to disc before installing it. </p>
<p>With the disc all you have to do is pop it in and it does the right thing. Or you can walk through and manually choose which versions you want to load.</p>
<p><img src="http://ramin.firoozye.com/i/vmwareinstall.jpg" width="396" height="299" alt="" /></p>
<p>Technically VMWare is only supposed to run Leopard/Snow Leopard Server which installs a lot of extra background services, etc. and needs a pretty hefty chunk of memory. If you Google around there are ways to patch the VMWare settings files to let it install <em>Client</em>. Far be it from me to suggest you do this, since it&#8217;s not certified and is not recommended for production use. All I&#8217;m saying is it might be less resource intensive and prevent your MacBook Pro from catching fire after the fans run on full-bore trying to cool down 100% loaded dual-core CPUs. But then again, YMMV.</p>
<p>So once you have VMWare and Leopard/Snow Leopard installed, you&#8217;ll want to install XCode (which comes on the OS install disk under &#8220;Extras,&#8221; or it can be downloaded separately from the Developer Connection website). Once that&#8217;s done you&#8217;ll also need the iPhone SDK. If you&#8217;re a member of the <a href="http://developer.apple.com/iphone/" target="_blank">iPhone Developer Program</a> (and really, who isn&#8217;t nowadays?) you&#8217;ll want to download and install the latest SDK (note that there are different downloads for Leopard and Snow Leopard).</p>
<p>Inside VMWare you&#8217;ll want to set up directory sharing. I won&#8217;t walk you through that here but if you have trouble getting the VMWare &#8220;folder-mapping&#8221; feature to work (like I did) one workaround is to turn on file-sharing in the host OS and mount the networked filesystem from the guest OS. If you do this, make sure you restrict access to only your own account on the shared volumes and turn it off for everyone else, otherwise all your pals at the coffee shop sitting on the WiFi and running Bonjour will have access to your source files.</p>
<p>Next you&#8217;ll want to end up with two separate projects, one for the host and the other for the guest OS. The reason for this is because each instance of XCode makes changes to the project settings each time you do a build. If you share the projects and load them from two XCode instances, you&#8217;ll end up with an endless litany of XCode warnings asking you if it should reload the project from disk. Save yourself a lot of headache. Just create separate projects but keep all your source and media files in the same shared folder. This way if you do actually make changes to the source code during debugging you only have to do it once from either side, otherwise it&#8217;s a nightmare keeping track of deltas.</p>
<p>(<em>Handy tip</em>: if you have dual monitors, install VMWare tools and  put the guest OS on the second monitor then have it go full-screen. It&#8217;s like having two actual systems in one.)</p>
<p>So now comes the fun part: plugging in the actual devices. Make sure you&#8217;re not running XCode or any other app that accesses the USB devices behind the scenes. If you have iTunes set up to auto-run and sync when a device is plugged in you either haven&#8217;t done much real iPhone device debugging or you have a much higher tolerance for Annoyingly Intrusive Software. I turn off all auto-sync, auto-run, auto-whatever features that iTunes throws in to make itself the consumer-friendly app that it is. But that convenience gets in the way of debugging, so do yourself a favor and turn it all off. Manual sync mode is your friend.</p>
<p>iTunes also installs an iTunesHelper app that runs in the background. I personally take that out too by going into System Preferences > Accounts<br />
then clicking on the &#8220;Login Items&#8221; tab button, finding &#8220;iTunesHelper&#8221; and hitting the &#8216;-&#8217; button (or delete) to take it out. The point is, if iTunes snags your USB port before VMWare gets to it you won&#8217;t be able to switch it over.</p>
<p>So now we have the two devices plugged in. Do NOT give in to temptation and start XCode just yet. In VMWare bring up the &#8220;Virtual Machine Library&#8221; which lists all your VM instances (if it&#8217;s not already showing, go under Windows > Virtual Machine Library). Select your Leopard/Snow Leopard instance then push the &#8220;Settings&#8221; button. </p>
<p><img src="http://ramin.firoozye.com/i/sl1.jpg" width="350" height="210" alt="" /></p>
<p>Now go into the USB devices section. Note that you can only make changes to the guest OS once it&#8217;s powered up and running. So if the guest OS isn&#8217;t already running, boot it up. You&#8217;ll be faced with a list of all the USB devices on your host machine, something like this:</p>
<p><img src="http://ramin.firoozye.com/i/sl2.jpg" width="362" height="282" alt="" /></p>
<p>Unfortunately VMWare doesn&#8217;t actually show the device names as assigned through iTunes so there&#8217;s no way to tell which device is which. If you have two iPhones plugged in they both show up as <em>Apple iPhone</em>. You can always test an iPhone against a 2G touch (the Touch shows up as <em>Apple iPod</em>). Then again, if both devices are running the same code it may not really matter.</p>
<p>Turn on the checkbox next to the device you want assigned to the guest OS. If it doesn&#8217;t stick then it&#8217;s likely you&#8217;ve got some other app locking up your USB ports. Go back and re-check (might have to do a clean reboot). I should note that this was the most frustrating part of the whole exercise. The trick that made it work for me was to make sure XCode is not running until AFTER you&#8217;ve done your USB port assignments.</p>
<p>Once it&#8217;s checked, *now* start up XCode on both sides. The host OS should be seeing one device and the guest OS the other. Verify by loading up the XCode Organizer and seeing that each device shows up with a little green dot next it. If you haven&#8217;t done it yet, you&#8217;ll want to tell the XCode Organizer that the devices are to be used for Development.</p>
<p><img class="alignleft" src="http://ramin.firoozye.com/i/organizer.jpg" width="184" height="247" alt="" /></p>
<p>Getting excited? Almost there. Now choose <em>iPhone Device</em> from your XCode Active SDK pop-up. </p>
<p><img src="http://ramin.firoozye.com/i/xcode-run.jpg" width="192" height="83" alt="" /></p>
<p>Ready to hit <em>Build and Run</em>?</p>
<p>Not so fast.</p>
<p><img class="alignleft" src="http://ramin.firoozye.com/i/sadclown.jpg" width="161" height="210" alt="" /></p>
<p>Your iPhone development certificate is only installed on your host OS. The guest OS is a whole other machine and it needs to be set up as if it was a brand new machine. Fortunately, it&#8217;s fairly straightforward to get the keys moved over.</p>
<p>Launch the <em>Keychain Access</em> application (in Applications > Utilities) on your host OS. If you followed the iPhone SDK instructions and created a provisioning profile for your application on the iTunes Connect site, you should have a private key certificate installed in your keychain. If you&#8217;re like me and have done this a number of times, you&#8217;ll have lots of similar looking keys floating around. The trick is to look for the <em>private</em> key with your name and a drop-down disclosure arrow next to it. Open those up and verify that they say <em>iPhone Developer</em> and/or <em>iPhone Distribution</em> next to them. If you&#8217;ve followed Apple guidelines you should have one for development and another for app-store or ad-hoc distribution.</p>
<p><img src="http://ramin.firoozye.com/i/keychain.jpg" width="309" height="236" alt="" /></p>
<p>While you&#8217;re there, it&#8217;s a good time to make sure the expiration date is in the future. I got bit once and boy, was it a pain to diagnose. Stuff that was working one minute magically stopped the next. So stay on top of your certificate expiration dates. If the date is pretty close or already gone by go back to iPhone developer site and follow instructions to regenerate new keys, then install them and come back when you&#8217;re done.</p>
<p>Command-select all the private certificates you want moved and export the lot of them (File menu > Export Items&#8230;) Make sure they go out as .p12 (Personal Information Exchange) files. You will be prompted for passwords. Pick something pithy but memorable and save the exported file to a shared folder you can get at from the guest OS. While you&#8217;re at it, you may also want to move over your app&#8217;s provisioning profiles just in case you need it later.</p>
<p>Back in the guest OS, double-click the exported certificate file, enter the password, and install it in your keychain. You&#8217;ll probably have to restart XCode so it picks up the changes. To verify that it worked, bring up the XCode project in the guest OS, do a <em>Get Info</em> on the target and make sure the Code Signing Identity is selected and is the same as the private key you just installed.</p>
<p>So NOW you&#8217;re ready to go. Select <em>iPhone Device</em> from the Active SDK on both sides, hit Build and Run, go grab a cup of coffee or an adult beverage, and wait until both instances come up side-by-side.</p>
<p>So, yay!</p>
<p><img class="alignleft" src="http://ramin.firoozye.com/i/yay.jpg" width="173" height="202" alt="" /></p>
<p>That wasn&#8217;t too bad, was it?</p>
<p>A few final thoughts: I ended up running Snow Leopard as both host and guest OS since I wanted to run XCode 3.2 with the latest goodies on both sides. You&#8217;ll definitely want separate project files if you want to run Leopard in host and Snow Leopard in guest OS. At this point it&#8217;s not clear if app-store submissions can be built using unreleased versions of XCode. So you might want to check on the developer forums before doing the crazy thing I did and upgrading everything everywhere to the new shiny version.</p>
<p>Also, there&#8217;s no reason this shouldn&#8217;t work for three or more devices (for group peer-to-peer or mass WiFi testing) but you&#8217;ll need a beefy Mac with a lot of CPU and memory. You&#8217;ll also be needing a USB hub (I ended up with this <a href="http://catalog.belkin.com/IWCatProductPage.process?Product_Id=367680" target="_blank">Belkin Ultra Mini</a> model based on advice from <a href="https://twitter.com/schwa" target="_blank">@schwa</a> on Twitter) if you run short on USB ports. All it takes is another VMWare instance and assigning the right device to the right OS instance.  Lather, rinse, repeat.</p>
<p>Happy debugging!</p>
<p><b>Update:</b> <i>Make sure you read VMWare update release notes.</i> In the latest release there are two known issues that directly impact this  way of using VMWare:</p>
<blockquote>
<ul>
<li><b>When being installed on a Mac running Mac OS X 10.6 (Snow Leopard), VMware Fusion does not install MacFUSE </b>
<p>MacFUSE might cause the installer to fail or become non responsive, so the VMware Fusion installation process does not install it by default on a Mac with OS X 10.6.</li>
<p />
<li><b>Selecting the Sleep option on a Mac OS X Server guest operating system causes it to stop responding </b><br />
The default setting for Mac OS X Server is for it to never sleep. However, if you change the setting or use <b>Apple > Sleep</b>, the virtual machine might stop responding.<br />
Workaround: Shut down the virtual machine and restart it, and make sure that in the <b>Energy Saver</b> window of <b>Apple > System Preferences</b>, the <b>Put the computer to sleep when it is inactive for:</b> slider is set to <b>Never</b>. Do not use <b>Apple > Sleep.</b>
</li>
</ul>
</blockquote>
<p>You&#8217;ll definitely want to turn off Sleep mode as soon as you&#8217;ve installed the guest OS and before you walk away from the system for an extended length of time otherwise you&#8217;ll have to hard-reboot the VM instance. I even turn off the screen-saver. If the system is idle for any length of time the host OS should be the one doing the sleeping and screen blanking.</p>
<p>The first issue is also easily solved. You can manually download and install <a href="http://code.google.com/p/macfuse/" target="_blank">MacFUSE</a>. It allows you to use not only third-party file systems on top of MacOS, but file systems on local disk, across the network etc. There are some issues with folder sharing across guest/host applications that clean install of MacFUSE might clear up.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/06/18/debugging-peer-to-peer-and-wifi-apps-on-the-iphone/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>On Tweaking and Sucking</title>
		<link>http://ramin.firoozye.com/2009/05/25/on-tweaking-and-sucking/</link>
		<comments>http://ramin.firoozye.com/2009/05/25/on-tweaking-and-sucking/#comments</comments>
		<pubDate>Mon, 25 May 2009 19:01:49 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Fun]]></category>
		<category><![CDATA[quotes]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=110</guid>
		<description><![CDATA[I feel like things as they are have about as much awesomeness as they&#8217;re capable of having, and you can&#8217;t imbue awesomeness into something that actually sucks. And in its way, something that sucks full-bore sucking at me is a kind of honorable experience&#8211;it&#8217;s an honorable exchange.
Steve Albini &#8212; indie music producer interviewed on public [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>I feel like things as they are have about as much awesomeness as they&#8217;re capable of having, and you can&#8217;t imbue awesomeness into something that actually sucks. And in its way, something that sucks full-bore sucking at me is a kind of honorable experience&#8211;it&#8217;s an honorable exchange.</p></blockquote>
<p><a href="http://en.wikipedia.org/wiki/Steve_Albini" target="_blank">Steve Albini</a> &#8212; indie music producer interviewed on public radio&#8217;s <a href="http://www.maximumfun.org/blog/2007/12/podcast-live-in-chicago-steve-albini.html" target="_blank">The Sound of Young America</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/05/25/on-tweaking-and-sucking/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>WWDC 2009 Predictions</title>
		<link>http://ramin.firoozye.com/2009/03/26/wwdc-2009-predictions/</link>
		<comments>http://ramin.firoozye.com/2009/03/26/wwdc-2009-predictions/#comments</comments>
		<pubDate>Thu, 26 Mar 2009 18:31:38 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Tech]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[wwdc]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=108</guid>
		<description><![CDATA[Word came today that Apple&#8217;s WorldWide Developer Conference is going to be running from June 8-12 2009 in San Francisco.
Since Apple&#8217;s no longer going to be participating in MacWorld this is one of the few public conferences where Apple and its partners can make public product announcements. So now&#8217;s a good time to start floating [...]]]></description>
			<content:encoded><![CDATA[<p>Word came today that Apple&#8217;s <a href="http://developer.apple.com/wwdc/" target="_blank">WorldWide Developer Conference</a> is going to be running from June 8-12 2009 in San Francisco.</p>
<p>Since Apple&#8217;s no longer going to be participating in MacWorld this is one of the few public conferences where Apple and its partners can make public product announcements. So now&#8217;s a good time to start floating <strike>outlandish rumors</strike><br />
predictions as to what&#8217;s going to be announced.</p>
<p>Since Apple already announced its intention to release iPhone 3.0 software around that time, a lot of products will be taking advantage of those features. One of them was access to the external USB port. The <a href="http://www.engadget.com/2009/03/17/live-from-apples-iphone-os-3-0-preview-event/" target="_blank">announcement demo</a> featured a heart-monitor. My prediction is it will be totally upstaged by one of these:</p>
<p><img src="http://ramin.firoozye.com/i/iPhoneCoffeeWarmer.jpg" width="413" height="356" alt="" /></p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/03/26/wwdc-2009-predictions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Eval applications on the iPhone AppStore</title>
		<link>http://ramin.firoozye.com/2009/03/19/eval-applications-on-the-iphone-appstore/</link>
		<comments>http://ramin.firoozye.com/2009/03/19/eval-applications-on-the-iphone-appstore/#comments</comments>
		<pubDate>Thu, 19 Mar 2009 07:09:05 +0000</pubDate>
		<dc:creator>ramin</dc:creator>
				<category><![CDATA[iphone]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[appstore]]></category>

		<guid isPermaLink="false">http://ramin.firoozye.com/?p=104</guid>
		<description><![CDATA[
One of the loudest complaints about the iPhone AppStore has been the lack of support for eval or demo applications. In the desktop world users can often download an application and use it for a period of time before deciding whether it&#8217;s worth paying for. But in the iPhone AppStore universe (where all transactions occur) [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://ramin.firoozye.com/i/30dayeval.jpg" width="119" height="100" alt="" /></p>
<p>One of the loudest complaints about the iPhone AppStore has been the lack of support for <em>eval</em> or <em>demo</em> applications. In the desktop world users can often download an application and use it for a period of time before deciding whether it&#8217;s worth paying for. But in the iPhone AppStore universe (where all transactions occur) there is no such support. Developers are then faced with the option of offering a <em>lite</em> version for free (or inexpensively) and a <em>full</em> version of their apps. The problem is that this still doesn&#8217;t allow the end-user to test out the full app and then choose to buy it if it fits their needs. And switching from a free to a full app involves installing an entirely  independent application. </p>
<p>What we really need is a way to <i>upgrade</i> an eval app to the full version once the user decides the app is worth paying for.</p>
<p>Yesterday Apple publicly announced the developer release of <a href="http://www.apple.com/iphone/preview-iphone-os/" target="_blank">iPhone 3.0</a> software (it won&#8217;t be publicly released until this Summer). To the dismay of many developers, there was &#8212; once again &#8212; no mention of support for <em>eval</em> applications among the 100 new features and &#8220;1000 new APIs.&#8221; So again, we are left without the option of letting users download an app, take it for a test run and then pay for it.</p>
<p>Or are we?</p>
<p>One of the features announced publicly was support for <strong>In App Purchases</strong>. This was presented as a way for users to obtain add-on levels or objects directly within games. The transaction (or more precisely, <em>micro-transaction</em>) still goes through the AppStore and gets charged to the same account. Despite <a href="http://i.gizmodo.com/5172350/why-iphone-in+app-transactions-could-be-a-disaster" target="_blank">public detractions</a> I belive this is a Good Thing &#8212; especially since the  feature can be used to <b>legitimately support eval applications</b>, even if the AppStore doesn&#8217;t officially support it yet.</p>
<p>Here&#8217;s how:</p>
<ul>
<li>Developer offers application <em>for free</em> on the app-store. This is a fully functional version (i.e. not <i>lite</i> or <i>crippleware</i>).</li>
<li>User downloads and runs the application and is informed that the application is in <em>eval</em> mode and will stop working after a period of time.</li>
<li>After the eval period  (say, 1-4 weeks) the application puts up a notice indicating the eval period has expired. It can either stop working or drop into a degraded mode.</li>
<li>At this point the user is given the option of performing an <em>In App purchase</em> of the full application.</li>
<li>If user accepts, the application contacts the AppStore and purchases the add-on &#8212; <i>which would be priced at what the full-price of the App would otherwise be</i>. Once completed, the app downloads an <i>add-on key</i> indicating the app has been purchased.</li>
<li>The presence of add-on indicates that the full app has been purchased and the timeout is taken out. All the application has to do each time it is launched is to look for the presence of this add-on.</li>
<li>Everyone&#8217;s happy.</li>
</ul>
<p>There&#8217;s a key assumption here &#8212; that the AppStore keeps track of already purchased <em>In App</em> purchases the same way it does with full applications today. In other words, if the user tries to re-download an In App purchase that they&#8217;ve already purchased with the same iTunes account, they shouldn&#8217;t be charged twice. If a user deletes the app or moves to a new phone, all they have to do is download the free version of the app, perform another In App purchase (for free this time) and off they go.</p>
<p>However, if this assumption is not true and In App purchases are tracked separately than full applications (or the application itself is responsible for keeping track of those transactions) then the developer will have to implement a way to track In App purchases that works across multiple app installs &#8212; most likely a simple web-server to keep track of eval vs. purchased apps. Let&#8217;s hope it doesn&#8217;t come to that (the documentation on the Store Kit is not out as of this writing and even if it was, developers under NDA won&#8217;t be able to talk about it publicly until the public  release of the 3.0 software).</p>
<p>There are some other issues that need to be hashed out, mainly what happens if unscrupulous third-parties find out what this add-on looks like and make it available for free download? The iPhone application sandbox makes it a non-issue since only the application itself is allowed to write to its Documents directory or modify its user settings &#8212; unless the phone has been jailbroken, in which case the concerned developer may want to support more complex security (like cryptographic  signing) for the add-on. Given that the <a href="http://www.google.com/search?q=Decrypting+AppStore+Applications&#038;ie=utf-8&#038;oe=utf-8" target="_blank">AppStore DRM appears to be compromised</a> using this technique does not significantly increase the risk of software piracy.</p>
<p>Another potential issue is the user who downloads the fully functional eval version, uses it for the full eval period, then deletes it, re-download and installs it so they can get another free eval period. If this is an area of concern, it can be handled through a simple web-service that keeps track of how many times the same user has installed an app. Personally, I don&#8217;t think it&#8217;s worth the hassle given that deleting an app also gets rid of all user-generated data. But that&#8217;s me.</p>
<p>Note also that when I&#8217;m talking about <em>downlaoding</em> something, I don&#8217;t mean literally downloading a chunk of code, but some sort of <em>token</em> that takes away the eval time limit. The whole operation can be performed very quickly once the In App transaction is completed.</p>
<p>I firmly believe having support for eval apps is critical for medium to high-priced applications to flourish on the AppStore. A user will hesitate to fork out a high price for a full-featured app without having the option to kick the tires beforehand. This method can easily solve the problem and let developers do eval apps as soon as the 3.0 software is officially released.</p>
<p><b>Update</b>: Apple has since announced that free apps <em>can not</em> use StoreKit. This is to avoid a potential bait-and-switch situation where the consumer downloads what they think is a free app and then get hit with a fee. However, I think it&#8217;s a misguided policy. A developer who does that will quickly get down-reviewed (if they even make it out of the app-review chute). A more likely scenario would be to allow users to use an app for a limited period of time, but give them the option to unlock the app for continued use.</p>
<p>Another more fundamental issue, however, is whether app developers even <i>want</i> an eval feature. I&#8217;ve heard from several Android developers that the Android store return policy has severely impacted sales of their apps. Their argument is that returns should be based on faulty apps, not because someone found their game too hard. Presumably, enabling eval apps will cut down on a lot of impulse-then-discard purchases that go on today.</p>
<p>Certainly a topic worthy of further discussion.</p>
]]></content:encoded>
			<wfw:commentRss>http://ramin.firoozye.com/2009/03/19/eval-applications-on-the-iphone-appstore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
