Wednesday, April 29, 2009

DevDiary: Audio stream handling improvements

I'm currently working on some improvements to the audio streaming code used in my radio app engine. Specifically, I'm working on improving the buffering of the audio stream. One of the more common complaints with radio apps in general (not just mine) is the behavior when the wireless connection is unreliable.

A lot of the connection quality issues depend on the data rate of the stream in relation to the current wireless signal quality. If the wireless connection is too poor, then it will be technically impossible for the connection to maintain a fast enough speed to keep up with the audio stream's data rate. If the audio is playing at 64K, but the wireless connection is so bad it only allows 32K of data per second, the stream is going to stop playing . In this specific situation, there's nothing I as a developer can do. I can't violate the laws of physics and get more bandwidth out of a bad wireless connection.

However, there are some things I can do if the wireless signal quality decreases only intermittently. If the signal gets so bad that it is dropped, my radio engine will currently stop the audio playback and attempt to reconnect. As part of this reconnection, the current audio buffers are cleared to start with a clean slate with the new connection. So, when a connection is lost, the end-user will immediately notice this as the audio will stop while the app tries to reconnect. A better idea is to maintain the current buffered audio data and allow that to continue to play while the app attempts to reconnect in the background. This is one of the improvements I've made.

Based on the audio stream bit-rate, this now allows a fairly decent time window for the app to reconnect before the audio buffer runs out of data. With a 128K "live" stream, based on the testing I've done it appears that the furthest ahead in time you can get is about 12.5 seconds. With a 64K stream, that approximately doubles to 22 seconds. So, if the app can reconnect within this time window, there should be no interruption in the audio playing.

I've done a road-test with my new code - I drove a section of the highway where I'd normally lose a connection with my app about a half dozen times. I'm happy to report the audio playback wasn't interrupted once with my new code changes! The app lost its connection to the server several times, but with my improved buffering, it wasn't even noticeable audio-wise.

I'm now working on seeing if it is possible to seamlessly re-stitch the two streams back together by comparing the audio packets. I'm not sure if this will be possible. I haven't yet determined if the streaming server always serves identical MP3/AAC frames for the same point in time in a stream. If it does, then there might be a time overlap between the buffered stream and the newly acquired stream and in that case I can simply compare the packets and find where the two streams overlap and merge the buffers at the point. This way, the streams will be seamlessly merged.

Thursday, April 23, 2009

The Gavel Lite - an experiment

The Gavel Lite is now available as a free download on the iTunes app store. It's a free version of my 99 cent app called, appropriately enough, The Gavel. The difference is the lite version is low-fat, has far fewer calories, and only includes 3 objects rather than 13: a gavel, a mallet, and a flashlight. But it still has the same great taste!

This lite version is an experiment to see what effect, if any, it has on the sales numbers of the full version. Will the sales of the 99 cent app go up, down, or stay the same?

I'll post a follow-up with results of this experiment in a few weeks.

Wednesday, April 15, 2009

iPhone Devs, change the date!

This isn't new news, but I see enough apps not taking advantage of this, so I figure it's worth repeating:

After your app is approved by Apple, immediately go into iTunesConnect and change the date of your app to be the date of the approval email from Apple.

If you do not do this, you are missing out on a lot of potential sales. Currently, if you do not do this, Apple will list your app in the "recently released" apps lists with the date of when you submitted the app. Given the average 5 business day approval time for Apple, this means your app will most likely appear buried several pages back on the lists.

If you change the date to the date of Apple's approval email, your app will instead be listed with that date. NOTE: you must use the date of Apple's email. Using another date will not work for positioning in the recently released listings.

Creating iPhone app video demos

Not having access to a good video camera, I was finding it very challenging to create a decent video demo of some of my iPhone apps. The issues of lighting and contrast were particularly difficult, especially with apps that have a black background (such as my Artificial Life app). Also, for an app that contained very small details on the screen, recording with a camera often made it difficult to make out the finer details in the image.

After producing a few admittedly "very rough" video demos for my apps, I finally decided to track down a better solution. I had noticed some companies had very nice demos in the same video aspect ratio as the iPhone screen, and they appeared to have been generated on a Mac vs. a recording of the iPhone screen. (This was noticeable since there was no hand visible making UI interactions and instead there were white circles representing where someone would tap).

After a few Google searches, I came across ScreenFlow, a $99 product that makes creating video demos of any portion of a Mac screen very simple. I've found capturing video of the iPhone simulator produces excellent quality for an iPhone app demo. There are limitations, of course. Since your are recording your app in the simulator, certain features are unavailable, such as demonstrating accelerometer behavior, or multi-touch beyond two finger pinching and stretching. But, for more basic functionality only involving taps and such, this works quite well.

It was definitely worth the $99 for me.

And since this ScreenFlow application allows recording video demos of a Mac in operation, here's a video demo I recorded demonstrating how easy it is to make a quick iPhone video demo. (Got a bit of recursion there...) The demo starts at the point after the rough video capture of the iPhone simulator has already been performed.


Sorry, the above video is currently in a format not viewable on the iPhone. Please view this updated version for a video that is iPhone compatible.

After you export your video (you can even choose iPhone format so it is saved as an iPhone compatible m4v file), you can then easily embed the video in a web page using Apple's quicktime player object. Something similar to the following object tag should work, replacing both references to my video with your own. Also, this assumes the video was saved in 1/2 the normal resolution (160x240 rather than 320x480). The extra 20 pixels in height are for the quick time video control bar on the bottom of the video.


<object classid="clsid:02bf25d5-8c17-4b23-bc80-d3488abddc6b" width="160" height="260" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=6,0,2,0" id="video_qt">
<param name="align" value="middle" />
<param name="src" value="http://stormyprods.com/movies/The%20Gavel-small.m4v" />
<param name="loop" value="false" />
<param name="controller" value="true" />
<param name='autoplay' value="false" />
<embed name="video_qt" enablejavascript="true" type="video/quicktime" width="160" height="260" src="http://stormyprods.com/movies/The%20Gavel-small.m4v" controller="true" autoplay="false" loop="false" align="middle">
</embed>
</object>

The Gavel update now available

A new update to The Gavel has been published on the iTunes App Store. The new version adds a few minor changes. You can now toggle the random events on or off and can also change the color of the background.

Here is a short video demonstrating all the objects and a couple of the random events.









Now available on iTunes.

Friday, April 10, 2009

Avoiding iPhone app rejection from Apple

I've been developing apps for the iPhone for over 6 months now. Over this time period, I've successfully submitted over 45 apps, the majority under my own company's iTunes account. Given the large number of app submissions, I've had my share of app rejections.

As has been mentioned many many times on the various developer forums, Apple's approval process can be very frustrating and inconsistent. However, if you are careful, you can greatly reduce your risk of getting an app rejected.

Based on my own experiences, here's my list of things to be careful about:

1. The dreaded HIG Violation of Apple's Human Interface Guidelines (HIG) is probably the most frequent cause for an app to be rejected. As an iPhone developer, you definitely need to read the HIG and follow the guidelines! Take every single item mentioned in the HIG seriously. Yes, many apps demonstrate gross violations of the HIG (after all, splash screens are a no-no according to the HIG), but you can never claim "App X does this and is already in the store" as an excuse when Apple rejects your app. Well, you can claim that, but Apple will not accept it as a valid justification.

There are certain items in the HIG to which Apple does seem to turn a blind eye (splash screens probably being the most obvious), but unless you like taking chances with your livelihood, avoid going against any of the HIG guidelines.

2. Matching icons Believe it or not, Apple is now requiring the 512x512 iTunes Store icon match the 57x57 icon displayed on the iPhone. As a reason for rejection, Apple will state having unmatching icons is in violation of the HIG. There's nothing in the HIG that states these two icons must match, but since it's Apple's store, you basically need to play by their arbitrary rules. So, unless you want unnecessary delays in your approval, make sure your icons match. The icons don't have to be identical, but there should be something shared between the two. Just having them both be pictures that are of a similar theme is not enough.

3. Simulating failures Apple doesn't like anything that pretends the iPhone or iPod Touch is failing. So, simulating a cracked screen is a good way to get your app rejected. Any other idea of faking a failure of the iPhone which you might think others would find amusing will probably also be a reason for rejection from Apple.

4. Button images must be consistent If you decide to use one of the existing images Apple provides for buttons, be careful you use it for an identical function. While the HIG states you can use a standard button in a non-standard way if your app is providing a "immersive environment", you are better off creating your own custom buttons to avoid the risk of rejection. If you use the "action button" image, make sure tapping on it brings up a menu with choices. If it doesn't, Apple may reject the app.

5. Bandwidth usage over cellular networks If your app downloads data over the cellular network, ensure you do not use too much bandwidth. How much is too much? Well, there isn't an exact number, but a tech support person from Apple advised me to not exceed 4.5 meg of data per 5 minutes of activity. You can test your app's usage by going into your iPhone settings, choosing the General->Usage menu and clearing the stats. Then run your app for 5 minutes, return to this screen and see what the stats say. Also, to get the most accurate numbers, you should turn off any other network activity on your phone while you run the test (such as Email or MobileMe updates).

6. Popup for network detection If your app requires the use of the Internet, you must detect when the network is unavailable and provide a pop-up message informing the user. Just having the spinning busy icon display and a message saying "trying to connect" is not sufficient. Apple will reject your app if you don't provide a message informing the user that they need a network connection.

7. False claims of a missing network On a related note, make sure you don't have any false positives in your network detection. There's a bug in the "reachability" functions provided by Apple. If you don't first try to perform a network connection but instead just do a reachability test, the code will always report the network is unavailable. Apple will reject your app if they discover you have this false positive case.

8. Political lampooning Don't make any jokes about political figures, past or present, in either your app or the description in iTunes. Apple will most-likely reject your app.

9. Ensure your app description is accurate Spend some time proof-reading your app description for iTunes. This description is the only information the reviewer is going to have about your app. Make sure there isn't anything ambiguous in the description. If there is room for misunderstanding a feature, you run the risk of the reviewer rejecting the app because they felt the app does not behave as described.

10. Keep your "what's new" descriptions brief Whenever you submit an update, Apple requires you to provide a description of what is new in the app. Related to the previous note above, try to be as clear and concise as possible. Don't go into too much detail describing what has changed, otherwise you introduce more opportunity for the reviewer to misunderstand what has changed. I've had an app rejected because the reviewer misunderstood what I said had changed in the app.

11. OS compatibility If you claim your app works with OS 2.0 and higher, you better make sure you test whether your app really does work on all the OS versions between 2.0 and the current one. The reviewer most-likely will! There are some anomalies in the behavior of certain functions across the different versions of the OS (for example, reachability code returns a slightly different set of flags under 2.0 vs. 2.2, UILabels don't respond to the Touch events under 2.1 and earlier, etc.). If the reviewer finds the app does not work properly with a certain version of the OS, the app will rightly be rejected. However, don't expect the reviewer to mention that they were testing using a different OS. That little detail is usually not mentioned in the rejection email, leading to the potential for lost time trying to find a bug while testing with a different OS than the reviewer. Again, test the app with every version you claim to support.

This is by no means an exhaustive list. It's just the things I've personally run into in my app submissions and is a laundry list of items I keep in the back of my mind whenever I'm developing a new app.

If you do find your app is rejected, the best advice I can give is try to remain calm. Remember there are thousands of other developers in your shoes. We feel your pain. It often feels unfair, and perhaps it is unfair at times. It can be a terribly frustrating experience, especially when you've done your best to follow every guideline Apple provides and you might be convinced Apple is wrong in their assessment of your app.

But, it's Apple's store. They can do whatever they want in the end and don't have to be fair. If you feel your app has been wrongfully rejected, the best you can do is be courteous and try to outline your position, quoting from whatever relevant Apple documentation applies. But, in the end, don't expect Apple to yield to your request, or in many cases, even acknowledge your request. Apple is generally very brief in their email responses and sometimes totally silent. The best bet for an approval is to implement a change based on Apple's reason for rejection and move on. Trying to win an argument because you feel you are right is not going to be productive.

And if you do get a rejection, add it to your list of things to avoid for the next app.

Tuesday, April 7, 2009

DevDiary: Artificial Life updates coming soon

I've been working on some changes recently to the Artificial Life iPhone app. Some of them have already been submitted to Apple and should be approved any day now.

The most recent submission includes support for saving the world state when the app exits along with having the protozoa grow in length as they attack others or eat. These two changes are in the pending update now.

The following describes some more upcoming changes that weren't ready in time for this latest app update, but will definitely be in the next (since they are working now):

I changed the graphics slightly - the creatures now are semitransparent and they pulse slightly, giving them a somewhat jelly fish look. It was mainly done as a test to see how practical it is to have all the creatures represented as bitmap images rather than just dots. It appears the graphics engine is pretty capable of keeping up - according to Instruments, I'm only using about 20% of the graphics power.



The main slowdown in the app is actually caused by the creatures' artificial intelligence routines. The slowdown is exponential in relation to the population. Each creature has to search through the list of all the creatures in the world when making decisions. So, 50 creatures means 2500 decisions. 100 creatures and the number jumps to 10,000. 300 creatures and it's 90,000. Obviously that's not an ideal way to process the AI.

For those interested, this issue is called the "nearest neighbor" problem. You can read about it on Wikipedia. It's a well studied computer science problem.

To address this speed issue, the world is now divided into a 9x9 grid and the creatures are put into one of 81 bins depending on their location. (Anything out of range of the 9x9 grid is put into the closest edge bin). For finding their nearest neighbor, a creature now only looks in the 3x3 grid area of its current location. This gives a significant boost in speed in the app. While there is still a noticeable slowdown when you reach the 300 protozoa maximum, the slowdown is much more tolerable.

I've also implemented a small particle system for "special effects" in the app. Now, when a protozoa gets killed by the sun, or is attacked by another protozoa, there will be some minor particle effects generated. You can see a sample here in this short video.






controller="true" loop="false" bgcolor="#000000" pluginspage='http://www.apple.com/quicktime/download/'>



And finally, the last change made was to have the protozoa's initial diameter be based on its age. So, when one is newly born, it is very small and will increase in size as its age increases. It reaches full size at at 40.

Again, I should mention the first two changes - saving the world state and protozoa growing in length - should appear in the iTunes App Store any day now. The remaining changes will most likely be submitted in a week or so.

All content copyright © 2009  Brian Stormont, unless otherwise noted.   All rights reserved.