Hey! I'm making a game called Terra Mango. You should check it out.

Cashify, An Android App Building Experience

I recently released my first android app, Cashify. This post is a reflection on my experience building an Android app for the first time. If you want to know what the app does visit its Google Play page (and download it).

Android Studio

Lately, my daily IDE has been Visual Studio, and Android Studio isn't too dissimilar from that. However, they completely got the "redo keyboard shortcut wrong; Ctrl+Y is supposed to redo, not delete the entire line! I never did get used to that.

Downloading, installing, and making Android Studio ready for work for the first time took nearly an entire day. There isn't a cumulative update for each AVD (Android Virtual Device) and the supporting files that go with them. So you have to install/update the AVDs and packages you want, and then sometimes restart the AVD manager, and then update them again, then repeat until no more updates are available.

Java

I had never built anything significant with Java before. Fortunately, coming from a C# background made it very easy. One thing I really liked about Java was the ability to create anonymous classes with methods.

Here's an actual snippet of code

mHelper.startSetup(new IabHelper.OnIabSetupFinishedListener() {
    public void onIabSetupFinished(IabResult result) {
        if (!result.isSuccess()) {
            // Oh noes, there was a problem.
            Log.d(TAG, "Problem setting up In-app Billing: " + result);

            showError("This application requires Google Play Services and In-App Billing, which your device is reporting as currently unavailable. If you think this an error, please email cashify@pxcoach.com.");
            return;
        }

        // Hooray, IAB is fully set up!

        mHelper.queryInventoryAsync(mGotInventoryListener);
    }
});

Android

Android's documentation wasn't bad, but not great, either. There are many examples that apply to Eclipse, but not to Android Studio, even though the getting-started tutorial recommends Android Studio. And not all documentation/SDK examples are consistent with one another, specifically, In-App Billing.

I don't request any permissions other than INTERNET, BILLING, and CHECK_LICENSE, which were all fairly straight forward concepts. I do feel that INTERNET should already include ACCESS_NETWORK_STATE.

I have two gripes about developing for Android:

  1. There are a lot of versions of Android that run on a lot of devices, about 18,796.
  2. I couldn't get the AVDs to run for most of them. Apparently it is a Windows problem?

A new concept I learned about when trying to make scalable drop-shadows for some UI elements was NinePatch. If you haven't heard of it, check it out. I do still think that there should just be a built in box-shadow property, à la CSS.

I also learned a lot about cross-device DPI, thanks to Sebatian Gabriel's article Designer's guide to DPI. I even went out of my way to produce XXXHDPI assets just for the Nexus 5's launcher, which uses the XXXHDPI icon in its launcher (and for a little future-proofing, of course).

Google Play

The fact that you can't test in-app billing on an emulator OR your own developer account is a major PITA. Luckily, my wife "let" me steal her phone whenever I needed to test, otherwise IAB would have required that I purchased a phone just for testing (or wipe my existing phone and set it up on a different Google account, ick).

In order to let someone to set their own "price", I created one product for each penny from $1.00 to $100.00. Google lets you import products via CSV, so it is very quick and easy to create with Excel.

Server

I set up a free Heroku account with SSL termination happening over https://cashify-server.herokuapp.com/ which handles all of the app's API calls.

I also configured a free New Relic account to monitor the site; which prevents the app from sleeping if no new requests come in for a while (a side-effect of the free Heroku account). I also tried integrating New Relic into the app itself, but couldn't get it working.

I'm running express on node.js for routing and handling requests.

The main workflow for the app goes like this:

  • check my Dwolla balance to make sure I have the necessary funds
  • take the completed IAB request and validate the JSON against its signature
  • save the request information to the (free) PostgreSQL database to prevent any replay attacks
  • initiate a transfer of funds (via Dwolla)
  • respond to the request to indicating success (or failure)
  • then email myself and the customer a confirmation of funds transferred via a free account at postmark.

Google itself tracks if a product has been "consumed", or not. If an In-App Billing purchase succeeds, but my server is unavailable at the time, the app will just check for un-consumed products at later time and ask if the user wants to try converting those funds again.

Hackers

As a precautionary measure, I only keep $100 in my Dwolla account at a time, just in the case someone finds a hole in the server's security.

There have already been several attempts of users using fake/bad credit cards (instead of Google Play Credits). In fact, there have been more malicious attempts than honest ones. I'm very fortunate Google automatically blocks these attempts for me.

I use strong+unique passwords and two-factor authentication for my Google account, Heroku account, CloudFlare account, domain registrar, etc., hopefully preventing an @mat horror story of my own.

All required API production keys/secrets are stored as config vars for the app, rather than in the source code itself. This alleviates the need to store any sensitive information on my computer, in the source code, or anywhere really. In theory, you could steal my computer tomorrow and still wouldn't be able to compromise the app's security.

Speaking of hackers, while developing this app I uncovered a semi-serious security bug in a stock Android application, which I'll write about as soon as the Android team gives me the thumbs-up for public disclosure.

Monetizing

Google takes 30% right off the top. This was a bit more than I expected. I take another 10% as a processing fee; which I admit is also a bit high, but is still much lower than Google's, so I try to get away with it. Dwolla, kindly, takes 0 (thanks Dwolla!).

For every Play Credit that is converted, Google gets $0.30, I get $.10, and the user gets $0.60.

The average amount of credits converted up to this point is is $1.38.

Since I launched the app, I have earned less than $1 (minus the $25 Google Developer Registration Fee).

Financing

I researched a lot of online financial institutions to try to find one that was:

  1. free (or nearly free)
  2. had an API
  3. allowed transferring money to any email address

PayPal struck out on requirements 1 and 3. Stripe lost on 1. Google Wallet would have won, but ultimately the API was lacking (no free email to email transfers). So Dwolla, the least popular of them all won out.

Dwolla is great because you can send money completely free if the transaction is $10 or less. If you are sending more than $10 at a time, you can break up the transactions into $10 chunks. Their API and node.js module was also very easy to use and test. They also have sandbox accounts to use for testing (the UI for it is terrible).

// Easy API (it won't be this simple soon, see the paragraph below for why)
dwolla.send(dwollaToken, dwollaPin, to, dollarsToSend, {
    "destinationType": "Email",
    "assumeCosts": true,
    "notes": message,
    "fundsSource": "Balance"
}, callback);

Dwolla isn't all rainbows and butterflies. Initial user registration asks for very personal information, like your SSN, just to accept the money. And they only work with US banks. While the Dwolla Android App has a 3.8 rating, the top reviews are all very negative, and the app hasn't been updated in 9 months. They also just changed their OAuth implementation, requiring all applications to update or bust. These changes are not trivial and will necessitate significant re-architecture of the backend soon.

Conclusion

I really enjoyed this little project and have been coming up with tons of new app ideas since I published it. Switching gears from the monotony of working with familiar languages and platforms in my day job was very rewarding and motivating, despite the total lack of monetary ROI. I encourage you to go find something you've never done, do it, and then tell people about it.

Fail at things, tell people.

Comments for this blog entry