12 · 07

Public Domain Fail - Whitehouse.gov is blocking access to public RSS feeds and content.

UPDATE: 7/12/10 10:16PM

All functionality seems to have been restored. Whether this was a hiccup in the system (probable) or a reversal of the blocking we will never know.  I am just glad that it has been resolved with minimal emails/posts on my part.

--------------------------------------------------

 

I have an iPhone app called Obama Speeches. It is an app that publishes the weekly addresses of the President, along with other important speeches made by him. All content is in the public domain, and the content is retrieved from public URL's. I have been using the same script for over a year to automatically pull down the content, until today. I started getting 404's.

A quick wget of the feed URL confirmed this to be true:

[ps6736]$ wget http://www.whitehouse.gov/podcast/video/weekly-addresses/rss.xml
--07:03:09--  http://www.whitehouse.gov/podcast/video/weekly-addresses/rss.xml
           => `rss.xml'
Resolving www.whitehouse.gov... 65.200.11.24, 65.200.11.25
Connecting to www.whitehouse.gov|65.200.11.24|:80... connected.
HTTP request sent, awaiting response... 404 Not Found
07:03:10 ERROR 404: Not Found.

Hmmm. I checked on a few other machines and found that it was going through fine. WTF? I tried using CURL, open-uri and other forms of fetching the RSS feed from whitehouse.gov but they still blocked me or redirected my requests from this machine. Every attempt to connect from other machines worked fine.

coneybeare $ wget http://www.whitehouse.gov/podcast/video/weekly-addresses/rss.xml
--2010-07-12 10:03:45--  http://www.whitehouse.gov/podcast/video/weekly-addresses/rss.xml
Resolving www.whitehouse.gov... 64.81.79.72, 64.81.79.70
Connecting to www.whitehouse.gov|64.81.79.72|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 97387 (95K) [application/rss+xml]
Saving to: `rss.xml'

100%[=====================================>] 97,387       239K/s   in 0.4s    

2010-07-12 10:03:46 (239 KB/s) - `rss.xml' saved [97387/97387]

I also checked other URL's to make sure this machine actually was connected an lo and behold, I could get a connection. Don't worry, I have it working again through tunneling into other machines to fetch the feed but I shouldn't have to — Public domain is public domain.

I think that whitehouse.gov is unhappy with my app (and it's success) competing with theirs and tried to take me down. The problem is that I am doing nothing illegal here and they have no right to block access to the public feeds and content. Of course, saying this makes me a conspiracy theorist but what else can I deduce from the situation?

Hey US Gov: If you have a problem with my frequency or method of fetching the public data, please try to contact me instead of shutting me off completely.

2 · 07

Using AudioStreamer with AVAudioPlayer and Avoiding Hardware Locking

In Ambiance, I use some customized AVAudioPlayers to play the apps audio. When possible, these AVAudioPLayers use hardware decoding of the audio files which speeds up the audio processing considerably and frees the software from having to dedicate resources to the process.

 
I also use Matt Gallagher's AudioStreamer to play remote files off my server for Ambiance previews.  In the latest version of the app, I was getting some feedback from beta testers that preview was not always working. One of them sent me a screenshot:
 
 
So I set out on trying to reproduce and I found that playing an AudioStreamer stream worked fine when no other audio was playing, but when other audio was playing, it failed.  Setting breakpoints in the code, I saw that it was failing in the enqueueBuffer method in this code:
 
err = AudioQueueStart(audioQueue, NULL);
if (err)
{
    [self failWithErrorCode:AS_AUDIO_QUEUE_START_FAILED];
    return;
}
err was returning a code of 1752656245. Knowing that Audio Queue codes are actually ascii codes, I threw it into calculator:
 
 
and saw "hwiu" as the code.  A quick google search led me to the docs where I saw that this means that the streamer was unable to obtain the hardware codec.  This makes sense! Ambiance uses the hardware codec to play sounds, and when a preview comes along and tries to play a streaming sound it cannot due to the fact that that hardware spot is taken.  I had been pausing the main sound, but that did not release the hold on the hardware codec.
 
It turns out the solution to my problem was much easier. Previews in my app are not used for very long durations, so using the software to play them isn't too taxing.  I decided to change the hardware codec preference for the audioQueue:
 
// set the software codec too on the queue.
UInt32 val = kAudioQueueHardwareCodecPolicy_PreferSoftware;
OSStatus ignorableError;
ignorableError = AudioQueueSetProperty(audioQueue, kAudioQueueProperty_HardwareCodecPolicy, &val, sizeOfUInt32);
if (ignorableError)
{
    return;
}
This code goes in "createQueue", line 1494 (as of 7/2/10).  It is telling the codec to prefer the software route, but use the hardware if anything fails.  So far, all tests have been unable to reproduce the issue and everything works fine.
30 · 06

Edit Google Analytics for iPhone to use a Hidden Database

I use Google Analytics in my iPhone apps to track how my customers are using them. It is very useful for determining the answers to questions such as:

 - Do users prefer Browsing or Searching
 - Do users setup simple, or complex alarms
 - Do users even tap _____ at all?

In Ambiance 3.0, I have added File Sharing through iTunes in order to process the App's Backup Files and capabilities.  The way this works is that iTunes will list the entire contents of your Documents Directory in the iTunes File Sharing pane for your app, unless they are a hidden file.  This means that every data file Ambiance uses has a "." prefix as I do not want to share these files. The only problem is that I could not find a way to hide the googleAnalytics.sql file that was created by Google, thus, the customer saw this:

While this isn't the worst thing in the world, it isn't ideal either. I contacted a friend of mine for some help and he had the brilliant idea of using a Hex Editor, editing the libGoogleAnalytics.a file to change the name of this string. Now, the string is hidden and all is good with the world!

Here is the tip he gave me:
I have modified the
library with an hexadecimal editor, I have used 0xed
(http://www.suavetech.com/0xed/0xed.html), and changed the first
letter of the string, the g, by a dot. The library seem to work and
generates the file. I have changed the first letter because I don't
know if you can add a new character to the string in a binary file
without side effects, and this way the length of the string and
library remains the same.
- Antonio Cabezuelo ( tapsandswipes.com )

So I installed 0xED, opened libGoogleAnalytics.sql and searched for "googleAnalytics.sql" and changed it to ".oogleAnalytics.sql", saved and ran the app and it works great.

Hope this helps somebody out because it really made my life easier working with the Google Analytics library. BTW, don't bother contacting Google with any issues, their support is horrible. I emailed at least 10 times about this before asking a friend.
23 · 06

What happened with the Ambiance 3.0 failure

The last two days were pretty bad for me.  I fucked up bad.  I mean really bad. really really bad.  As a developer you expect bugs, and even though you do your testing and QA, some always slip through the cracks.

 
I was super excited to have an Ambiance 3.0 release on the iOS 4 release date as it would mean extra exposure and press. The update came and I watched my servers as thousands and thousands of customers started updating the app.  Then the emails started trickling in…
 
Some users were reporting of their sounds being lost in the update, others reported not being able to save sounds and other about crashes.  It was only a few so I thought it might be an isolated bug or two.  Then the emails started FLOODING in.  I am talking about hundreds and hundreds of emails, each with varying degrees of intensity.
 
"WHAT HAPPENED TO AMBIANCE I PAID FOR!"
"Was one of my favorite apps"
"FUUUUUUUUCCCCCCCCCCKKKKKKK UUUUUUUUUUUUUUUUUUUUUU"

Ouch.

I immediately pulled the app from the store to stop people from updating to the now clearly-bad update.  At this point, about 15,000 customers got the updated app and I feared the worst.  Of all types of bugs, the last kind of bug you want is a data loss bug and it seemed that this might just be that.  I was able to grab some of my test phones and after trying to duplicate, I could not.  My app worked fine.  All these customers can't be wrong though so I contacted a few of the nicer ones to send me their import file.

Once I got the import files and scanned them for common links, I tried using one of them to import. BAM! I ran into all three major symptoms: Failed Import, No Downloading, Crashes.  Uh oh…
 

BUG #1
After a few minutes sleuthing, I was able to track down bug #1.  Get this: On my test devices, I never rate sounds. This is because I don't want to affect the sound ratings unfairly.  Thus, NONE of my test devices had a sound with a rating in it.  Of course, there was a bug in the import script on the Rating line.  This bug was preventing users from importing their old libraries because of an exception.  That exception was caught and the app went along without the users sounds imported.
 

BUG #2
Bug #1 was bad but it wasn't over. I still couldn't figure out how users were not being able to download sounds.  I tried to take my mind out of developer mode and acted like a random user.  I tried the update process from scratch again, but this time, after the failed import, I did what most users did: tried to use the apps restore functionality to restore using the backup file.
 
This file was created specifically for this purpose and I have no regrets about doing it.  Unfortunately, bug #2 lied in the import database path.  Using the apps restore function with a backup file from Ambiance 2.x had a bug that caused the core data database to be overwritten by the old non Core-Data db.  The restore process would overwrite the DB, then ask the user to restart, then on restart, would open the DB and re-download sounds that should be there.  Except that now the DB can't be opened by Core-Data, and nothing new can be saved either.

FUCK!

The Fix
I patched them both up which took a few hours because I now had to support recovery from at least 4 different potential error states (2^2). I also used the time to do additional checking and failsafes into the restore method to prevent this and other potential failures from happening.  On the bright side, I was able to figure out a way to recover the users data as long as they did not remove the app from the phone.  All the sounds were in the Documents directory still, so I was able to make sense of the old and new DB's,correctly do the import, and correctly transfer the old data.

I uploaded the app to iTunesConnect on Monday night and send of a few emails to request an expedited review. Meanwhile I sent out copies of the update to Beta Testers to see if any issues were still there, ready to pull the app from the review queue if necessary.  Everything went smoothly so I began to wait, fearing the worts with a 2 week review time.  I am not sure if the request was granted or if it was pure luck, but tonight (after 2 days) the update was approved.  1 hour into the availability, about 2000 people have updated and I have yet to hear any issues.  

So what did I learn here? 

- I need to have a more rigorous QA cycle
- Rushing to get the app out on release day can bite you in the ass
- Make sure the "restore" function of your app actually will restore the app from all states.
- Your customer will genuinely hate you if their $2.99 app is not working for 1 minute.

I hope the ratings for Ambiance weren't affected by this hiccup and that these past 2 days can fade into the deep hole of buried developer failures.

The Ambiance 3.0.1 update is now live in the store (http://bit.ly/ambiance)
21 · 06

Ambiance 3.0 available in the iTunes store with background audio!

5 · 06

Getting HTML5 Audio tag and flash fallback to work nicely with all browsers

In implementing the new (yet-to-be-released) html Ambiance audio pages, I wanted to take advantage of modern browsers support of the tag. I loaded it up with a flash fallback but for some reason, in Firefox (!!!), mp3's cannot be played with html5 audio. Ambiance uses mp3 files and caf files, neither of which are supported by Firefox and html5.

I was left with 2 choices:

  1. Convert the entire Ambiance library to ogg just for firefox users.
  2. Fine tune the javascript to properly fall back onto the flash AudioPlayer

I decided that ogg sucks and I would not waste any time doing the conversions, so I went for number 2.

Using code from html5doctor as a guide, and using the Standalone Flash WPAudioPlayer, I came up with the following code snippet that seems to work in all browsers.

It pretty much speaks for itself, but here is quick explanation. First, the html5 audio tag is placed on the page with the id="audioplayer". Next, some javascript runs that checks a few things and if any of them fail, it replaces the id="audioplayer" element with the fallback flash player. Of the things it checks, it checks that the browser can create the audio element (html5 supported), then it check that the browser can play a filetype of audio/mpeg (mp3). If any of these fail, it will go to flash. This works on all the browsers I have tested on, including firefox, but I make no guarantees. Just from code inspection, if the user has javascript disabled, it won't work. But I don't care. Who really wants to provide support for those (L)users anyway ;)

Hope it helps.

23 · 03

Preview of the new Alarm system in Ambiance 3.0

1 · 02

How to Make Custom Drawn Gradient Backgrounds in a Grouped UITableView with Core Graphics

In iPhone app design, it is important to find a balance between customization and familiarity.  Many times, subtle differences are all you need to make yourself stand out from the crowd.  While doing the Ambiance 3.0 redesign, I wanted something to make my list of content a little different than all the other cookie cutter table views out there.

A great place to start is to implement your own background and use a clear table view background.  Many apps are now doing this and it is come to be expected from a grouped UITableView that is done with a little love.  Another way to spruce up these tables is to add a custom background color.  Since 3.0, this has been as easy as setting the cells backgroundColor property.  I implemented both of these and it wasn't enough for me. It still looked like so many apps out there.  I thought about putting a gradient view as the background, only to find that setting a grouped UITableViewCell's background ignored the nice rounded corners of the cell.  Almost giving up, I googled around to see if anybody else has done it and shared some code.

This was a great resource as it helped me in the right direction — Core Graphics.  It was meant as a way to customize the background of a cell before the 3.0 sdk came out, but I used it as a basis for my code to draw a gradient!  It needed tweaking and optimization, but after a little bit of hacking away at it, I was able to get it to work nicely.  I present to you the UACellBackgroundView.

To use the UACellBackgroundView, simply add the .h and .m files to your project, then use it as the cell background view.

.h file
.m file

Whenever you want to use it, just set the cell's backgroundView to be the UACellBackgroundView in your own UITableViewCell Subclass's initWithStyle  method.  Then, when you have your data and are creating cells, simply set the position of the cell by calling setPosition, of just call the line directly if you don't want to subclass the UITableViewCell.  The position is important as it lets the cell know to draw itself correctly depending on whether or not the cell is first, last, in the middle, or a single cell.

Hope this helps you in your quest for a better app.  If you want to use it, you will have to set your cell labels and elements to have a clear background, so hopefully you have a fast drawing method and have optimized your table view cells to do minimum work during scrolling.

29 · 10

Fixing symbolicatecrash...

Because you found your way here, I am assuming you already know what symbolicatecrash is and when/why you would use it.  If not, take a detour here and come back.  This tool has been great but is very temperamental.  It worked for a while when I first started, then it broke and stopped giving results.  I applied the Alan Quatermain Fix, but things still weren't right.

Well, tonight I had a client app rejected from crash I couldn't reproduce.  I only had 1 crash log from Apple, and the stupid symbolicatecrash script wasn't finding anything!  I had to dig in and see what was up.  After spending a little bit brushing up my Perl, I was able to fix the problem.

Basically, the Regex that the script uses was failing to match in two places: the bundle name, and the versions.

Change lines 372-377 in the symbolicatecrash script to look like this:

There are 2 changes from the pre-Alan-Quartermain-Fix:
On line 374, I changed the "(.+)" to be "([^\s]+)" just like the AQ fix. 
On line 375, I changed the "\s+ .+ \(.+\) \s*" to be "\s+ \w+ \s*" because my crash reports never have versions in parenthesis.

I don't know if this will work for everybody, but it works for me and the crash reports I get back from iPods and iPhones.  Good luck!
29 · 10

Ambiance has been named the "App of the Day"...

(via http://appoftheday.com/app/Ambiance )

Its a great honor to be named alongside apps like Tweetie 2 and DropBox. This is great!

About

The Findings of an iPhone Developer

Pages

Flair