Amazon Appstore Disappoints
Amazon is taking a bit of flak at the moment over the way its Android Appstore operates. The catalyst for this was a blog posting by Australian app developer Shifty Jelly revealing that, contrary to popular belief (belief informed by Amazon’s own Developer Agreement), Amazon does not make payments to the developers of apps it lists as Free App of the Day. The Developer Agreement requires that Amazon reimburses the developer with 20% of the list price for each app it gives away as a free download. However, in order to be listed as Free App of the Day, Amazon apparently requires the developer to agree to waive this part of the contract and to accept 0% instead.
To be clear, Amazon is not forcing the developer to give the app away for nothing, they can decline the offer, but this behaviour does have the faint whiff of a bait and switch and undermines one of the key reasons I highlighted previously for listing your apps with Amazon. Perhaps this is just another example of the old adage that if something sounds too good to be true, it probably is.
Shifty Jelly’s blog post lists additional complaints that echo other disgruntled developers. The approval time is only a minor annoyance for me. Some degree of delay is inevitable on a curated app store and Amazon’s approval time is comparable to Apple’s. Surrendering control of pricing has been controversial but it is clearly outlined when you sign-up. I was willing to go along with this because I assumed that Amazon’s goals would align with mine (we would both benefit from maximising the revenue from my apps).
More annoying is that Amazon will rewrite your app’s description. In most cases for me this has only involved tweaking a few words but in one instance the description was rewritten from scratch and I found the result pretty infantile. The issue extends beyond the description; the developer has no control over the formatting and content of the product page. It’s clear that some publishers are more equal than others because some apps get a rich treatment while most receive only the most basic listing. I enquired about how to get my page upgraded and didn’t really get an answer except to be told that Amazon doesn’t have the resources to provide the full treatment for all apps. On the plus side, at least when I contact Amazon I eventually get a response. There is no indication that there are any human beings involved in the operation of Google’s Android Market.
All of these complaints would be overlooked if the Amazon Appstore delivered impressive revenue for developers but at the moment it doesn’t. Part of this is due to only serving the US. We can reasonably expect that it will eventually expand to other countries where Amazon has a presence, though when this might happen is anyone’s guess. We can also expect to see a big push when Amazon unveils its own Android tablets. For now though Amazon’s offering to developers is underwhelming.
Update (3rd August 2011): Shifty Jelly is having problems getting Amazon to remove the app:

I hope this is just a misunderstanding. It’s terrible PR for Amazon.
Embedding AdMob Adverts in Android ListViews
Whilst working on StackAnywhere (a new Android client for Stack Overflow and other Stack Exchange websites), I was trying to figure out how best to incorporate AdMob adverts in the UI so that I could make the app free to download. The stumbling block was that, with some space already taken up by the tabbed navigation, the additional space occupied by the adverts tended to make the user interface very cramped with little room for content. This was particularly problematic in landscape orientation since the adverts are the exact same dimensions as in portrait mode which means they take up proportionally more room vertically whilst wasting space horizontally.
Since most of StackAnywhere’s activities feature ListViews, I eventually hit on the idea of embedding the adverts in the lists. This is not an entirely original idea, there are other apps that do something similar, but it has the advantage of displaying the advert prominently while also allowing the user to scroll it off screen and out of their way.
Implementing this solution is reasonably straightforward although there are a couple of minor pitfalls to avoid. The decorator pattern is an ideal approach to use since it allows you to add adverts to an existing list adapter without having to modify the code for that adapter. My naive first attempt fell foul of a ClassCastException when adding the AdView to the list, and I also had some focus issues to resolve. The code below is a simplified version of that used in StackAnywhere. The implementation simply adds one advert to the top of the list. You could easily modify this to show more adverts if you wish. For example, you could show an advert after every 10 items. The code assumes that you are using the new Google AdMob SDK (version 4.0.4 in this instance), rather than the old AdMob SDK.
import android.database.DataSetObserver; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.BaseAdapter; import com.google.ads.AdRequest; import com.google.ads.AdSize; import com.google.ads.AdView; /** * List adapter decorator that inserts adverts into the list. * @author Daniel Dyer */ public class AdvertisingAdapter extends BaseAdapter { private static final String ADMOB_PUBLISHER_ID = "YOUR_ADMOB_ID_HERE"; private final Activity activity; private final BaseAdapter delegate; public AdvertisingAdapter(Activity activity, BaseAdapter delegate) { this.activity = activity; this.delegate = delegate; delegate.registerDataSetObserver(new DataSetObserver() { @Override public void onChanged() { notifyDataSetChanged(); } @Override public void onInvalidated() { notifyDataSetInvalidated(); } }); } public int getCount() { return delegate.getCount() + 1; } public Object getItem(int i) { return delegate.getItem(i - 1); } public long getItemId(int i) { return delegate.getItemId(i - 1); } public View getView(int position, View convertView, ViewGroup parent) { if (position == 0) { if (convertView instanceof AdView) { return convertView; } else { AdView adView = new AdView(activity, AdSize.BANNER, ADMOB_PUBLISHER_ID); // Disable focus for sub-views of the AdView to avoid problems with // trackpad navigation of the list. for (int i = 0; i < adView.getChildCount(); i++) { adView.getChildAt(i).setFocusable(false); } adView.setFocusable(false); // Default layout params have to be converted to ListView compatible // params otherwise there will be a ClassCastException. float density = activity.getResources().getDisplayMetrics().density; int height = Math.round(AdSize.BANNER.getHeight() * density); AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.FILL_PARENT, height); adView.setLayoutParams(params); adView.loadAd(new AdRequest()); return adView; } } else { return delegate.getView(position - 1, convertView, parent); } } @Override public int getViewTypeCount() { return delegate.getViewTypeCount() + 1; } @Override public int getItemViewType(int position) { return position == 0 ? delegate.getViewTypeCount() : delegate.getItemViewType(position - 1); } @Override public boolean areAllItemsEnabled() { return false; } @Override public boolean isEnabled(int position) { return position != 0 && delegate.isEnabled(position - 1); } }
Scrolling Tabs in Android
Perhaps this is obvious but it wasn’t immediately clear to me so maybe it’s worth documenting for the benefit of future Google searchers. If you use a TabActivity in an Android application you can probably fit four or maybe five tabs on a standard screen in portrait orientation before things become too cramped. To display more tabs than this and still be able to read the text on each it would be ideal to have a scrolling tab widget like many UI toolkits do. But how can you do this in an Android app?
Reading the patchy Android API documentation is rarely an illuminating experience at the best of times and it doesn’t help in this instance either because the possibility of scrolling tabs is not even mentioned in the entries for TabHost and TabWidget. In the absence of any better ideas you might speculatively attempt to wrap the TabWidget in a ScrollView. Don’t bother, it won’t do anything, ScrollView only provides vertical scrolling.
If, like me, you thought that ScrollView was the last word in scrolling Android widgets, you may have failed to notice android.widget.HorizontalScrollView. The name fails to conceal what this class is about. It’s the solution to your non-scrolling tab woes.
Wrap your TabWidget with a HorizontalScrollView and the tab set will be able to expand beyond the width of the screen and the user can drag the tabs left and right as required:
<?xml version="1.0" encoding="utf-8"?> <TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <HorizontalScrollView android:layout_width="fill_parent" android:layout_height="wrap_content" android:fillViewport="true" android:scrollbars="none"> <TabWidget android:id="@android:id/tabs" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </HorizontalScrollView> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout> </TabHost>
Set android:fillViewport to true to ensure that the tabs stretch the full width like they would without a scroller and set android:scrollbars to none to avoid having a scrollbar displayed between the tabs and the content. The scrollable tabs will be rendered with faded edges on the right and/or left depending on which direction you can scroll (see image above).
Thoughts on Amazon’s Android App Store
I’ve posted some thoughts about Amazon’s upcoming Android Appstore over at the Rectangular Blog. There has been a lot of discussion about Amazon requiring control over app pricing, most of it focusing on the potential negatives for developers. However, one thing that has been overlooked is that if Amazon decides to give your app away for free it might actually be the most lucrative way for your app to be distributed:
The developer will be paid 70% of the purchase price of the app, or 20% of the list price, whichever is greater.
The important thing about this last point is that the developer gets paid even if the app is given away for free. At first glance, having your paid app given away for free and only getting 20% of the list price for each user, rather than 70%, seems like a bad deal but in reality it could be lucrative for the developer. On the Android Market, free apps typically get somewhere in the region of 50 times as many downloads as paid apps. If that ratio translates to Amazon’s store then instead of selling 200 copies at $2 and getting $280 out of it, the same developer could see 10,000 copies given away free and yet earn $4,000.
Not everyone will be a winner, but with Amazon’s other obvious advantages, this new store could potentially be the first alternative marketplace to seriously challenge Google’s Android Market.
Adjusting the Opacity of an Android Bitmap
This took me a lot longer to figure out than it should have done. I’m documenting it here in case it’s useful for somebody else searching for a similar solution.
If you’re displaying the Bitmap in an ImageView, you can probably use the ImageView.setAlpha(int) method. However, if the ImageView is accesed via RemoteViews, as is the case when updating a widget, you won’t be able to invoke this method (if you try to call it via RemoteViews.setInt(int, String, int) you’ll get an exception telling you as much).
After much searching I was unable to find a widget-friendly mechanism for adjusting an ImageView‘s transparency, or any obvious way of manipulating a Bitmap‘s alpha channel.
Eventually I stumbled upon Kevin Dion’s excellent answer to a different but related question on StackOverflow. From this I was able to figure out that I needed to use the DST_IN Porter-Duff mode to modify the alpha channel.
/** * @param bitmap The source bitmap. * @param opacity a value between 0 (completely transparent) and 255 (completely * opaque). * @return The opacity-adjusted bitmap. If the source bitmap is mutable it will be * adjusted and returned, otherwise a new bitmap is created. */ private Bitmap adjustOpacity(Bitmap bitmap, int opacity) { Bitmap mutableBitmap = bitmap.isMutable() ? bitmap : bitmap.copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(mutableBitmap); int colour = (opacity & 0xFF) << 24; canvas.drawColor(colour, PorterDuff.Mode.DST_IN); return mutableBitmap; }
Analysing Android Application Sales
One of the reasons that I’ve chosen to get involved in mobile app development in recent months is because I wanted to experiment with the economics of selling software. The new world of mobile app stores provides an ideal opportunity to do just that. For an eye-watering 30% of your revenue, Google and Apple will provide all of the distribution and payment-processing infrastructure so that you can concentrate on making and marketing software. Given that I’m already experienced with Java and that Google puts fewer barriers in the way of developers than Apple, Android was the obvious platform choice (I have since also started exploring iOS development, perhaps I’ll talk about that in a later post).
I have already related details of my initial forays into Android app development, the results of which were my first two (very basic) paid-for applications. The Beep Test app has sold a decent number of units considering its modest functionality and that it was only written as a “my first app” introduction to Android. We’re talking hundreds rather than thousands but that comfortably beats the “one genuine non-refunded sale” target that I set for it. The second app on the other hand has been, by all financial metrics at least, a total failure.
Try again. Fail again. Fail better.
Fortunately I was not banking on getting rich from these simple applications. They were a means to an end, an Android familiarisation exercise, phase 1 in a longer term plan that has more than one possible successful outcome.
Since then I’ve released a couple more apps, though much of my time has been occupied generating real revenue for Rectangular Software through paid development work. Like the vast majority of Android developers, I’m still awaiting the promised riches of the smartphone revolution. I have no sense of entitlement in this respect. I don’t expect to make a year’s salary from an app that took two weeks to write. A more realistic goal is two weeks’ salary for two weeks’ work, acknowledging that an app will not generate all of its revenue in the first month – it may take a year or more to make a decent return. Of course, like most apps, it may never make a decent return.
If you can make a modest amount from one mobile app, you can make 20x a modest amount from twenty mobile apps. Applying the arithmetic of unspecific numbers, 20x a modest amount equals a reasonable amount. The logic is sound but the approach only scales so far. In the absence of a genuine hit among your 20 apps, substantial wealth may not be forthcoming. Adding more unfocused development effort is unlikely to be sufficient.
At this point I’ve written a page of text and not gotten to my point. My point is that, to stand a chance of financial success, the average mobile developer needs to figure out how to maximise the return on their development effort. Marketing, economics, and all the other non-technical stuff. The goal is to make sure that you leave no money on the table. You’ve written the software, sell it.
You can’t control what you can’t measure
I’m not the person to tell you how to increase your sales (maybe you should start with Andy Brice’s series of articles about promoting your software). I’ve already established that I am a very long way from making a sustainable income from mobile development. You should also know, if you haven’t deduced it already, that I am not an economist. As for marketing, I make that up as I go along. I do however have an extensive collection of quotations ready to deploy as the situation demands. Enter Benjamin Disraeli:
“As a general rule, the most successful man in life is the man who has the best information.”
When optimising computer software better information leads to better decisions and better outcomes. The same is true when optimising for financial performance. It’s why insider trading is so profitable (and so illegal).
If you were selling software from your website rather than somebody else’s app store, you would use Google Analytics or similar to record and digest the information that you needed to optimise sales. There are some partial equivalents in the Android world such as in-app analytics, which only tell you what happens to your software after it’s been bought, but a complete picture will not be possible until Google starts revealing more Android Market data to developers. For now we have to work with what we’ve got. What we’ve got is some fairly detailed information hidden away in Google Checkout. Again, it won’t tell you about the people who didn’t buy your apps but it does give some insight into who is buying.
You can download this information in CSV format. When I looked for a tool to process this data, I didn’t find anything. So I wrote my own. This has helped me to identify some interesting trends.
Perhaps most informative is where I’m making sales. The top five countries are all (predominately) English-speaking countries. This is to be expected since my software is currently only available in English. These five countries account for 94.8% of all my Android revenue. Take a close look at the figures for the UK and France. These are two neighbouring Western European countries with almost identical population levels and similar levels of wealth. Assuming similar levels of Android adoption (which seems reasonable but I don’t have any figures to back up this assumption), it should be possible for me to make as much money from France as from the UK. Instead I make over 50 times as much in the UK. This leads to the obvious hypothesis that I am leaving money on the table by not translating my applications into French. Germany, an even bigger market, is similarly under-represented. This is easily remedied – there are online services that will do the necessary translations for somewhere in the region of $20 – $50 per app for a single language.
The second interesting thing about this data is that the figures for the UK and the US are broadly similar despite the latter having five times the population. In this case the discrepancy cannot be due to language. The data is from the last 3 months or so. In the last few weeks I have seen a sustained jump in US sales and a corresponding dip in UK sales. I can only speculate that this is related to the recent Android Market change to display app prices in the user’s local currency. My figures for October to date are 52.5% for the US and only 25.5% for the UK. Australia is also slightly up.
There are several other ways to digest the Google Checkout data. The above chart shows how revenue is distributed throughout the day. Here you can see that my most productive period of the day is between 4pm and 6pm UK time. Filtering the orders by country shows that 4pm – 5pm generates more money from UK users than any other time of the day, which I find surprising, whereas 5pm to 6pm (12pm – 1pm Eastern / 9am – 10am Pacific) is peak time for US users.
The point in the article where thinly-veiled product placement becomes blatant advertisement
Still reading? OK, that tool I mentioned for analysing Google Checkout data is my fourth Android application, Appmonger, which is on the Android Market for the bargain introductory price of £1.99. It automatically fetches the Google Checkout CSV data and generates various charts, which you can share via e-mail and social media. You can find out more about it by following the link or by watching the poorly shot video on the right. Appmonger has already been through a couple of iterations to incorporate feedback from early adopters and I hope to extend the functionality in future releases, so feel free to make suggestions.
Android LVL Obfuscation Pitfalls
The recently-introduced Android License Verification Library (LVL) survived a disappointingly short time in the wild before somebody figured out how to circumvent its protection. Google responded to this development by stating that it was the lack of obfuscation that had made the crack so straightforward and then followed up with further advice on achieving security through obscurity, effectively acknowledging that there is no robust way of doing licence verification that can’t be bypassed.
Unfortunately, the LVL is pretty much the only option for protecting apps sold via the Android Market (other app stores have their own protection mechanisms). The choice for Android developers is mediocre protection or no protection at all (Google apparently intends to withdraw its previous copy protection mechanism). You can thwart the most casual Android pirates and make things harder for the determined but that’s about as good as it gets.
Obfuscating LVL-protected Apps with Proguard
Assuming that you choose to add the LVL to your app, you’ll no doubt want to follow Google’s advice and obfuscate your code, probably using Proguard. If you do, you might hit a couple of problems that prevent the LVL from working properly.
I added the LVL source to my application and built it as a single entity but it is also possible to incorporate the LVL as a library project.
Disable Aggressive Overloading
The first problem I encountered was a limitation in the Dalvik VM. Unlike the JVM, it does not (did not?) permit static fields of different types to have the same name. In normal Java development this situation never arises but Proguard has an option to aggressively overload names to make decompilation more difficult. For Android development this option should not be used otherwise you will get VerifyErrors.
Avoid Renaming the ILicensingService Intent
The checkAccess method of the LVL’s LicenseChecker class binds to the licensing service as follows:
boolean bindResult = mContext.bindService( new Intent(ILicensingService.class.getName()), this, // ServiceConnection. Context.BIND_AUTO_CREATE);
The problem with calling ILicensingService.class.getName() is that, after obfuscation, the class has a different name and therefore the wrong intent is created. This will show up in the log as an error with the message “Could not bind to service” and the licence check will always fail.
You could fix this by modifying the Proguard configuration to avoid renaming the ILicensingService interface or, even more straightforwardly, you could just modify the code in LicenseChecker and hard-code the appropriate action:
boolean bindResult = mContext.bindService( new Intent("com.android.vending.licensing.ILicensingService", this, // ServiceConnection. Context.BIND_AUTO_CREATE);
Building Two Versions of the Same Android App
There are good reasons to want to build two versions of the same Android application. The most common scenario is to produce a free demo/reduced-functionality version of a non-free app. You could achieve this by maintaining two separate source trees but the duplication would make most developers wince. So the question is how to build two differing apps without duplicating the code and resources?
Building Android Apps with Custom Ant Scripts
The answer is Ant. Maybe it’s also possible with Eclipse. I doubt it but I don’t know and I don’t care to find out. As I mentioned previously, the Android Ant build system is fairly painless to use. If you want to customise it though you’ll have to do a fair bit of digging as it doesn’t appear to be documented anywhere. The first place to look is the <sdk_dir>/platforms/<target_dir>/templates/android_rules.xml file that is used by the build.xml that the Android tools generate for you. This will give you a good idea of the various stages of the build but if you want to experiment with the Android Ant tasks you’ll have to look at the source to see what attributes they support (making sure that the version you are looking at is the same as the version you are using). The AaptExecLoopTask is just a simple wrapper around the aapt tool but the ApkBuilderTask is non-trivial.
The outline of a minimal Ant build for an Android app looks something like this:
- Generate the R.java file from the resources using the the exec task and the aapt tool with the -J option.
- Compile all of the app source, including the class generated in step 1.
- Use the dx tool to convert the Java bytecode into a .dex (Dalvik executable) file.
- Use the aapt tool (either via the exec task or via the provided AaptExecLoopTask) to package the resources.
- Build the .apk package using the ApkBuilderTask.
- If you are building a release package rather than a debug package, sign the .apk file using the signjar task.
- Use exec to run the zipalign tool on the .apk file.
More advanced applications will involve additional steps, such as running the aidl tool.
Once you have the outline of your build in place, you can start to customise it using your standard issue Ant prowess.
Different Resources for Different Versions
In my scenario I don’t mind shipping all of the code with both versions of the application. The difference is just the initial Activity that each uses. It doesn’t add much bloat to the package and the code is useless without the full set of resources so there is no danger of somebody hacking the demo version into a fully functioning version. In other words, I don’t need to worry about excluding certain classes from one version or the other.
I do however only want to include a subset of the resources in the demo version. The way I have achieved this is to replace the default res directory with three directories: res-common, res-demo and res-full. I then use the Ant copy task to construct the res directory from the appropriate pair of directories prior to building.
Different Manifests
Because I want to invoke different activities, I need to define the AndroidManifest.xml differently for each version. My first idea was to just have two different files with different names but I discovered that the Android tools get upset if the file is not called AndroidManifest.xml, even if you explicitly specify which file to use. This just means that I have to copy the chosen manifest so that it has the correct name.
The biggest problem with building two versions from the same tree is resolving conflicts in the application package name. Each Android application must have a unique application package. This is specified in the manifest. You can just use the same package name for both versions but users will run into problems if they ever try to install both versions at the same time. They will likely end up not being able to use either. Despite the drawbacks, this method seems to be widely used judging by the number of apps in the Android Market that warn users to uninstall the demo version first.
So we’ll just change the package name in one of the manifests then? Yeah, that would be nice. The problem is that the package name specified in the manifest is the package into which the R class is generated. If the two versions of your application have their R classes in different packages then common classes will not compile for both versions.
Android 2.1 introduces the --custom-package option for the aapt tool which allows you to over-ride where R.java will be generated. So the idea is to set the application package differently in one of the manifests but then to use this option to make sure that R.java is still in the same place as in the other version. I tried this and it resolved my compile problems but there were resource problems at runtime. I didn’t fully investigate what was wrong because I found another approach that appears to work.
The aapt tool also has the --rename-manifest-package option. Leaving the application package the same in both manifests and then using this option at step 4 above, I was able to generate a working demo version and full version from the same source tree and have them both functional when installed at the same time.
The whole custom Ant build exercise was not nearly as straightforward as I would have liked, mostly due to lack of documentation, but it is at least a working solution to the problem. Another, probably more recommended, way of achieving something similar would be to use library projects.
Android Adventures
Late to get involved as ever, I’ve been developing with Android for the last couple of weeks. On the whole it has been a positive experience (thanks to Richard for pointing me in the right direction with my queries).
My first impression is “what the hell were Sun doing for the last decade?” Android shows what J2ME/JavaME could have been. A proper Java environment for mobile devices (the fact that it uses Dalvik is largely inconsequential). J2ME may have first arrived when mobile phones were far less capable than they are today but, like Java in general in the last few years, it never really progressed. Worse still, with its numerous device profiles and JSRs it betrayed the “Write Once, Run Anywhere” philosophy that is so fundamental to Java. With J2ME it’s more like “right once, wrong somewhere else”. You don’t really write Java at all, you write some horribly restricted, out-dated subset of it. That’s not to say that J2ME was not a success of sorts despite its numerous short-comings. I don’t have the figures to hand but I believe it’s true to say there are vastly more J2ME-enabled devices in circulation than iOS and Android devices combined.
Pain-Free Mobile Development
Android is a complete reboot of Java for mobile devices. No longer do you have to worry about which devices support floating-point arithmetic or how to do anything useful with an anaemic UI toolkit. No more making do with Vectors and without generics, or wondering what happened to half the useful classes and methods that you take for granted with JavaSE.
Of course, nothing’s perfect. The API documentation, while generally pretty good, is not quite up to Sun’s high standard, the UI toolkit is either slightly buggy or slightly unintuitive (probably both), and a couple of things I wanted to achieve were less straightforward than I might have hoped. These however are minor gripes. The resources framework seems to do a pretty good job of dealing with the differences in platform versions and screen sizes. As Sun no doubt learned from J2ME, there is a real risk of fragmentation when different manufacturers want to deliver different capabilities. So far it seems under control.
The documentation favours Eclipse throughout but fortunately it’s pretty painless to develop Android code without it. The Ant tools are fine and, if necessary, it seems flexible enough that I could move things around to employ more sophisticated builds. I’m not sure how easy it is to use TestNG in preference to JUnit when using the Android tools. At the very least it would be possible to just bypass the Android test project stuff and test your Java classes the way you normally would. Given that Cedric was heavily involved in Android it’s mildly surprising that TestNG support is not included out-of-the-box.
Android Market
Yesterday, after paying the $25 registration fee, I pushed my first two (pretty basic) apps to the Android Market. This is an area where Google has room for improvement. It’s all a bit simple at the moment. As I’m in the UK my prices are set in pounds. There is no way to specify different prices for different currencies, nor does the market automatically convert prices for users. That means that, as a user, you are presented with application prices in at least four different currencies (US dollars, Euros, Sterling and Yen) and have to do the necessary conversions yourself. I would like to be able to specify that if my application costs £1.99 in the UK, then it should be $2.99 in the US and €2.49 in the Eurozone.
The other thing you can’t do is respond to user comments. Somebody left a comment that my app did not work properly for them. Unfortunately they provided no details to enable me to track down the problem. Worse, they wrongly assumed that the functionality was simply missing and stated as much. As the only comment on the app so far, that will likely dissuade other people from buying.
The good thing about the Market is that you have the freedom to upload pretty much whatever you want and to have it immediately available to users. Unlike the iPhone, you are not subject to the whims of an inconsistently applied approval process.
My First Apps
So what did I make? My first app is a simple utility for performing a multi-stage fitness test (a.k.a “Beep Test” or “Bleep Test”). It’s a one-button UI that emits the necessary beeps at the appropriate intervals and displays status information such as current speed and cumulative distance.
My second app is an educational game called Flagpole. All you have to do is identify flags. You get one point for each correct answer and it’s game over when you get one wrong. It’s divided into challenges of increasing difficulty, so you might start with South America, for which there are only 14 flags to identify. Eventually you’d progress to “The Whole World”, which would require you to correctly identify 232 flags without making any mistakes.
I intend to release further, more sophisticated applications in the coming weeks. These apps are sold via Rectangular Software, which is the new home for my commercial software development activities (contract/freelance development and now applications). My open source projects remain here at uncommons.org.


