Adam Howitt's Blog

Feb 08
2012

Seeking Android Developer

I'm the CEO of WalkJogRun.net, a Chicago based startup in the Ravenswood Corridor. Our site gets over 16,000 visitors a day from around the world from runners looking to map a route, download a training plan or log their training to our diary. Our iPhone app has generated over $70,000 since it's launch 2 years ago and we're looking to replicate that success on the Android platform.

We're in search of a talented Android Developer and wondered if you know any devs that fit the bill. If so, please have them send over a letter of introduction. I'm looking for people with a passion and a talent, not a resume 18 pages long ;-)

We're looking for an intern looking to get their feet wet in a real world project that generates real revenue. I fully expect that the developer who can get this done would be hired to work full time on all of our platforms dabbling in the iPhone app and the website built on ColdFusion and MySQL. A passion for running would be ideal.

I see this as a great final year project or internship for the right candidate with some amazing opportunities with WalkJogRun at the end of the project.

Does location matter? Preferably greater Chicago area for the sake of simplicity but we're definitely not looking to offshore this project. I want someone who can grow with the company.

Jan 06
2011

Run a Linux process on a remote server and disconnect terminal session

I've been writing some nifty python scripts lately as we (WalkJogRun) migrate our route data from XML files to Google Maps encoded polylines. I finally whipped the script into shape and started pulling our route data from Amazon S3, encoding as SQL update statements and then rinse and repeat for nearly 500,000 legacy XML files. Trouble is, 500,000 files on my local machine would take about 20 hours.

Amazon AWS to the rescue! I span up a new Amazon EC2 medium size instance (high CPU) and pushed my script up to the cloud. The beauty of this is that the bandwidth between EC2 and S3 is free whereas my local machine relied on a crappy network connection and incurs the bandwidth charge on our S3 account. Ordinarily S3 bandwidth is pretty cheap but the script running on our EC2 machine is pulling down 5gb of data per minute and processing 1,000 files per minute. In around 8 hours we should have every legacy file processed and converted to a SQL statement we can run against our MySQL database.

But wait. My terminal timed out. Doh. If I login to the server over terminal and start the python script it is connected to my shell so if the connection breaks (on my crappy internet connection) the process is terminated on the server. The batch isn't as smart as it could be so it doesn't gracefully restart where it left off so I called on my friendly linux whiz Scott Frazer for a solution.

Scott directed me to the NOHUP command and after a few minutes of reading, a little typing and restarting my first batch I was able to disconnect my session thanks to this helpful command:

nohup ./myprogram > foo.out 2> foo.err < /dev/null &
Roughly, nohup says don't hangup when I do but because my script outputs to the terminal as it runs the rest of the output needs to be redirected to files instead of the console.

If you run this command, exit and log back in you'll see the PTS/1 replaced by ? when you run the ps -fe command. I'm able to track the progress of my script because each iteration/file writes a line to the sql file it generates and the handy wc -l command tells me how many lines are in that file.

So thanks to Scott I'll have all my new shiny encoded polylines for our database and we can start to eliminate the need for the legacy XML files. The background there is that Google Maps on the iPhone and in the browser both support polyline encoding such that instead of a large xml file of latitude and longitude coordinates (some as big as 40kb!) I get an encoded string I can insert into the database each no more than 1000 characters.

Nov 17
2010

Calculate Week of Year starting on a Monday

I am putting together a training log for WalkJogRun members to log their training data and ran into a spot with ColdFusion 8 showing Sunday as the first day of the week. Exercise training plans generally start on a Monday so I had to find a way around it.

The US starts it's week on a Sunday, the UK and a lot of other countries use Monday as the first day. For the most part Java is hiding that detail from you since java servers in the US will use Sunday as the first day of the week, whereas in the UK it will use Monday. I assume (rightly or wrongly) that the same is true for ColdFusion since it is built on Java.

To be explicit in ColdFusion you can construct a Java calendar object, set the first day of the week with setFirstDayOfWeek and then use a dateformat object to generate a week number starting on a Monday.

However, I realized after looking into these options my problem was the week() function of MySql. Arg. It turns out that date_format() for mysql has a format specifier %u for week of year beginning on a Monday or %U for week of year beginning on a Sunday. Perfect:

SELECT date_format(training_date,"%u"), sum(miles) as totmiles
FROM training_data
GROUP BY date_format(training_date,"%u")
ORDER BY date_format(training_date,"%u") DESC

Apr 09
2010

Apple is Doing the Right Thing Blocking Flash

I just read Joa Ebert's theoretical conversation parodying the move by Apple to block Flash code-generation tools and thought I'd repost my argument here. The argument is that Apple is being petty or childish by preventing developers from using code generation tools to develop apps.

I think the author and the flash devs who agree are selfishly angry. They think this is a move to block them and make things harder for THEM but it's not about being childish. It's about a track record, mobile development and maintaining the reputation of the app ecosystem.

Track Record.

I (and many of my mac cohorts) have seen Flash spike CPU on brand new hardware with fast processors and 8GB RAM so how will my poor little iPhone perform? Sure there is an argument that enabling flash on the devices reduces the demand for native apps but hybrid apps and jQuery are all options now but the native apps continue to flourish.

Mobile Development.

How big is your SWF? For every flash developer who knows that an optimized lightweight SWF loads faster there are hundreds who build and deploy massive SWF files that take a lot longer to load even on broadband, let alone filtering that through AT&T's "reliable" network. From a user experience if I wander onto a page with a bloated flash movie I risk crashing my device or at least locking up my bandwidth.

Code generation.

I've been a ColdFusion developer for over 10 years and have written code generation apps from scratch but always with the understanding it gets me 80% of the way there even when I'm generating ColdFusion apps! Imagine the idea of trying to write codegen in one language for another?!

It took me over 200 hours of development to release the first version of WalkJogRun Running Routes - and another 200 for each subsequent release. It's just that hard.

If the developers using the generated code don't learn Objective C it puts pressure on the review process. Just to correct the point in the blog post - review time is less than a week and has been for some time with my record turnaround at 3 days recently. Starting with this 80% code developers either never submit because they can't get it working or do submit it and have multiple app rejections because they don't understand why it breaks.

A plethora of CS5 generated apps could therefore put a huge strain on the review resources based on these multiple rejections. Even if an app sneaks through the likelyhood of an app continuing to crash would threaten the reputation of the developer and the app store.

A solution.

I think that if Adobe would be willing to sponsor the addition of a team of Apple Appstore reviewers dedicated to apps built with Adobe's codegen tools the situation would be very different. It's easy for Adobe to say their tools would be perfect but until they pay the salaries of the review team it's hard to accept responsibility for the consequences of their actions.

Jan 19
2010

Run your ass off this year!

After another 200 hour programming marathon spread over 4 months I'm thrilled to announce the release of version 3 of WalkJogRun's iPhone App "WalkJogRun Running Routes".

What does it do?

The most significant change version 2 was the addition of 23 training plans created by Coach Jenny Hadfield of Runners World fame. Once you sign up for a training plan and pick a start date you'll get alerts every morning at 6am (silent so they don't wake you) to tell you how far to run, how fast and give you motivation. Tap the find routes button to find a training route in your neighborhood from the 600,000 routes at WalkJogRun.net

What if I've never run before?

We've got plans for beginners, intermediate and advanced runners including one called "Run your first 5k" designed to take you from the sofa to being able to run a 5k race in 10 weeks. We've also got 10k training plans, half marathon training plans and full marathon training plans.

Gimme the nerdy stuff

The programs themselves are delivered as in-app purchases using the StoreKit framework on the device to process payments and then send receipts to the ColdFusion server to register the subscription and begin delivery of the alerts.

The alerts are delivered as Apple Push Notifications generated by ColdFusion. No mean feat I can tell you using Java in ColdFusion to connect to a streaming data socket to send and receive the bytes and then drop the encoded JSON packets off on your phone. The phone gets the alert, opens the app and takes you to the training session for the day to show you your training tip.

Download a copy of "WalkJogRun Running Routes" before it gets too late!

Dec 31
2009

Affiliate Link Shortening for Profit

Coupon Cabin just launched their latest offering yesterday in the world of affiliate marketing called Dealfer.com so you make commissions on the sales you generate at participating merchants. It's a clever idea and leverages their relationships with affiliate merchants to help you make money.

Why would I need a short URL?

If you're not hip to the URL shortening jive yet it has a couple of benefits. The first is that shorter URLs are easier for people to type in and they fit on business cards, in books or promotional materials nicely. Dealfer.com links become http://dlfr.me/xxx where xxx represents a string of characters used to find your link and expand it when someone clicks. Being so short they also use less characters on a webpage or the most common use in twitter where you're limited to just 140 characters.

The second big reason for URL shortening is that marketers can track how many clicks a link in a certain place received. For example if you tweet a link using dealfer you'll be able to see how many clicks it got on twitter. Some URL shortening services, like bit.ly, even offer stats so that even if your link get's copied and repurposed anywhere like on someone's blog you'll know about it.

Online marketing is easier to monitor than offline marketing traditionally because when someone types in your home page URL into their browser you have no idea where they saw it or heard it, be it on the side of a bus or on the radio but by using a link shortening service you bring traditional marketing back into the ring. The downside is that you're marketing a link that doesn't look like your home page - dlfr.me - but at least it's memorable "deal for me", with the exception of the string part that follows!

Why not use bit.ly?

True, the links are one character shorter and the stats breakout the referral sources but Dealfer wins out in my mind because if I'm linking to a merchant they support I'll get a commission for a sale vs bit.ly links where I won't. Commissions range up to 15% which could help turn a hobby blog into a paying venture.

How does it work?

Just like every other URL shortening service but you get paid! The first way to use it is that any time you want to shorten a URL just go to Dealfer.com and paste in the URL. If you're not logged in it will ask you to login, create an account or if you just need a short URL you can skip registration and get the short URL.

When you register you give them a PayPal account to receive funds for any commissions you make. Not every link is going to result in commissions but their list of merchants broken out by commission level could inspire you to promote products in the 15% tier! If you link to a merchant not on the list or a site that doesn't monetize you'll get your short URL and can track the number of clicks but the real magic happens when you link to a supported merchant. Chances are if you get 100 clicks to a merchant you'll end up with a sale, especially if it's something your peers would be interested. You can either link to the top level domain name or deep link to a specific product.

Any top tips?

They have a bookmarklet you can drag onto your bookmarks to make it easier to generate links while you shop. Basically if you're on a product page for something you think your friends would like you can hit the bookmarklet and it pops up a window to give you a dealfer link to use when you're done shopping. You don't have to worry about whether it's on the participating merchant list or not - you'll still get a link you can share. If it is, it's a bonus.

I would recommend looking at the merchant list shown by commission percentage to see what to expect from each merchant. Some only offer 1% of a sale and others offer 15%. Familiarize yourself with the sites so you know that if you have a choice between linking to something at site A vs site B (a participating merchant) you don't miss any opportunities.

Lastly, think about where you are sharing your links. If your blog is about Adobe products then linking to Adobe makes perfect sense. Try to put your readers one click away from the purchase instead of just linking to the merchant home page. For example a long blog post about Adobe ColdFusion would deserve a link write down to the ColdFusion product info/purchasing/trial page.

Until the stats are broken out at Dealfer by referrer you can at least create different links for the different places where you wish to use a link to a site. For example in an ad in the newspaper you might use one link and for a twitter promotion another. Even though they both point at the same place you get to see how many people "clicked" each. (The quotes because if they type it in after seeing it offline they are still tracked as a click).

Think about opportunities to promote specific products as you wander around the web. If you're in a forum about the latest nike running shoe and you know one of the featured merchants has a sale on that product or is the cheapest, "dealfer a link" instead of just linking to the store directly and you'll still get commissions on whatever sells. Even on facebook or linked in where people are asking for product recommendations. If it's truly a great product you believe in and a reputable store it will sell and you'll get the credit.

Future developments

I'd like to see this service incorporated into some of the big twitter applications like cotweet.com and Twitterific or Tweet Deck. The advantage for developers is that until the account holder enters their own login for Dealfer into the application, the developers would be credited with commissions generated by links. I shudder to think how many links per day the average twitter app sends!

Another feature I'd like to see is a list of the merchants listed by the highest conversion rates and/or revenue generated per click. This type of breakout could help potential linkers find the stores that, while they may offer excellent commissions, rarely convert visitors into sales. Dodging the dogs could lead to a really profitable linking hobby!

Conclusion

Go create an account at Dealfer.com, grab the bookmarklet or their toolbar and stop before you think about recommending a product next time and "deafer a link" instead.

Sep 08
2009

Testing iPhone StoreKit purchases

I spent a significant amount of time troubleshooting the iPhone StoreKit framework for our WalkJogRun iPhone app this weekend. I finally discovered that the documentation was slightly misleading after discovering a post on the Apple developer forums.

I had followed the StoreKit developer guide for testing which instructs you to 1. Create an account in iTunes Connect 2. Go to the Store Settings app and sign out 3. Sign in as your test account 4. Go to your app and test the purchase process

The problem comes at step 3 when you sign in. You are typically (but not consistently) told that the login has never been used in the App Store before so you'll need to review your details, which begins an account mini-interview to pick a country and enter credit card details. If you go anywhere near this process, you'll not be able to use the account when you go to your app and finally login with a series of different alerts, mainly "Your Password has Changed" or confirm your billing info.

The solution, I discovered from an Apple forum post by "Kuga", is NOT to sign in once you logout of your real account - instead just go straight to your app after you sign out in the Store Settings and use the in-app login.

Note that if you ran into the "your password has changed" error you'll find that it's damn near impossible (I couldn't work it out) how to turn an account you completed an interview for back into an account you can use for testing.

Country Specific Testing Notes

Instead of hard coding pricing into your app, if you've followed the store kit programming guide you'll pull the pricing and descriptions from iTunes Connect but initially pricing is shown in the country you were using before you logged out in the store settings.

Ben Gottlieb, author of the awesome Crosswords and Satchel iphone apps, gave me a great tip at the last NSCoder night here in Chicago for in app purchase accounts - if you use gmail you can create "throwaway aliases" to use when creating users, since each email account you use must be a unique email address that has never been used for testing and not an existing apple id. So, for example, if your email address was aardvark@gmail.com you can create fake aliases with the "+ syntax" so I would create a test user "aardvark+itcUS@gmail.com" for a US iTunes Connect test user account. The +itcUS gets ignored by Google and the email related to that account still goes into gmail for the aardvark@gmail.com account. It saves you creating a ton of email accounts for testing.

If you've created a test user for the same country as your regular account you'll have no trouble finalizing your purchase. If you've chosen a store in another country for your test user you'll be told initially that your account is only valid for that country store and you're unable to finish your purchase. This is a good thing!

Close your application and go to the store settings and you should see that you are actually logged in with that new test account for a different country. Close the store settings and reopen your app. At the point where pricing info is shown you should now see it localized to the test user country and you can complete the purchase in that language. Just be aware that the dialogs will all be in your target language so before you test the Japan store you might want to memorize the order of the buttons :-)

Verifying Receipts

I threw a simple alert in my "provide content" function to give a visual confirmation initially:

- (void) provideContent:(NSString *)productId {
    /* This is where I download the product based on the product Id to store on their phone */
    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Purchase complete" message:@"Thanks for buying, sucka" delegate:self cancelButtonTitle:@"Done" otherButtonTitles:nil];
    [av show];
    [av release];
}

This is where I'll pull down the actual content if my purchase was successful. Since you should have your server validate receipts before delivering content you need to send the encoded receipt data over http. This piece isn't well documented but a great post on StackOverflow from JDAndrea provides the code necessary to pass the signed receipt by URL to your own server, in that case a PHP box. Since I'm a ColdFusion developer I wrote the following snippet to handle the work:


<cfset stcReceiptSend = structNew() />
<cfset stcReceiptSend["receipt-data"] = url.receipt />
<cfset receipt = serializeJSON(stcReceiptSend)>
<cfhttp method="POST" url="https://sandbox.itunes.apple.com/verifyReceipt">
    <cfhttpparam value="#receipt#" type="XML" />
</cfhttp>
<cftry>
<cfset result = deserializeJSON(cfhttp.filecontent)>
<cfmail from="mytestemail@example.com" to="mytestemail@example.com" subject="iPhone in-app Receipt Verification" type="html">
<cfdump var="#result#">
</cfmail>
<cfif result.status eq "0">
<cfcontent reset="yes"><cfoutput>0</cfoutput>
<cfelse>
<cfcontent reset="yes"><cfoutput>1</cfoutput>
</cfif>
<cfcatch>
<cfcontent reset="yes"><cfoutput>1</cfoutput>
</cfcatch>
</cftry>
It's very simple and just turns the encoded receipt data from your app into a serialized JSON packet which is posted to the itunes sandbox. Note for production releases you'll need to change that url to be the real itunes URL. If the result is a 0 you have a valid itunes transaction and I send an email dumping out the transaction keys to my email for reference before returning a 0 (success) to the code in my iPhone app. Anything other than a 0 in the result.status means something isn't right and you should pass back something other than a 0 to the iPhone app so you don't deliver the content they "unlocked".

That's it for my StoreKit testing summary - hope it helps remove some obstacles I encountered along the way. If you're looking for tips on this stuff I strongly recommend three sites which have proven critical to my forward motion: iPhoneSDK, Apple Discussions and StackOverflow. The iPhone Reference Library is a fourth but that *should* go without saying. I've found it particular useful searching for exact classnames to find the detailed API overview of properties and methods I need.

Sep 03
2009

Patch the box and upgrade CF8 JRE for stability

When I signed up for a VPS pre-installed with CF8 Enterprise I made the assumption it would be patched for me. Hmph. After a month and a bit of tolerating instability I finally nailed the problem.

[More]

Aug 11
2009

CF8 Server Monitoring alerts oddity

Has anyone used CF8 Server monitoring and seen negative values in the app scope in terms of memory size? I'm getting some peculiar alerts ever few days related to my site adamhowitt.com and don't know where to start. My google foo is weak so I thought I'd throw it out to the crowd.

The server hosts a few sites of mine including this blog and after seeing it hang every now and then I decided to start monitoring alerts (since it's an enterprise box). The alerts that are triggering are that the JVM Memory exceeds 450 MB and the server starts to slow down. When I look at the snapshot it produces and sends me everything looks normal except:

Application Scope Memory Used - -22033448 bytes
[Application Name : Memory Used]
   adamhowitt_site : -22600792 bytes
      [Variable Type : Variable Name : Size]
      CFC : ham : 113168 bytes
      STRUCT : stcservice : 8976 bytes
      STRUCT : stcresource : 6584 bytes
      ARRAY : restypesorted : 448 bytes
      STRUCT : stcresourcetypes : 216 bytes
      STRUCT : stcservicemap : 176 bytes
      68FB39AB-1CBF-0773-47DEBE569016FA50 : strresources : 112 bytes
      68FA822E-1CBF-0773-47CA40FAA0CD3F5A : strportfolio : 112 bytes
      68FABC5A-1CBF-0773-47FF8F2DE5691EB2 : strservices : 112 bytes
      C:\xxx\xxxx\xxx\xx\ : hamroot : 112 bytes

The part that concerns me is the -22,033,448 bytes (or -22 MB) of app scope memory. It's consistently this app and I've looked over my code without success.

I realize the topic narrows my potential audience down to a few people that use alerts but I'd love to work this out. It seems like the continued growth of the JVM memory used on the box is directly tied to this app and the incorrect memory report. Is it a leak? Any help GREATLY appreciated!

Jun 26
2009

WalkJogRun TV Interview

I'm thrilled to announce that I recorded a TV interview in New York last weekend for Better TV and a sneak peak has appeared on YouTube. I was interviewed by Ereka Vetrini who you may remember from season 1 of the Apprentice.

More Entries