Testing Your ContentProvider with Robolectric

You like testing?  I love testing, especially unit testing.  ContentProviders are the underpinnings of many data layer implementations in Android apps and obviously, an important thing to test.  I added some new code to a ContentProvider in the RadioPublic app and wanted to verify that the ContentProvider and model code worked.  I spent an hour looking through the documentation and online. I also wanted to use the Robolectric test framework already setup in the app.  After concluding my research, I found what I was looking for and its very straightforward.

First of all, if you haven’t already done so, in your module’s build.gradle file, depedencies section:

testCompile 'junit:junit:4.12'
testCompile 'org.robolectric:robolectric:3.1.1'

In your unit test class, class annotations

@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 18)

Register your ContentProvider with the appropriate Authority:

private static final String AUTHORITY = "com.example.debug";

@Before
public void setup() {
    YourProvider provider = new YourProvider();
    provider.onCreate();
    ShadowContentResolver.registerProvider(
            AUTHORITY, provider
    );
}

Get a reference to the ContentResolver, since this is, most likely, how you’ll be interacting with your provider:

ContentResolver contentResolver = RuntimeEnvironment.application.getContentResolver();

Finally, test your ContentProvider

@Test
public void getSomeData() {
   ...
   cursor = contentResolver.query(Test.MyUri, null, null, null, null);
   ...
}

That’s it!  Hopefully this will save you time and encourage you to write tests for your ContentProviders.

Use ints instead of enums on Android

Romain Guy, an Android framework engineer, gave a great talk at Devoxx on building Android apps in a memory conscious fashion.  See the link at the end of the post for the entire slide deck.

One thing always stood out to me, using int variables instead of enums.  As great as Java enums are (self documenting, type safety, etc), the following slide convinced me not to use them unless I really needed to.

Screenshot from 2015-03-04 19:11:44

 

It may seem like a trivial amount, but 1) that’s an order of magnitude smaller when you use int variables instead of enums and 2) a couple thousand bytes here and there in aggregate can lead to substantial savings.  Those memory savings matter, especially on lower end devices.

-> Android Memories

Identifying The Right Customers

Shift Jelly developer, Russell Ivanovic, shared some insights on the breakdown of Pocket Casts users on Android.

First of all, Android version adoption numbers.

screen-shot-2015-01-31-at-10-25-14-am

Developers should spend an overwhelming amount of their time developing and shipping products for Android 4.1 “Jellybean” – Android 4.4 “KitKat” because that’s where the users are right?  Well, it depends.

Pocket Casts specific Android adoption numbers (ie. what versions of Android are my users running).

pc_numbers

My lone Android application, NC Traffic Cams, Android adoption numbers.

Screenshot from 2015-01-31 11:33:01

So while Android 5.0 has less than 1% adoption in the overall Android eco-system, 23% of our customers already run it. This makes sense when you put a bit of thought into these numbers. People that have the money to buy apps, and are passionate about Android, have up to date phones. While some users who run Android 2.3 on their 5 year old phone might be perfectly happy, they probably weren’t ever going to buy Pocket Casts. It’s also worth noting that Pocket Casts sells in much larger volumes (and makes more revenue) than any numbers I’ve seen for an equivalent iOS app. We’ve slowly moved our minimum version from 2.3, to 4.0, to 4.1 and it hasn’t hurt sales at all.

I, 100%, agree with Rusty.

Android adoption numbers, provided by Google, are only relevant if your target customers include ALL Android users.  This is rarely the case.  I’d imagine only a very few developers and companies can afford to target all Android users as customers for their apps and services (depending on the complexity of their apps, most in this group are large public corporations or venture backed startups ie. the Facebooks, Twitters, Instagrams, and Ubers of the world who aim for ubiquity).  Android is such a huge market (1 billion devices sold in 2014) that there are bound to be smaller, profitable, niche markets available.  Enthusiast and indie developers need to spend sometime identifying these smaller, niche markets before starting on new products.

While building NC Traffic Cams, a relatively simple product, I essentially targeted Android users who were interested in North Carolina traffic imagery.  I wasn’t using the latest and greatest APIs because my priority was providing visual traffic information to as many Android users as possible.  Early on, I used libraries (ActionSherlock, Google Play Services, etc.) that made it easy for me to provide a consistent user experience across various versions of Android (at that time, starting at Android 2.1).  I eventually dropped support for Android 2.1 and 2.2 because the Google Play Services library eventually dropped support for these versions.

I, of course, did not completely follow my latest insights with regards to my current project, PremoFM.  In the beginning, I identified, at a very-high-level, business-diagram-type-of-way, the customers I am targeting, but I failed to identify the specific profile of Android users I am targeting until midway through the project.  For example, I targeted Android customers running Android 4.0 through to Android 5.0 (I at least had enough foresight to cut out Gingerbread support).  Then I began writing code and realized how many specific APIs weren’t available on older versions of Android.  I was definitely on the road to a bad user experience and high support costs, given my real life constraints (one person, doing this in my free time).  I took a step back and asked a few questions, some of them being:

  • How much effort or time am I willing to sacrifice to provide support to users with older devices (fixing bugs specific to these version, etc.)?
  • What versions of Android will allow me to provide the best user experience possible?
  • Are there enough paying customers using older versions of Android to make supporting these versions worthwhile?

In the end, it’s all about establishing your priorities (and more importantly, de-prioritizing other things!).  The time you spend working on XYZ will mean you won’t have that time to work on ABC.

As an side, it would be really interesting to see general data on which types of users spend the most money and what versions of Android they use.  My guess is pretty consistent with Android adoption numbers provided by Russell.

-> How New Versions of Android Work @ RustysRants

 

NC Traffic Cams now in the open (source)

A few years ago, in 2012, soon after I accepted a full-time Android developer position, I started working on NC Traffic Cams (in the Google Play Store).  It started out as a “hack” to see if I could scrape all North Carolina Department of Transportation (NCDOT) traffic cameras.  Consequently, this was also my first time coding in PHP (https://github.com/emuneee/nc-dot-tims-scraper).  This quickly turned into something where I wanted to implement my understanding of several Android development concepts of the time:

  • Android ListViews + Image Loading + Image Caching
  • Actionbar
  • Google Maps SDK for Android (this wasn’t in Google Play Services at the time)
  • Google Analytics SDK (neither was this)
  • Holo (the Android 4+ design language)
  • HTTP Connectivity
  • JSON Parsing
  • Fragments (yay!)
  • Phone & Tablet layouts
  • SQLite
  • AsyncTasks

At the time, the Samsung Galaxy S, running Android 2.1 (!) was the hot new Android phone.  I had the AT&T derivative, the Samsung Captivate.

Initially, it became a chore.  I had to manually run my hacked together PHP script, then export the traffic camera data into a format that I could stuff into the source code, then update the Android app (do things that don’t scale right?!?).   Well, I soon after discovered automation and built a backend whose job it was to keep the app updated with the latest traffic cameras added by the NCDOT so that app users had access to the latest imagery.  It was at that point that I bootstrapped a Node.js API server to serve the latest cameras to the app, a Java app to periodically query the NCDOT TIMS, and a MongoDB datastore.  Some related topics covered during the bootstrapping process:

  • Node.js + ExpressJS APIs (I’ve kinda turned into a Node.js fanboy of sorts)
  • MongoDB & general NoSQL database concepts
  • Crontab
  • Deploying to Amazon Web Services (AWS) S3
  • XML parsing

In late 2014, my year of free AWS usage ran out, so I took the backend server offline and decided to open source the app.  What good is the source code if you can’t share it with the world?  You will find the source code to the Android app, Node.js API server, and the Java app at the following GitHub.com repository.

https://github.com/emuneee/nc-traffic-cams-open

Disclaimers and Quick Notes

The Android app was built using Eclipse + Android Development Toolkit (ADT), the Android Studio based on IntelliJ wasn’t a thing when I started this app in 2012.

This was my first modern Android app, written in 2012, when I had just begun writing code professionally.  I look back at the code to this day and truly understand how I’ve grown as a developer over the past few years.  Don’t judge me.

Some cool statistics (Google Analytics is embedded in the Android app):

The day that experienced the highest usage: Tuesday, February 12, 2014 – my NC people (especially Raleigh folks) will remember this day as the Great Snowpocalypse of 2014.

On this day 26,000 traffic camera images were served to NC Traffic Cams users.  This told me people were interested in viewing near-realtime traffic conditions on their mobile devices.  It saved me hours of headache because I was quickly able to see the most congested and snow-covered routes (like the following image), and avoid them completely.

As of today, January 6, 2015, this app has been downloaded and installed 7,700 times and currently, actively installed on about 2,000 Android devices.

When I built the app in 2012, there were around 450 publicly available NCDOT traffic cameras.  Today, that number is nearing 700.

The methods and techniques used in NC Traffic Cams form the basis of my Android development experience.

Sidenote: my very first mobile app was Speeed Reader for Windows Moble 5/6.X, one of the first & full featured Google Reader RSS clients for Windows Mobile at the time. (Source Code)  I did not make this video.

I have ceased development of NC Traffic Cams and am burning the midnight oil building a beautiful social podcast experience by way of Premo.FM (@PremoFM).

Anyway, I hope the code proves useful.