Posts Tagged ‘android’

State of the Android app union

I thought it might be useful to report on how all my apps are doing on the Android Market, in terms of downloads and active users. Hopefully this information will be helpful for someone looking to write their own app, or wondering what their chances of success are.

It’s worth mentioning that I’ve never marketed any of my apps, except for a short “house ad” campaign I did in Chord Reader to promote KeepScore. App development is a hobby for me, so I’ve found it more interesting to just release my apps into the wild and see whether they sink or swim. I’ve relied almost solely on the Android Market and word-of-mouth to build up my user base.

This may have worked better when I first started writing apps, which was around March of 2010, when Android was still in its infancy. Back then, the Android Market had less than 20,000 total apps, so you could get a decent amount of visibility by simply publishing your app. Today, the Android Market boasts over 250,000 apps, so it’s much easier to get lost in the crowd.

My Personality Type

For instance, when I released my second app, My Personality Type, in March of 2010, it was able to gain 3,000 downloads in a single week without any advertising. Most likely this is just because personality tests are fun, mine was free, and it was also only the second or third of its kind to be released on the Market. The app was later removed due to a takedown request from psychologist David Keirsey, so there’s no way of knowing if it could have maintained that stellar rate of growth, but it’s pretty impressive nonetheless. (Yes, Pokédroid was not my first run-in with copyright issues. I tried to work out a licensing agreement with Dr. Keirsey, but eventually he stopped responding to my emails.)

By comparison, my most recent app, KeepScore, has grown much more slowly. KeepScore only broke 1,000 downloads very recently, even though it’s been on the Market for almost two months, and despite the fact that I promoted it through house ads (where it got 8,091 impressions and 243 clicks). I’m guessing this is because the Android Market is already saturated with tons of score-keeping apps, so KeepScore doesn’t even show up in the top 10 in a search for “score,” “score keeper”, etc. Even though it’s the best of the bunch, it’s hard to stand out over apps that have been around longer, with more downloads and more reviews.

In general, though, I’ve found that the best determiners of an app’s success in the Market are 1) search engine optimization, 2) constant updates, and 3) short, easily understandable app summaries. I’ll describe each one in turn.

Search results for "score keeper."

Search engine optimization is important for the obvious reasons. Most users are going to discover your app by searching for some problem they’re trying to solve – “save battery,” “calorie counter,” “weather widget,” etc. Try to think of what need your app fulfills, and be sure to include those terms in your Android Market description. I always just add a section at the end where I write “seo:” and then list a bunch of terms related to the app.

Constant updating might not be something you’d imagine would contribute much to an app’s success, but anyone who’s worked in Android development long enough can testify to this. Back in the old days, this technique was enormously effective, because the Android Market app had a prominent “Just In” page that simply listed the most recently released or updated apps. For this reason, you’d often see spam apps (such as “Sexy Hot Girl #12”) releasing a new version every day, perhaps under the imaginative title of “version-20100614”. Anybody could just change a string, release a new version of their app, and watch the number of downloads spike.

Google seems to have cracked down on this practice since then, and the new Market app doesn’t even include a “Just In” page. Instead we now have “Top New Paid,” “Top New Free,” and “Trending,” which seem relatively free of spam. But updating from time to time can still be a boon to your app’s success. Users love getting updates, and when the updates stop rolling in, they tend to lose interest in your app and uninstall it. Go long enough without any updates, and you may even start hemorrhaging users. (We’ll see an example of this later.)

Search results for "logcat."

And finally, short, easily understandable app summaries are a crucial part of promoting your app through the Market. I believe most users will decide whether or not to install your app based on a glance at the search results, which means the icon and the name are key. The description, the reviews, and even the star rating are of secondary importance, in my opinion. (The star rating is almost meaningless, because all halfway decent apps will have at least 4 stars.)

So when you design your app, you need to ask yourself: 1) Is the icon attractive, and does it hint at the app’s functionality? and 2) Is the name simple, and does it effectively communicate what the app does? For illustration, I’ll point out that aLogcat beats out my own app, CatLog, by this measure. CatLog has a cute icon (which many users have complimented me on!), but I’ll admit it requires a little bit of extra mental effort to figure out what the app does. CatLog still has fewer downloads than aLogcat.

All of these are just tips based on my own personal experience, which means they’re mostly hunches and guesswork. Make of them what you will. But of course, the Android Market also provides us with some wonderful reporting tools, so I have some hard data to offer as well!

So without further ado, here’s the current state of all my apps in Android Market, in the order I wrote them. I report the total number of downloads, as well as the number of active users (i.e. installed copies of the app). Each graph shows the change in active users since January of 2011, which is when Google started providing these detailed statistics. You can ignore sudden spikes in the graph – I think those are bugs in the reporting tool.

Japanese Name Converter

Released March 2010
39,144 downloads
7,464 active users (19%)

My first app, which I never updated beyond version 1.0, is still fairly popular. Its popularity also seems to be pretty constant, since I imagine most people download it, get a kick out of it, and then uninstall it soon afterwards. That doesn’t bother me much, though, since this was basically just a “Hello World” app for me.

My Personality Type

Released March 2010
3,286 downloads
287 active users (8%)

As I noted above, My Personality Type only spent one week on the Android Market, due to a takedown notice from the author of the test. (I actually based this app on an assignment from one of my undergraduate computer science classes, so I didn’t know the test was under copyright.) Given it’s been off the Market for a year, I’m kind of amazed the app still has any active users at all.

Pokédroid

Released April 2010
451,492 downloads
125,576 active users (27%)


This chart still breaks my heart a little. The sudden bump in March corresponds to when I released the update for Pokémon Black/White, and the dip in June, of course, corresponds to when I removed the app from the Android Market due to a takedown notice from The Pokémon Company. At its height, it had 170,000 active users.

Offline Browser

Released June 2010
17,032 downloads
2,820 active users (16 %)

I wrote this app while I was attending the 2010 NAACL conference, because I wanted to be able to browse the conference proceedings, which were distributed as raw HTML and PDF files, on my phone. This app didn’t hold much interest for me afterwards, so I never looked back. (By the way, here’s my paper from that conference.)

App Tracker

Released July 2010
3,183 downloads
344 active users (10%)

With only 3,000 downloads over the course of a full year, App Tracker is a certified dud. As I was developing it, I actually believed it was going to be my breakthrough app, and that the revenue from the Premium version would allow me to quit my day job and do app development full-time. Unfortunately, the graveyard of lost ambitions is littered with such failures, and App Tracker never really got off the ground.

CatLog

Released August 2010
24,614 downloads
10,330 active users (41%)

Ah, CatLog – the phoenix that rose from the ashes of App Tracker. After App Tracker’s failure, I refashioned its log-reading component into a straight-up Logcat app, and now CatLog perseveres as my third-most popular app. In fact, it’s probably the app I’m most proud of after Pokédroid.

Chord Reader

Released October 2010
30,533 downloads
11,607 active users (38 %)

It’s a shame I never found this app very compelling to work on, because it’s actually my most popular app on the Market (now that Pokédroid is gone). I’m not really sure why it started bleeding users in late June, but if I had to guess, I’d say it’s because I haven’t updated it much over the past year. Like I mentioned above, users tend to lose interest when you don’t update, and I think that’s especially true when there are much-needed features they keep clamoring for. (In my case, users keep asking for an auto-scroll feature and setlists.)

KeepScore

Released June 2011
1,207 downloads
873 active users (72 %)

I would really, really like to see this app succeed more than it has. My goal with KeepScore was to create the end-all be-all best score keeper for Android, and in a sense I’ve failed simply because the app still doesn’t have much visibility in the Android Market. As I mentioned above, it doesn’t even come up in the top 10 in searches for “score” or “score keeper,” meaning that most users will probably never find it, and instead settle for an inferior app. I’m not sure what to do, though, other than wait for it to gain more downloads and ratings. I have no control over Google’s search rankings.

So that concludes my app-by-app report. But because it’s a lot of data to take in individually, I also created some charts comparing all the apps side by side:

Total downloads and active users

Total downloads and active users

This chart shows the total number of downloads and active users (as of today) per app. Obviously Pokédroid is an order of magnitude more popular than my other apps, so I also created a log-based version of the same chart:

Total downloads and active users (log)

Total downloads and active users (log)

Here it’s a little easier to compare the non-Pokédroid apps. Chord Reader, CatLog, and Japanese Name Converter are all reasonably successful, whereas Offline Browser and App Tracker are less so. With KeepScore and My Personality Type, it’s difficult to compare, because they’ve spent much less time on the Market than the others. So I also went ahead and created a chart showing the total number of downloads and active users divided by the approximate number of days spent in the Market:

Downloads and active users per day spent in Market

Here it’s easier to see which apps were more popular on a day-to-day basis. The most surprising finding is that My Personality Type apparently had more potential than I thought. Even though it was only on the Market for one week, it looks like it could have been as popular as Pokédroid if it hadn’t been taken down. (Funny that my most successful apps are also the ones that get targeted for copyright infringement! Take note, kids: you walk a fine line when you reuse other people’s content.)

And here’s the same graph with a log-based y-axis:

Downloads and active users per day spent in Market (log)

So there you have it. Of the apps I still have on the Market, Chord Reader, Japanese Name Converter, and CatLog are the most popular. Offline Browser and KeepScore take up the second tier, whereas App Tracker is an unmitigated failure. (I couldn’t even show App Tracker’s active users per day on this chart, because the value was less than 1, meaning the log value actually went negative.)

I wish I could say there was a way to know in advance whether an app is going to be a hit or a miss, but I think the Android Market is just too unpredictable for that. You really can’t know how popular an app is going to be until you put it out there. For me, though, this is the excitement of app development. More so than with any other kind of software development, you get immediate confirmation of whether or not people find your app useful. So if nothing else, it’s fun to throw darts at the board and see what sticks.

Update on Pokédroid

I’m still getting lots of comments and emails about Pokédroid, which was taken down from the Android Market last month due to a DMCA notice from The Pokémon Company. (See these posts.) Most of my blog traffic still seems to come from Pokédroid-related searches, which is not surprising given the more limited appeal of my other apps. (What – you guys aren’t as excited about my system log reader?) So I thought I’d do a little round-up of the commentary on Pokédroid and get everyone up to speed on where the app currently stands.

Tim Oliver, the developer of iPokédex, informs us that the app removal process for iPhone Pokédexes has now begun. The timing seems about right, given that the TPC lawyer I spoke to said that Apple’s process takes a bit longer than Google’s. Tim and other iOS developers are in talks with TPC right now, but if their experience is anything like mine, we can expect iPhone apps to be removed shortly.

None of this should be surprising, given that TPC is now venturing into territory previously occupied by fan developers. The recently released Pokédex 3D app for 3DS, although not a true strategy guide like Pokédroid, makes it clear why TPC would start to view fan-made apps as unwanted competition. The rhythm-action Pokémon games coming to Android and iPhone make this point even less ambiguously.

Liam Pomfret, the head of Bulbagarden, has been my most helpful contact point throughout this whole process, and he has an interesting editorial on Bulbanews laying out TPC’s case for taking down Pokédex apps. It’s very persuasive, and if nothing else it splashes some cold water on the impulsively negative fan reaction. He points out that all fan-made media (including Bulbagarden itself) is in violation of TPC’s copyrights, and so TPC is within its legal rights to selectively allow or disallow whatever content it wants. It’s debatable whether or not taking down Pokédex apps is actually in TPC’s own self-interest (I’ve argued it’s not), but the legal case is pretty difficult to dispute.

And in fact, even if Pokédex developers like myself did have a good case, we probably wouldn’t be doing ourselves any favors by taking it up in court. Recently there was the case of the Miles Davis afficionado who ended up paying $30,000 for a copyrighted photo he used in a tribute album. This was without any admission of guilt, and despite the fact that his lawyers thought they would have had a decent case if they had actually pursued it. The $30,000 settlement was simply the least expensive option available to him.

Now this may surprise you, but Pokédroid, as a hobby app, is not worth $30,000 to me. And if you think I could just get 30,000 of my 150,000 active users to each chip in a buck and cover my legal expenses, then you’ve never developed a mobile app before.

This is why I’ve rejected requests to open-source Pokédroid. As Liam pointed out above, open-source licenses still presume ownership of the IP content in the code, which means I’d be making myself a legal target just by publishing the code base. Even though I’m a die-hard Linux user who loves open-source, I have to admit that this isn’t really the time or place for it.

Anyway, I’ve been on good terms with TPC so far, so I have no incentive to do anything to try and spite them. Everyone I’ve spoken to at TPC has been very courteous and respectful towards me, and they’ve taken obvious care to explain their point of view and avoid any misunderstandings. They’ve even mentioned reading my blog posts (hullo out there!), so they’ve obviously got their finger on the pulse of the fanbase, and aren’t acting hastily or thoughtlessly.

My hope right now is just that they will offer to license Pokédroid or rebrand it as an official Pokémon app. In my ideal world, they would also let me open-source it, possibly in exchange for my help with the rebranding process. That way, I could gracefully hand the reins over to other fan developers (who would probably be more hardcore Pokémaniacs than me, and thus more diligent contributors), but the app would still remain an officially licensed product. TPC could continue to disallow unofficial apps on the Android Market if they wanted, but anybody would be able to contribute to the official app. The same community involvement that made Bulbapedia strong could make Pokédroid the best Pokémon resource on any mobile platform.

Admittedly, this scenario is a little starry-eyed. But even if TPC wasn’t keen on the open-source idea, I still have 19,000 lines of code that could save them a ton of time if they decided to build their own Android Pokédex app. Hopefully they’ll take me up on my offer, so that Pokédroid can get back in the Market, and back in the hands of the fans who find it so useful.

A small improvement for KeepScore

This week at the pub I took KeepScore for its first test run in a little game of four-person cribbage. It got high marks from my friends, who agreed that KeepScore was better than the other Android scoring apps we had tried. (But of course my friends would say that.) Still, I also received some useful criticism that informed an update I wrote later in the week.

It seems the biggest problem was that the bolded history items were too small, and therefore difficult to read. In light of this, I considered just upping the text size on all the history items, but then I realized: the only history item you’re usually interested in is the most recent one. When you’re trying to tap the button 7 times to add 7 points, you want to verify that you’ve actually added 7, instead of 6 or 8. But after you’ve given the player his/her points, you tend to stop paying attention until the next time you need to add points.

Before

After

So instead of the bold text, I decided to use little “badges” over the numbers (or “blibbets,” as we called them at my old company). I think they’re pretty neat looking, and they also make it dead simple to tell how many points you’ve added. After 10 seconds of inactivity, the badges disappear and move over to the history column instead. This has the added benefit of drawing a clear distinction between the modifiable and unmodifiable parts of the history.

Something else I noticed was that, in the long-press popup, the buttons were also too small and too hard to read. So I simply enlarged the text and gave the buttons more space relative to the EditText (which no one at the table used anyway).

Before

After

Both of these problems stemmed from the fact that I had only tested the app with the phone held in my hand, rather than flat on a table within reach of multiple people – which is how it’s actually used. Held in my hand, all the text on the screen is perfectly easy to read, but in the middle of a dimly-lit bar table, it’s another story.

In the end, this turned out to be one of those slap-yourself-on-the-forehead-it’s-so-obvious kinds of problems that you can only really discover through usability testing.

If imitation is flattery, then CatLog has a secret admirer

When I first released CatLog last summer, my goal was to create a replacement for the dominant Logcat app, aLogcat. (“Logcat,” if you don’t know, is the somewhat cryptic name for Android’s system log, which is invoked by typing adb logcat in a shell. In a delicious pun, the Android team also lets you invoke it with adb lolcat.)

Around that time, I was on vacation in France, and I didn’t have access to a computer with an Android development environment. So when a problem came up in one of my apps, I tried using aLogcat instead. But aLogcat just wasn’t cutting it for me. It was clunky, difficult to read, and lacking in decent search/filter functionality. Just scrolling through the logs to try to pick out my own app from the others was a classic victory of the haystack over the needle.

When I got back to Seattle I was still unemployed, which meant I had a lot of time to burn. So I sat down at my laptop, and less than 24 hours of frenzied coding later, I had busted out my first version of CatLog. It didn’t have a lot of the cool features I ended up adding in future updates, but it would still beat aLogcat in a beauty contest:

aLogcat

CatLog

CatLog’s look and feel is inspired by Jeff Sharkey’s Colored Logcat script, which is a great way to view logs because the tags are color-coded, and because everything is organized into neat columns. CatLog is also easier to search than aLogcat, because the search bar is right on top of the screen, and it filters automatically as you type.

As far as additional features go, CatLog also records logs in the background, sends logs as text or attachments, and auto-scrolls when you’re at the bottom of the screen. aLogcat, by contrast, only lets you search through a cumbersome dialog box, it can only send logs as text, and it forces you to pause and unpause if you want to control the scrolling. It does the job, but in terms of usability, it leaves a lot to be desired. (Edit: aLogcat now supports auto-scrolling.)

Despite these shortcomings, aLogcat is still more popular than CatLog, and it comes up first in a search for “logcat”. That doesn’t bother me much, though, because I know I’ve written the best Logcat app for Android. You only have to play with each app for a few seconds to see the huge difference in presentation, features, and usability. aLogcat was first on the Android Market, and that’s probably what it owes much of its success to. But given enough time, I’m sure CatLog will pull ahead.

I got a little surprise a few weeks ago, though, when I noticed a new Logcat app on the market: LogViewer. I wondered if someone had finally improved upon CatLog – I love a good challenge! But as I played around with the app, I became more and more puzzled. LogViewer has far fewer features than CatLog, but the presentation is a dead-on imitation. Like CatLog, it has a cat in the icon. Like CatLog, it arranges everything in columns. And like CatLog, the search bar is on top of the screen, with “expand” and “clear” buttons to the side.

CatLog

LogViewer

I’m not angry at the developer for taking design cues from CatLog. After all, I modeled CatLog after Jeff Sharkey’s script, and the two look very similar (although his is a Python script and mine is an app). Also, I don’t really believe there’s anything wrong with borrowing someone else’s ideas to improve on them – human civilization is built off of this practice.

But what confuses me about LogViewer is that it doesn’t even improve upon CatLog in any way. It has far fewer features – no process id, no color-coded tags, no widget, no ability to delete saved logs, no ability to send logs as attachments, etc. And the only thing it adds is a big ad banner at the bottom, along with some text saying “Copyright 2011 ukzzang. All Rights Reserved.” (Nice use of the screen real estate, by the way. Heaven forbid someone should try to copy his app!)

I guess I just don’t see the point. Why would you go to the trouble of writing a Logcat app if it doesn’t improve on the competition? I suppose you can slap an ad banner on it and make a couple of cents that way, but having written an ad-supported app myself (Chord Reader), I can attest that ad revenue tends to be chump change unless your app is on par with Angry Birds in terms of popularity. (Chord Reader has over 11,000 active users, but it’s only earned about $60 since I released it 9 months ago. I’m thinking of just taking the ads out, since it’s not really worth it to ugly up the app.)

CatLog with menus

LogViewer with menus

My only hunch is that, since the author of LogViewer has written an “App Lock”-style app, he’s already had to deal with reading Logcat output (which is the way these sorts of apps work), so he figured he might as well write a Logcat app as well. And if that’s his reasoning, then fine. CatLog is still the best Logcat app on the Market, but if any of my users think to themselves, “Gee, I like CatLog, but I wish it had more ads,” well, they now have another option. I can’t argue against consumer choice, even though this particular choice seems a little silly to me.

There is one area, though, where I have to give LogViewer credit: its performance is pretty damn good. When I first tested it out, I noticed that its scrolling was much faster and smoother than CatLog’s. This made me realize that CatLog had some room for improvement in the speed department. So, spurred by this upstart new rival, I went back to the CatLog codebase and made some long-overdue optimizations that brought it up to roughly the same speed as its competitor. These changes are available starting in version 1.1.6.

So in this small way, at least, I tip my hat to CatLog’s secret admirer.

On Pokédroid’s Removal

I posted the short version of this story to Pokédroid’s page on the Android Market:

Pokédroid will be removed from the Android Market shortly.

A legal representative of The Pokémon Company has responded to me via email. He has confirmed that TPC would like Pokédroid, and all similar apps, to be removed from the Android Market.

TPC’s stance is apparently that they don’t want any Pokédex or Pokémon-related apps at all for the Android platform. They feel that such apps infringe upon their copyrights and compete with the print versions of their strategy guides.

While I disagree with this decision, which I believe is detrimental to the interests of both Pokémon fans and TPC alike, I have decided to comply with their request. Thus, henceforth I will cease all development on Pokédroid and remove it from the Android Market.

When this page goes down, please visit my site (www.nolanlawson.com) for more information. I will _not_ host the APK there.

It has been a pleasure to serve the Pokémon community. I hope you had as much fun using Pokédroid as I had writing it.

– Nolan

Going through this whole process of being targeted for copyright infringement, trying to fight it with argument and persuasion, and eventually being defeated has been a strange odyssey for me. I’ve learned a lot about how IP enforcement actually works in the real world, and I’ve lost a little bit of my naïveté. I’ve also lost the hundreds of hours of work I put into Pokédroid, and I’ve let down my 400,000+ users. It’s been humbling, to say the least.

When Pokédroid Donate was first taken down by Google, along with a dozen other Pokémon apps, I was not very surprised. I figured that either Nintendo was trying to crack down on paid Pokémon apps, or they were targeting blatant copyright infringements like wallpapers, games, and soundboards. I assumed Pokédex apps, which are really just strategy guides, would be safe.

Google sent me a copy of the original DMCA takedown notice from The Pokémon Company (which is an affiliate of Nintendo). But the fact that it listed my app, Khiry Arnold’s “Poké Pal”, and Stephen Willey’s “Pokédex” among a dozen-odd wallpaper and soundboard apps seemed to me like a mistake. Anyway, the notice itself looked very hastily thrown together – it was obviously the result of an entry form on Google’s website, and some of the app names were even misspelled. (“Pokédroid” was listed as “Pokédex,” although they spelled my name right.)

So when I started trying to get in contact with The Pokémon Company to rectify the problem, I figured the stakes were low. The free version of Pokédroid was still on the Market (probably due to an oversight from Google), and I couldn’t imagine TPC would want it removed. So I felt like I was mostly fighting for Khiry and Stephen, whose apps had been forcibly removed by Google while mine was overlooked. I had the most users out of the three of us, and therefore the most clout, so it seemed the responsibility had fallen on my shoulders to clear up the misunderstanding. Sort of like I was representing the Pokédex App Developers Union or something.

I honestly thought that the content of the apps was uncontroversial, and that as soon as I could get in touch with someone at TPC they would rescind the takedown immediately. I mean, there are plenty of fansites that offer the exact same content as Pokédroid, and nobody seems interested in taking those down, so why would Android apps be any different?

I did worry, though, that TPC might frown down upon monetizing our apps. So to be on the safe side, I deprecated Pokédroid Donate, which had only distinguished itself by including the “shiny” sprites anyway, and added the shinies to the free version. Now I felt Pokédroid was scrubbed clean of anything even slightly questionable – it was a free (and ad-free) app, with no content that couldn’t be found at a half-dozen popular fansites, and to boot I had gotten written permission from all the people who had given me their data (mostly Marriland, but there were a few other FAQ authors as well). A perfect representative of our little Union.

So like a fresh-faced Jimmy Stewart going to Washington, I penned the following polite email to TPC:

Hello,

I’m the developer of the Android Pokédex app “Pokédroid.” A few days ago I received an email from Google explaining that my app was to be removed from the Android Market due to a DMCA takedown notice from The Pokémon Company (see attached). Several apps are mentioned in the notice, including “Pokédroid” and other similar Pokédex-style strategy guide apps.

Could you please explain why The Pokémon Company is targeting these particular apps? My understanding was that they fall under the category of “fair use,” in that they function as strategy guides (i.e. research) and are not directly competing media. Furthermore, there are plenty of iPhone apps and web sites (such as Bulbapedia and Serebii.net) that offer the same content, so I’m perplexed as to why Android apps were singled out.

To be fair, many of the apps mentioned in the notice are clearly copyright-infringing – e.g. games, wallpapers, and soundboards. I can understand your desire to have these apps removed. But strategy guide apps, to me, do not appear to fall into the same category.

If this was indeed a mistake, please notify Google so that they can restore these apps to the Market. Hundreds of thousands of Pokémon fans use these apps as a resource when playing your wonderful games, so I’m sure that having them back in the Market would make those fans very happy.

If not, then I will be happy to keep “Pokédroid” off the Android Market, per your wishes.

Thank you for your time.

Sincerely,
Nolan Lawson

For two weeks I received no response. I sent multiple emails and even left a voice message at TPC’s company phone number. Then finally, after finding the phone number of one of their lawyers and leaving a message there, I received this email:

Nolan:

I’m the position omitted for The Pokémon Company International, Inc. I’ve been given to understand that you’re trying to reach someone at TPCi to try to get some information about Pokédroid and Pokédroid Extras and more specifically about why we asked Google to have them removed from the Android Market. Since you’ve reached out to us and been reasonable about this, I wanted to take a moment to write you back and give you some insight into our thinking.

By way of background, and sorry but I do have to get legalistic for a minute, you have told us that you think your apps are fair use. Unfortunately that’s not the case. There are lots of websites that purport to give information about what is and isn’t fair use, but I find one good summary is from the US Copyright Office at http://www.copyright.gov/fls/fl102.html. Under US law all uses of a copyrighted intellectual property by anyone other than the owner of the IP are presumptively illegal, and it’s up to the person using the IP to demonstrate that their uses are permitted. So fair use isn’t an affirmative permission to do something, it’s a defense to an action that is otherwise illegal, which means that it’s your obligation to prove that you should be allowed to make apps based on Pokémon and unless you can prove that you’ve got a legal right to do that, your apps are infringing.

One thing that’s not commonly-understood by fan communities is that the owners of the Pokémon IP have the right to decide not to put this IP into the Android Market or anywhere else. Put another way: if we don’t create our own Android Market app, that’s not an invitation to other people to fill what they perceive as a gap, it’s a decision that they have to respect. You may think that Pokédroid and Pokédroid Extras don’t compete with our print strategy guides like the one for sale at Amazon (http://www.amazon.com/Pokemon-Black-Version-White-Official/dp/0307890600/ref=pd_sim_b_1) or the one available for free at our website www.pokemon.com. But as you can see from the Copyright Office link that’s not the only criterion in the test, and even if it was I’d have to say we don’t agree, and in any event we have chosen not to allow any Android Market apps for Pokémon.

I hope this helps you understand the situation and our position. I can’t ask that you agree with me, although I’d hope that after you’ve read this you’ll know that we didn’t act capriciously or lightly. But I do have to ask that you take Pokédroid and Pokédroid Extras out of the Android Market and not upload them anywhere else. Could you confirm to me by return email that you’ll do that?

I hope that you’ll find another way to contribute to the Android app community. Given how skilled you are at app development, I don’t think it will take long.

Name omitted

Needless to say, I was shocked. Were they serious? Why would Nintendo target apps that do the exact same thing as a half-dozen fansites, which they’ve never attacked before? (To be fair, TPC has attacked fansites in the past, but only for small portions of the content they publish.)

I’m not arguing that Nintendo doesn’t have the right to act in this way. They can do pretty much whatever they want with their own intellectual property. IP law, taken to its logical conclusion, means that they can prohibit me from whistling the Pokémon theme song as I walk down the street, for instance. This is kind of a silly example, but I’m just pointing out that determining IP infringement is not clear-cut. For this reason, most companies choose to act judiciously when they enforce IP, because too much enforcement could be dismissed by the courts or cause a backlash from fans. They have to find a middle ground.

And in the case of Pokédroid, IP enforcement seemed to me like a clear lose-lose for Nintendo. If there are no mobile Pokédex apps, then that seriously reduces the value of every Pokémon game that Nintendo publishes. Gamers love strategy guides because they increase their enjoyment of the games. Imagine if a resource like Bulbapedia were taken down – so much of the fun of playing Pokémon games would be sucked out of them! And it’s the same with mobile apps. Undoubtedly, taking down mobile Pokédex apps would cause fewer people to buy Pokémon games in the future, and Nintendo/TPC would suffer. They might sell more $10 strategy guides, but they’d sell fewer $30 games. They’d lose money.

Alternatively, TPC may be thinking of releasing their own app, which would explain why they’d want to eliminate competitors. But even that reduces quality for consumers. Undoubtedly TPC would release one monolithic app with a limited feature set, and if some fans wanted different features or a different presentation, then tough luck. With a lot of competing apps, though, choice is increased for consumers and everyone’s more likely to get what they want. This was already happening with “Poké Pal,” which was an app geared more towards serious, competitive players than my own. It was a free app, and it excelled in its own way, while Pokédroid excelled in other ways. Consumers could download one, the other, or both. Everybody wins.

I sort of doubt that TPC or Nintendo will release their own app, though. If anything, the author of this email seems to be suggesting that Nintendo is deliberately leaving a “gap” in the Android Market, and that I need to respect their decision to keep it that way. Similar to when Nintendo shut down that fan-made Zelda movie, or when Square Enix shut down the fan-made Chrono Trigger sequel, no replacement is intended. IP enforcement can be somewhat mindless in its destruction. I like to picture it as a grumpy old coot, waving his cane at those pesky neighbor kids when they’re having too much fun on his front lawn.

So at this point, reading the email, I kind of glumly realized that the game was lost. There was probably no way to convince TPC to take back the original DMCA notice. I felt a little frustrated that I had provoked them in the first place, since, if I had just done nothing, Pokédroid might have stayed on the Market awhile longer while they shuffled their paperwork around. But by buzzing in his ear, I had invited the giant to swat me down. It seemed there was nothing left for me to do but bow to their demands.

I wanted a little more clarification about their motivations, though, and I also hoped I could make an emotional appeal for them to reconsider. So I wrote the following:

Hi Name omitted,

Thank you so much for your response. I really appreciate you taking time out of your day to help explain these kinds of issues to me, especially since (as a layman) legal matters are obviously not my area of expertise.

I think I have a better understanding now of what is meant by “fair use.” I understand that TPCi has complete legal right to their intellectual property, and that therefore any third-party use of that IP is considered to be infringement until proven otherwise. Also, I’m perfectly willing to take down Pokédroid and Pokédroid Extras from the Android Market and not upload them anywhere else, per your request. In case you were wondering, the reason it’s still on the Market is because Google did not take it down themselves, probably due to an oversight on their part. I was confused about the situation, and so I left it up until I could get word back from your company.

I have to admit, though, that I’m surprised by TPCi’s decision, and I’m hoping you could tell me a little more about the motivations behind it. Specifically, why Android apps? To my knowledge there are about a dozen Pokédex apps for iPhone, and many of those are even paid apps. There are also popular web sites such as Bulbapedia and Serebii.net that offer similar content. Does TPCi plan on removing those sites and apps as well, or is there a specific reason that Android apps are being focused on? I’m not asking this in order to play “gotcha,” or to make some kind of “two wrongs make a right” argument; I’m honestly just trying to understand TPCi’s position on this issue. After having put several hundred hours into developing this app, I think it’s reasonable for me to want to know a little more about your company’s decision before shutting it down for good.

Also, I realize it’s sort of a “children’s letters to Santa Claus” argument that doesn’t carry much legal weight, but I do hope you’ll read some of the reviews for Pokédroid: https://market.android.com/details?id=com.nolanlawson.pokedex. Ever since I mentioned that the app might be taken down, there have been lots of comments expressing sadness and frustration over the news. Pokédroid has over 420,000 users, and it honestly saddens me to think about taking away what is obviously such a valuable resource for them.

Thank you again for your legal advice and courtesy towards me. I hope you know that, as a longtime Pokémon fan, I offer TPCi the same courtesy and will bow to any of its wishes regarding its own IP. But I also hope that TPCi will consider alternative solutions to this problem.

Nolan Lawson

The next day, I received the following response:

Nolan:

Not a problem to respond, and thanks also to you for your reply. It’s certainly not unreasonable for you to ask for a bit more background. Unfortunately and as you can probably imagine I can’t really discuss the specifics of other situations or other apps, except to note that we’ve sent a fair number of notices recently, will be sending some more, and if there are people out there who aren’t as great about this as you have been they may receive a slightly different form of communication from me. But you shouldn’t feel singled-out at all, and it’s not just Android apps. Apple has a slightly different approach to these kinds of things than Google does and so their process takes a bit longer to operate, for example.

Thanks again for your reply and for your understanding here.

Name omitted

He’s obviously not letting on very much here. He isn’t recognizing the contradiction in targeting Pokédroid while leaving Bulbapedia and Serebii up, and he doesn’t really explain why TPC has suddenly decided to go after mobile apps. The evasiveness of his answer was kind of a letdown for me, although I can understand why the legal team would want to keep mum about such things.

He’s also being very diplomatic about all this, which I appreciate. But I do detect a sort of “good cop” routine going on here (“as great as you,” “how skilled you are”), with the thinly veiled threat of the “bad cop” waiting in the other room in case I don’t play ball (“a slightly different form of communication”). He’s left little room for debate – the impetus is clearly on me to either follow directions or face the consequences. No response to my heartfelt Miracle on 34th Street reference, and no response to my suggestion to seek alternative solutions. I suppose I naïvely thought he might be touched by all the user comments, but it seems not.

So that’s pretty much the whole score. Nintendo: 1; me: 0. I wish I had the courage to fight this battle, but I searched my soul and came up empty. It just doesn’t seem worth it to me to stick out my neck and try to stop Nintendo from attacking their own customers. Also, I could do more harm than good if I continue this line of argument with them. I was worried enough that, when I mentioned Bulbapedia and Serebii, the lawyer might respond, “Hmm, shut down Bulbapedia and Serebii? Not a bad idea.” At a time when TPC’s legal team is clearly on the rampage, the last thing I need to do is draw attention to myself or anybody else. It’s like the T-Rex in Jurassic Park – stand still, and he might just leave you alone.

On a personal level, though, I’m deeply disappointed with this whole result. Although I haven’t been the most dedicated Pokémon fan (I tried but couldn’t really get into the newer games), I’ve poured my heart and soul into Pokédroid. In terms of Android app development, it’s my magnum opus. I put deliberate care into every inch of the interface, every function call in the code, every UI design decision.

Pokédroid might not look pretty (I don’t have an eye for design), but there are little touches that improve the experience in ways the user might not even perceive. For instance, the buttons’ “onClick” methods load in the background, so that the UI doesn’t slow down. The voice search uses string edit distance to try to find approximate matches. The moves and locations use dropdown lists, because I wanted to keep the interface clean and uncluttered. The “advanced search” uses optimized SQL indexes for the fastest possible searching.

All of these are things I put time and effort into, to please my 400,000+ users. I’ve spent hundreds of hours trying to improve Pokédroid, which, even with all my donations considered, was done at below a minimum-wage rate. And yet, I don’t regret any of it, because (and I’m going to get a little mushy here) I know Pokédroid has brought a little ray of sunshine to so many people’s lives. As of today, it’s in the top 50 free apps in the “Entertainment” category, it has a perfect 5-star rating, and it has hundreds of comments from satisfied users, all expressing how much joy, delight, and amusement Pokédroid has brought to them.

To say that this gives me the warm and fuzzies would be an understatement. In fact, Pokédroid was a great psychological boon to me, as I left the safety of college and entered into full “quarter-life crisis” mode. I wondered: What was my contribution to the world? What had I done to justify my existence? With Pokédroid, I could always point to it and say, “Right there. 400,000 people who got a kick out of my app. 400,000 people who reminisced about the cartoon show, looked up stats for their competitive team, or just giggled at the silly text-to-speech feature. 400,000 smiles. That’s what I’ve done for the world.”

I’d like to close this article with some of my favorite reviews from the Android Market. The fans are the reason I kept working at Pokédroid, and they’re the ones who gave me feedback and criticisms that helped me fix bugs, retool the user experience, and correct glaring flaws. I want to thank them for giving me a really cool project to work on for the past year, and for giving me lots of insights into application development. Thank you all.

  • this is the most amazing app i have ever seen, ive always dreamed of having a dex on my phone. i love you man<3 – Jonesyruless
  • Now i can trump my kids with my mad pokemon knowledge – Lisa
  • Kids love the talking pokedroid. Its a must have for any Pokemon fan! 5 stars – Ash
  • Is super great and I would buy the donate version but my mom said no haha but as soon as im off her plan I will if I still play Pokemon – Steven
  • I am donating asap. And I NEVER donate. Not to the homeless, friends in need of a buck for gas, never! – Philippe
  • Love it! Showed it to my office mate and we started getting all nostalgic – Lumpy
  • Why I bought Android – Nick
  • My 5 yo daughter loves this. – Eric
  • This app has amazing info, and the voice is hilarious! – Sean
  • I was out in the wild and a pokemon appeared. My friend asked me what it was but i didnt know. So i took out my Pokédroid and identified it! – Dal
  • I absolutely LOVE this app! My friends have become jealous and they want an android phone JUST for this app! Genius! ^_^ – Abigail
  • Incredible! This app has single handedly justified my Droid purchase. Please add egg moves! – |3reak
  • Thank you Thank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank youThank – Wonton
  • This is well cool. My friend’s all want android phone’s just for this app. :-) – Max
  • My daughter loves this app. Just like a pokedex from the cartoons! – Jessica
  • My son loves this keeps him occupied for ages – Lorna
  • Wow, this is simply awesome, no words to describe.. it just feels very special for some reason!.. thank you! =] – Cloud
  • I bought a Droid for this app! I love it. Keep up the good work. – Timothy
  • A real Pokedex? I love the future. – Craig
  • Would give it 1000 stars if I could, what an elaborately designed app. Thank you for sharing for free! – Zach
  • I use this pokedex on the regular. Helps with all versions. I am in college and I still use it to settle disputes. Great app. A+ – Dietrich
  • Fantastic! Work at gamestop and this app has gotten me some sales haha def donating. Game specifucations would be nice tho – Victoriano
  • I cant imagine playing the games w/out this app. I use it whenever i am in battle to help me choose what pokemon to use. Cant wait for b and w update. – Cameron
  • Being a programmer it takes alot to get 5 stars but he earned this – Jonathan
  • Awesome! My kid loves the black & white update. Really useful, and free! – Paul
  • Good resource! Great for keeping up with my 7 year old daughter ^^ – Midd
  • This is the best Pokédex app that is out there. It makes me feel like I’m part of the show. – Kohaku
  • Since the moment I downloaded this months ago I’ve loved it. The latest update makes the interface lightning fast and pretty much flawless. – Daenym
  • Thanks for B/W update! Scrolling is PERFECT now!!! Thank you for voluntarily working to satisfy such a prissy bunch of people! – Sidney
  • Perfect app for a beginner or veteran. Now I can stop getting on the PC to look up new Pokemon I haven’t heard of! – Frogmum
  • Best app on my phone – Tom
  • Childhood dream come true… enough said – Kevin
  • Not only is it a great app but the customer support is tops as well – Christopher
  • This has got to be the funnest/greatest app ever!! Absolutely in love w/ it! – Denise
  • So convenient! Considering that bulbapedia is down half the time! – Kathy
  • Best thing ever – Daniel
  • I love this app! Easy reference to help me train my pokémon in the best way possible! Plus getting to freak out my friends w/ random pokémon cries! – Bryan
  • 10 out of 10!!!!!! This is by far the most comprehensive pokedex I have ever seen. Fast, easy to use. Settings for different versions (Great for when I play Black and by daughter plays Platinum). Consistent updates. If you have not already downloaded this and the extras bundle… then you are dumber then a Magikarp! – Wayne

Nintendo used Takedown! It’s super effective!

UPDATE: I was in error when I wrote this post. Apparently, all Pokémon-related Android apps were cited in the DMCA takedown notice, not just paid ones. Every Pokédex app has been removed by Google except for Pokédroid and Pokédex Companion. It’s not clear why.


Today I received an email from Google explaining that Pokédroid Donate was removed from the Android Market due to a DMCA takedown notice from The Pokémon Company (a subsidiary of Nintendo). The email begins:

This is a notification that the application, Pokédroid (Donate) with package ID com.nolanlawson.pokedex.donate has been removed from Android Market due to a violation of the Developer Content Policy. Please review the Content Policies and Business and Program Policies before you create or upload additional applications. Note that repeated violations may result in a suspension of your Android Market Publisher account.

Mine wasn’t the only app removed – in total, about a dozen Pokémon-related apps were cited in the DMCA notice. These include “Poké Pal Donate,” “Pokédex,” and “Who’s That Pokémon?”, among others. Apparently only paid apps were targeted; the free versions of Pokédroid and Poké Pal, for instance, were not mentioned.

In response, I made an update to Pokédroid and added the following text at the beginning:

Google has removed Pokédroid Donate from the Android Market, due to a copyright claim by The Pokémon Company. In fact, all paid Pokédex apps (Poké Pal Donate, Pokédex) were removed. Free apps were not affected.

In response, I am adding the shiny sprites to Pokédroid for free. To the people who already paid for Pokédroid Donate, I apologize for the sudden bait-and-switch. So you won’t feel like you wasted your money, I am hereby donating all proceeds from the month of May (about $150) to Doctors Without Borders.

I disagree strongly with what The Pokémon Company is doing. It hurts Pokémon fans the most, because they are the ones who benefit from having a variety of apps on the Market. Also, the apps don’t even threaten Nintendo’s bottom line, because they’re strategy guides and not competing games. However, there isn’t much I can do, because Nintendo is a powerful company and I’m just one guy.

Please keep in mind that your donations sustain my interest in developing this app. You can still donate via PayPal at my website: nolanlawson.com/donate.

Thank you for using Pokédroid, and stay tuned for more updates! I have some very cool features in the works, and I will try to get them to you despite these legal hurdles.

– Nolan

And for the “pics or it didn’t happen” crowd:

Mostly what I’m doing here is damage control. Nintendo has backed me into a corner, and I’m too sheepish to fight back. So I’m just doing what I assume they want me to do – make Pokédroid 100% pro bono. But since this will irritate people who already bought Pokédroid Donate (and who are therefore my best and most enthusiastic users), I’m also doing the donation as a show of good faith.

This is my own, somewhat cowardly reaction to the news. I’m not sure what other app developers will do. I’m in contact with Stephen Willey, the developer of Pokédex, and Khiry Arnold, the developer of Poké Pal, but neither seems to have decided what their strategy will be. Admittedly, we’re all in a bad predicament. I feel especially sorry for Khiry, because he had just started doing a freemium model like me, and his app was really spectacular in terms of depth and detail.

Of course, none of these deleted apps really violate fair use, insofar as they might compete with Nintendo’s core product. There’s nothing about a strategy guide or a silly “Who’s that Pokémon?” quiz that diminishes anybody’s desire to go out and buy the next Pokémon game. If anything, these apps actually increase interest in the product, because they add value for current Nintendo customers and encourage them to learn more about Pokémon. And if nothing else, they’re free advertising.

But this is the tragedy of current copyright law. Presumably, Nintendo took out its copyrights to protect against blatant infringements, like game piracy. But here instead it’s using its IP to attack the Pokémon fan-developer community, at great cost to its customers and, indirectly, to itself. To be fair, though, none of this is really Nintendo’s fault. They’re just operating within the mad logic of a broken system.

People who know me personally know that I am very skeptical of copyright law and intellectual property in general. I tend to view patents and copyrights as government-enforced monopolies that drive up prices, reduce choices for consumers, waste money on litigation, and stifle more innovation than they spur. For your own interest, and to challenge any assumptions you may have about IP, I recommend reading these articles: here,
here, and here.

Your Froyo users are an army of testers

The error reports page in the Android Market Developer Console is one of my favorite additions to Android 2.2 (Froyo):

It gives you a nice, organized view of the stacktraces reported by users when your app has crashed or frozen. This is great because, for the most part, users are not particularly eloquent when describing bugs. Usually they just say something like “Doesn’t work anymore, please fix.” And when they do give more information, it’s often tantalizingly incomplete: “When I go to Settings I get a force close.”

Stacktraces, on the other hand, don’t beat around the bush:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=0, result=-1, data=Intent { (has extras) }} to activity {com.nolanlawson.pokedex/com.nolanlawson.pokedex.PokedexActivity}: java.lang.NullPointerException
      at android.app.ActivityThread.deliverResults(ActivityThread.java:3515)
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3557)
      at android.app.ActivityThread.access$2800(ActivityThread.java:125)
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2063)
      at android.os.Handler.dispatchMessage(Handler.java:99)
      at android.os.Looper.loop(Looper.java:123)
      at android.app.ActivityThread.main(ActivityThread.java:4627)
      at java.lang.reflect.Method.invokeNative(Native Method)
      at java.lang.reflect.Method.invoke(Method.java:521)
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
      at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NullPointerException
      at com.nolanlawson.pokedex.VoiceSearcher.guessMonsterUsingDirectLookup(VoiceSearcher.java:132)
      at com.nolanlawson.pokedex.PokedexActivity.receiveVoiceResults(PokedexActivity.java:1206)
      at com.nolanlawson.pokedex.PokedexActivity.onActivityResult(PokedexActivity.java:1178)
      at android.app.Activity.dispatchActivityResult(Activity.java:3890)
      at android.app.ActivityThread.deliverResults(ActivityThread.java:3511)
 ... 11 more

NullPointerException. Bam. Go to the line in the code, figure out what’s null, and fix it. Nothing clarifies a bug like a good old-fashioned stacktrace.

Before Android 2.2, you had to get this kind of information from users by having them download a Logcat app and go through all the tedious effort of recording the log, reproducing the bug, and sending the stacktrace to you. Users can hardly be blamed for a lack of enthusiasm about this process. When you’re trying to complete a task and an app force-closes on you, the last thing you think is “Oh goody! I should tell the developer about this!”

Oh goody!

So Froyo’s error reporting framework is a godsend. From the user’s point of view, it’s a lot less painful to just click the “Report” button than to go through the rigamarole of downloading a Logcat app and emailing the developer. (Although, there is a splendid little Logcat app out there.) And from the developer’s point of view, your users have become an army of testers – and good ones, at that! They give you stacktraces and everything!

Plus, even when the stacktrace is not enough information, the additional comments from users are sometimes enough to squash the bug. For instance, I recently had an ArrayIndexOutOfBoundsException that was reported by almost a hundred Pokédroid users after the release of version 1.4.4. Try as I might, though, I couldn’t reproduce it. Then I noticed the user comments:

  • 셋팅 클릭시 프로그램 종료됨
  • Every time I open settings it shuts it self down. Galaxy ACE
  • se cierra al entrar en “Settings”
  • 렉 너무걸린다
  • När man ska gå in på inställningar så hänger programet sig
  • Happens every time I go to the settings
  • whenever I go to settings, the program crashes
  • I has updated this app and now when i want to change settings that not working! I mean i cant change settings! :-( sorry about my bad english :-(
  • It crashes while I try to enter the settings
  • trying to open settings. always happens. samsung galaxy s. android 2.2
  • when click on settings freeze
  • Telkens als ik naar settings wil gaan dan flipt ie
  • i was trying to go to the settings-screen… crashes whenever i try it…
  • Opened settings

Hmm… there sure are a lot of non-English comments here. So I set my phone to French and, aha! It turned out the bug only occurred if your phone’s language was set to something other than English. The bug was fixed and I shipped out 1.4.5 that same day. (Another great thing about the Android Market – no review process!)

When you have an app with a lot of downloads, though (like Pokédroid, which just hit 250,000), you start seeing some strange little bugs:

java.lang.NullPointerException
     at com.lge.media.SprintMultimedia.isStreaming(SprintMultimedia.java:27)
     at android.media.MediaPlayer.setDataSource(MediaPlayer.java:738)

Caused by: android.database.sqlite.SQLiteDatabaseCorruptException: database disk image is malformed
     at android.database.sqlite.SQLiteQuery.native_fill_window(Native Method)

java.lang.NullPointerException
     at com.motorola.android.widget.TextViewHelper.drawCursorHalo(TextViewHelper.java:306)
     at android.widget.TextView.onDraw(TextView.java:4175)
     at android.view.View.draw(View.java:6742)

Caused by: java.io.FileNotFoundException: res/drawable-hdpi/ic_dialog_alert.png
     at android.content.res.AssetManager.openNonAssetNative(Native Method)

Most of these just aren’t worth the effort to fix. For instance, they might only be reported by one or two users, and reflect situations that you, as a developer, don’t have a lot of control over (“database disk image is malformed”?). Others may be bugs in proprietary builds of Android, like the Motorola and Sprint bugs above. Obviously, I’m not going to go out and buy every flavor of Android phone just to test a few stray bugs.

If you’re lucky, you may also run into the Bigfoot of Android bugs:

java.lang.RuntimeException: Unable to get provider com.nolanlawson.pokedex.PokedexContentProvider: java.lang.ClassNotFoundException: com.nolanlawson.pokedex.PokedexContentProvider in loader dalvik.system.PathClassLoader[/mnt/asec/com.nolanlawson.pokedex-1/pkg.apk]
     at android.app.ActivityThread.installProvider(ActivityThread.java:4969)
     at android.app.ActivityThread.installContentProviders(ActivityThread.java:4696)
     at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4652)
     at android.app.ActivityThread.access$3000(ActivityThread.java:140)
     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2225)
     at android.os.Handler.dispatchMessage(Handler.java:99)
     at android.os.Looper.loop(Looper.java:143)
     at android.app.ActivityThread.main(ActivityThread.java:5097)
     at java.lang.reflect.Method.invokeNative(Native Method)
     at java.lang.reflect.Method.invoke(Method.java:521)
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
     at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassNotFoundException: com.nolanlawson.pokedex.PokedexContentProvider in loader dalvik.system.PathClassLoader[/mnt/asec/com.nolanlawson.pokedex-1/pkg.apk]
     at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
     at android.app.ActivityThread.installProvider(ActivityThread.java:4954)
... 12 more

I want to believe.

I call this the Bigfoot Bug because, if you Google it, you will find a lot of puzzled developers saying that they’ve only ever seen this bug reported in the Android Market, and they can’t reproduce it themselves. I mean, “ClassNotFoundException”? The class is right there! I was stumped by this bug myself, until I saw one developer suggest:

AFAICT, the installation process sometimes leaves the app in a corrupt state leading to weird errors like this.

So apparently, this bug is just one of those unavoidable parts of life, like sitting through red lights or having the sushi fall apart when you dip it in the soy sauce. You just have to put up with it.

Still, if you can manage to not get overwhelmed by the sheer number of reported bugs (Pokédroid has gotten over 500), and if you can prioritize them based on how many users they affect, the Froyo error reports can be an invaluable tool in making your app more stable. For instance, I had a layout-related bug a few months ago that I could not reproduce. It was reported by enough users, though, that I finally decided to rewrite that bit of the code and do some long-overdue optimizations. I haven’t seen the bug since.

Why it’s still your bug, even when it’s not

In the previous post, I talked about a workaround for a bug that occurs when integrating with the Facebook Android app. It brings up an interesting question: when software A integrates with software B, and software B has a bug, whose responsibility is it to fix it?

Intuitively, you might answer B. “It’s B’s fault. The developer of A can wash his/her hands of the whole matter and go to bed with a clean conscience.” Justice prevails, right?

But I disagree. In my opinion, the responsibility falls on whomever the user chooses to blame. Because when it comes down to it, the user does not care whose bug it is. They just want someone to fix it, or else heads will roll.

Case in point: the Facebook ACTION_SEND bug. To recap, the ACTION_SEND Intent is used to send arbitrary text from one app to another. Many apps answer the call – Facebook, Gmail, Twitter, Yammer – any app that may be interested in the text. Intuitively, Facebook should let you share the text as a status update, like Twitter and Yammer do, but instead they stubbornly interpret it as a URL. If it’s not a URL, then it barfs up an error.

In my own apps, I could have just used the ACTION_SEND Intent as-is. Let Facebook clean up their own mess – my hands are clean. But obviously, because I’m one man and because Facebook is Facebook, users would assume the bug is mine. So here’s what would have happened if I had chosen to ignore it: I’d get a ton of emails and Android Market comments saying, “Facebook doesn’t work” or “4 stars until you fix Facebook.”

Maybe then I would have smugly responded, “It’s Facebook’s bug, not mine.” Or, if the comments persisted, I might have added a popup saying, “Facebook doesn’t work correctly, due to a bug in their app. Please avoid Facebook.” But as we know from a previous post, users don’t read anything. So I would have continued getting angry comments and emails, and I would just have to respond to each one with a triumphant “Not my bug.” In the end, my users would be unhappy, but hey – at least I stood up for myself, right? At least I’d have the satisfaction of knowing I did the right thing.

But this is not the right thing. At least, not if you believe that the point of software is to make people happy. In fact, there’s a grand tradition of unsung heroes in software development fighting to fix the other guy’s bug. Once again, my main man Joel Spolsky explains:

[I heard this] from one of the developers of the hit game SimCity, who told me that there was a critical bug in his application: it used memory right after freeing it, a major no-no that happened to work OK on DOS but would not work under Windows where memory that is freed is likely to be snatched up by another running application right away. The testers on the Windows team were going through various popular applications, testing them to make sure they worked OK, but SimCity kept crashing. They reported this to the Windows developers, who disassembled SimCity, stepped through it in a debugger, found the bug, and added special code that checked if SimCity was running, and if it did, ran the memory allocator in a special mode in which you could still use memory after freeing it.

From Microsoft’s point of view, they had a good reason for doing this. If a customer was upgrading from DOS to Windows, and suddenly all their favorite applications stopped working, they’d simply return Windows. Microsoft would bear the fallout from the other guy’s mistake. Once again, the one who gets blamed is not necessarily at fault, but it’s still his/her responsibility to fix the bug.

In Android development the most infamous instance of this occurs in the Android Market, and it’s the bane of Android developers everywhere:

“Error 18” occurs when the Android Market fails to download and install an app. And even though it has nothing to do with the app itself, this is the most common bug you will see reported by users. In fact, I’ve gotten so many reports of this bug that I’ve created a “canned response” in Gmail that I send out to all of them. I believe I recall reading that Arron La, the developer of the immensely popular Advanced Task Killer app, has said that he simply stopped responding to these kinds of emails, because he gets too many of them.

The reason that poor schmucks like Arron and me get inundated with these emails is due to the interface of the Android Market itself. When an app fails to install, the user will be on this page:

It may as well say, “Direct your frustration here.” And from the user’s point of view, this is understandable. When they get an error like this, whom are they supposed to ask for help? Google is not famous for their tech support. So, as the quaint proverb goes, shit rolls downhill. And it hits the developer first.

So we’ve established that the one who gets blamed is not necessarily the one at fault. But how do you determine who gets blamed? In the case of SimCity, it was the OS rather than the app. In the case of “Error 18,” it’s the app rather than the OS. I think the explanation for this is pretty simple.

In the smartphone world, your OS is wedded to your phone, and your phone is very dear to you. Perhaps you even consider it an extension of your psyche, the way some people might feel about a trendy haircut or designer jeans. So if an app breaks on your phone, you return the $2 app, rather than the $500, psyche-extending phone. In Microsoft’s case, the OS was not very closely tied to the hardware back in the 90’s, and the cost of an application was about the same as that of the OS. Or at least, the gap wasn’t as steep as $2 vs. $500. So in that case, it’s Windows that would get returned.

I think this can all be generalized as follows. The bug becomes your bug if:

  1. You are more accessible than the other guy, e.g. they represent understaffed call centers in far-flung corners of the world, whereas you represent a single ordinary person (who must have oodles of spare time to answer emails, if you can afford to waste it writing apps).
  2. You are more visible when the problem occurs, e.g. the bug pops up when you use the other guy’s library, and that library is invisible to the user.
  3. You will suffer the most from the blame. I think this is the big one. Even if user opinion is split 50/50 on whose fault it is, it becomes your bug if the blame hurts you more than the other guy. The Android Market bug is an instance of this, since “Error 18” might cause a developer to lose a sale, but it hardly affects Google’s bottom line.

Unfortunately for me, even though the “Error 18” bug is my bug by this definition, there’s not a whole lot I can do about it. There’s nothing I can change in the software that would stop the error from occurring, or lessen the pain for the user. So the best I can do is keep responding to these emails.

Or, if I’m feeling snarky, maybe I can link them here.

Share and share alike – just not with Facebook

Edit: Facebook has fixed this bug in the latest version of their app.

Here’s a common situation when you’re writing an Android app: you’ve got some text (a link, a test result, a poem you wrote about your love for Android) and you want to allow the user to “share” it with others. And if you’re lazy like me, you’ll quickly discover the fastest way to do it:

Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Android, oh Android.");
intent.putExtra(android.content.Intent.EXTRA_TEXT, "Wherefore art thou, Android?");
startActivity(Intent.createChooser(intent , "Share"));

This generates a screen that looks like this:

Isn’t that nice? And it only cost you five lines of code! But oh, if only it were so easy…

See, the problem is with the fourth guy there – Facebook. The Facebook Android app only supports sharing URLs, not arbitrary text. Most other apps work fine, but when you click on Facebook, you get this sad, broken-looking page:

For my own apps where I wanted to enable sharing (Japanese Name Converter and CatLog), I could have just left this as-is. I mean, this is Facebook’s bug – not mine, right? But then I realized that, whether it’s my fault or not, my users would see this ugly page and assume it was a bug in my app. So I had to get Facebook out of there.

After some Googling, I found this discussion, which pointed me in the right direction. In the thread, one of the posters basically gives you all the tools you need to build your own custom SEND_ACTION chooser. However, I found it was a non-trivial amount of effort to co-opt their code to do what I wanted it to do.

So I built a more easily extensible version.  Here’s the final product, based off that poster’s original Launchables class.  It uses the PackageManager to find all apps that respond to SEND_ACTION, then filters out Facebook and displays the rest in a simple ListAdapter.  The code is open source; do whatever you’d like with it. All you have to do is copy SenderAppAdapter.java and the resource files into your app, and then use it as in DemoActivity.java. It will create an AlertDialog like this:

It looks almost exactly the same as the default chooser, but Facebook is gone! Plus, I threw in a “copy to clipboard” action as a little bonus. This way, the user can always post her lovely poem to Facebook by copying the text, opening up the Facebook app, and pasting in the damn text manually.

And most importantly, no one will blame you for Facebook’s oversight.

Download the source code

Respect your users by treating them like idiots

Working on Pokédroid in the middle of a huge boom in its popularity (it’s gaining 3,000 installs a day – not downloads, but cumulative installs) while reading Joel Spolsky’s User Interface Design for Programmers is teaching me a lot about designing UIs.  You can read some chapters of the book for free online; I especially like this post. I’m learning that Joel is absolutely right about many things, but especially this:

  1. Users don’t read anything.
  2. You must assume that users will not give your app their full attention.

Spolsky explains:

What does it mean to make something easy to use? One way to measure this is to see what percentage of real-world users are able to complete tasks in a given amount of time. For example, suppose the goal of your program is to allow people to convert digital camera photos into a web photo album. If you sit down a group of average users with your program and ask them all to complete this task, then the more usable your program is, the higher the percentage of users that will be able to successfully create a web photo album. To be scientific about it, imagine 100 real world users. They are not necessarily familiar with computers. They have many diverse talents, but some of them distinctly do not have talents in the computer area. Some of them are being distracted while they try to use your program. The phone is ringing. WHAT? The baby is crying. WHAT? And the cat keeps jumping on the desk and batting around the mouse. I CAN’T HEAR YOU!

Now, even without going through with this experiment, I can state with some confidence that some of the users will simply fail to complete the task, or will take an extraordinary amount of time doing it. I don’t mean to say that these users are stupid. Quite the contrary, they are probably highly intelligent, or maybe they are accomplished athletes, but vis-à-vis your program, they are just not applying all of their motor skills and brain cells to the usage of your program. You’re only getting about 30% of their attention, so you have to make do with a user who, from inside the computer, does not appear to be playing with a full deck.

The scroll thumb in Pokédroid

I’ve seen this “not playing with a full deck” situation play out over and over.  Recently, I had a user send me a very polite, carefully-worded email asking if I could make it easier to scroll to the new Black/White Pokémon, which are about 500 down from the top of the list. I was perplexed.  I wrote back and told him that, on my Nexus One, I can scroll down to the new Pokémon in about one second using the fast scroll thumb.  In fact, I implemented the fast scroll thumb to solve this exact problem. Was the fast scroll thumb not working on his phone?

Nope.  It turned out he just hadn’t noticed it.  He didn’t read the popup explaining the new feature, and he didn’t notice the scroll thumb at the right, even though it pops in and out as you scroll and is about 15% the width of the screen.  Now, it’s not that this person wasn’t intelligent – from reading the email, I could tell that he was highly literate.  It’s just that he wasn’t giving the app his full attention, because that’s what users do.

Several other users complained in the Android Market comments that there were no Black/White Pokémon:

  • Would be 5 stars but I can’t find the unova pokemon srry
  • Unova Pokemon don’t so up after update but all together its a good app
  • I just got the update and it had all of the improvements but it didn’t have the Black/White Pokemon
  • Huh?I updated but unova pokemon didn’t come out.HTC legend

This is because they’re updating from an older version of Pokédroid, and their game version is still set on HeartGold/SoulSilver, or some other version.  I told them in the initial popup that they needed to switch it.  I told them in the Android Market description that they needed to switch it.  I even put it at the top of the description preceded by the word “NOTE” in all caps.  Did it work?  Nope.  I still see these comments.

Of course, this is totally predictable given that, as Spolsky puts it so succinctly, “users don’t read anything.”  Again he explains:

This may sound a little harsh, but you’ll see, when you do usability tests, that there are quite a few users who simply do not read words that you put on the screen. If you pop up an error box of any sort, they simply will not read it. This may be disconcerting to you as a programmer, because you imagine yourself as conducting a dialog with the user. Hey, user! You can’t open that file, we don’t support that file format! Still, experience shows that the more words you put on that dialog box, the fewer people will actually read it.

The Black/White popup

So in the upcoming version, I’m implementing a popup to ask the user to confirm their game version when the app starts up.  Now, I know that users don’t read text, and I know that they hate popups, so I’m using some relaxing visuals instead – the box art from the games.  “Confirm Game Version: HeartGold/SoulSilver” pops up with a huge box art in their face.  Bam.  No confusion.  Except there is.  I realized as I was toying around with it that when it says “Confirm Game Version: Black/White,” I felt like I wanted to click on either the Black box art or the White box art.  I felt like it was asking me whether I wanted Black or White.  It was confusing to have to hit “OK” instead.  Which one am I confirming?

So I realized this: most users are going to assume that the game version is Black/White.  Why would they want anything else? Black/White is the most recent game.  If there are older Pokémon games with fewer creatures and different move sets, they sure as hell don’t want to know about it.  They just want to see some damn Pokémon, and they couldn’t care less whether I show the move sets from HeartGold, LeafGreen, or HotCherryPassion. Hardcore Pokémaniacs might scour all the settings and figure it out, but casual users won’t.

So my solution is to only show the popup if they’re on something other than Black/White. Normally, users expect popups when something is wrong, not when everything is A-OK. So new users, whose game version will default to Black/White anyway, would just be confused by a popup. “What happened?  Did I do something wrong?” So I figure: why even show it, if they’re already on the newest version of the game? This way, I can solve the immediate problem (people stuck on HeartGold/SoulSilver) without interrupting the majority of my users.

Another change I’m making is to shorten the introductory dialog and add pictures.  Given that the introductory dialog has traditionally been a wall of text, I should be surprised if users read anything in there.

Old intro popup

Just look at my pretentious little dialog, with its list of chores for the user to complete.  Are they really going to want to learn about the settings before they’ve even used the app?  Or where the “About” section can be found? I thought about it, and realized that there are only three pieces of information I need to convey in that dialog:

  1. You can download Pokédroid Extras to get footprints and cries.
  2. You can download Pokédroid Donate to get shiny sprites.
  3. The most recent changelog, for the 10% of users who want to know what’s updated and will actually read it.

Anything else, the user will only seek out on a need-to-know basis.  For the most part, they will just plow through the app and assume they can figure out how to use it as they go.  They don’t want pedantic lectures explaining how to change the settings or where to go for more information.  If they want information, they’ll come to me.

Pokédroid Extras and Pokédroid Donate are the only non-obvious components to the app, because you can’t get them in the app itself.  They require a separate download.  So I figure I’ll slap some pictures on the introductory dialog explaining what Extras and Donate do, and hope that the user’s eye will be attracted to the pictures, which will motivate them to read the 6-7 words to the right. They should be able to get the gist of the popup in one glance. They shouldn’t have to break out a cup of coffee and their reading glasses just to start the damn app.

New intro popup

This whole discussion may make it sound like I don’t respect my users.  But the beautiful thing, as Spolsky explains, is that by assuming my users are going to act like airheads, I actually am respecting them.  I’m saying, “I know you don’t care about this app nearly as much as I do.  I know you’re not interested in lectures about how I optimized the database, or all the cool little features I put in and why.  You’re a busy person, and you have better things to do.  You will put in the bare minimum of intellectual effort to understand my app, so that you can complete whatever task you’re trying to complete.  And that’s great.  I’ll be here to help you complete your task, and the rest of the time I’ll try to stay out of your way.”  What I’m doing is showing humility, and respecting my users’ valuable time.

Also, a lot of my conclusions about user behavior come from observations I’ve made about the way I use software (since reading Spolsky’s book, anyway). The fact is, I drive my phone like a reckless drunk drives a semi.  I pound the OK button to skip long dialogs.  I spam the back key to get out of an app.  I never read the changelog, the “About” section, or the manual – or maybe I glance through it, reading in an “F” shape (horizontal at first, then vertical down to the bottom).  If there’s a non-obvious Android feature that I actually use (holding down the home button to see recent apps, holding down the menu button to bring up the keyboard), it’s only because I’m an Android developer myself, so I saw it in the documentation.  It’s certainly not because I read the manual to either of my phones, because I didn’t.

When I download a new app, I usually just try to use it to accomplish one very specific task.  If I can’t figure out how to do that in ten seconds, I uninstall it.  For instance, I recently wanted an app that would let me uninstall other apps by clicking a widget on my home screen.  So I downloaded two or three of those “Task Killer”-type apps and tried to figure out how to do what I wanted.  When I couldn’t, I gave up and uninstalled them.  Each app probably spent all of sixty seconds alive on my phone before I flushed it down the memory hole.

When I manage to accomplish a task in a downloaded app, I rarely fiddle with the settings and just assume that the defaults are okay.  Sometimes this gets me in trouble.  A great example is the gStrings tuner app, which I use to tune my guitar.  The app is wonderful, and I’m happy to have downloaded the premium version to help support the developer.  The guy obviously knows his stuff – the settings are full of fancy options like “Playback Octave,” “Use Orchestra Tuning,” and “Use Harmonic Product Spectrum.”  Of course, I’m not going to change any of these, because they might as well be in Hebrew, but at least they inspire confidence that the developer is a real pro.

gStrings' settings

"Optimize For"

However, buried within those options is one called “Optimize For,” with the very scary-sounding description of “select an optimal target frequency range.” After you click on it, it gives you a choice between violin, viola, cello, double bass, guitar, and ukulele, with violin as the default.  When I discovered this, I was surprised.  I figured that, if anything, the guitar would be the default – everybody and their dog plays the guitar, but almost nobody plays the violin.  Also, who in their right mind would actually click on this option in the first place?  The only reason I discovered it myself is that I was evaluating my purchase of gStrings, and I wanted to see the differences between the premium and the free version.

Unfortunately for users of gStrings, this is exactly like my Black/White situation.  Everyone is going to assume that the default setting is guitar – if they even imagine that such a setting exists.  And nobody is going to cuddle up and read the settings menu, slogging through wordy descriptions like “shift target frequencies e.g. by redefining A: 440Hz -> 443Hz,” to figure out if they should change it.  I’m sure if the developer of gStrings did a random survey of 10 users, he or she  would discover that 7 of them play the guitar, but 6 of them have their app set on violin.  The other 3 users play the ukelele, the cello, and the violin, but none of them managed to find the “Optimize For” setting at all. So only two lucky users get to actually have the setting that’s right for their instrument.

Now that I’ve read Joel Spolsky’s book, I’m starting to see dumb programmer mistakes in every app I use.  Descriptions that are too long and complicated. Unhelpful popups that interrupt the workflow. Optimizing for edge-case usages (like searching by regular expressions), while ignoring common use cases (like just punching in a single letter and searching by the first character).

Searching logs in Catlog. Just start typing and it filters as you go.
 
 

Searching logs in aLogcat. Hit Menu, hit Filter, then get a free lesson on how your regular expressions need to conform to Java.

I’m starting to see it in my own apps as well, which is especially frustrating, because I had no idea I was making such elementary mistakes. The most egregious of these is probably App Tracker, which is so bad it deserves a post of its own.

Well, from now on at least, I’m going to work to make simpler, easier-to-use UIs for my apps. Hopefully it will result in a better experience for my users, because they are are all idiots. Just like me.