Tuesday, October 25, 2016

Build It Bigger: Managing Dependencies with Gradle

Finished version of "Built It Bigger"
It’s official. Yes, I did complete the “Build It Bigger” project for the Android Developer Nanodegree, but that was a week ago. The only news is that I’ve finally put my laziness aside to write about it!

Like the post on Popular Movies, I’ll detail the key features, how I chose to implement them, and the challenges involved. And of course, there will be plenty of screenshots of the finished product.

The Assignment:

The accompanying course for this project was all about Gradle; that mysterious thing in Android studio that keeps displaying yellow messages about “syncing”. Previously, my only encounter with Gradle was hopelessly updating the version number on older projects and occasionally adding the dependency for ButterKnife or the Android Support library.

But Gradle does much more than that. Despite the annoyances, it’s a full automation tool that saves you lots of time when working on large projects. Hence, the name “Build It Bigger”.

For this project, I had to create a joke telling app, with functionality separated into libraries. In addition, there were also free and paid versions that needed to share the same code base. There was even some “cloud code” to supply the jokes.

The Implementation:

The starting code was a simple screen with a prompt and a button to tell a joke. Nothing thrilling; just a place to begin.

Starting point for this project.

The first task was to create two libraries: one to supply the jokes, and the other containing an activity to display the joke. Note that because there needed to be free and paid versions, and because both versions tell jokes, this functionality is included in separate libraries, as it’s unchanged across builds. While the joke provider was a simple Java library, the joke presenter was an Android library, because it contains Android-specific components (an activity), its own resource files, and even a manifest.

At first, the joke provider library returned a hardcoded joke, but this was only temporary. I then needed to create a GCE (Google Cloud Endpoints) server to supply jokes in a more proper manner. After all, it would be silly charging for an app that just contains a handful of hardcoded jokes. The ability to add new jokes without requiring users to install updates is what makes an app more powerful than a joke telling book.

While the assignment only required a single GET request to download jokes, I wanted to further explore GCE. For this reason, the paid version of the app also has access to a POST request that allows users to upload jokes straight from the app. Free users don’t get an upload button and see the banner advertisement instead. We only want to hear from serious jokesters, and freeloaders are more likely to submit spam or bad jokes.

Paid users can submit jokes.

But inevitably, there will be that corny joke that nobody likes. What can we do to ensure the quality of jokes is maintained for all the users?

To solve this problem, I added a joke popularity system. After viewing a joke, users would get the chance to submit an up vote or a down vote. This is included in the activity from the joke presenting library, so it’s available to both free and paid users. All jokes start with a popularity of 3 and each vote is worth 1 point. Once a joke’s popularity reaches zero, it gets permanently booted off the server.

Bad jokes like this one can be voted off.

So where does the Gradle part come in?

While all this could technically be done by hand, it would be very tricky if you only want one Android studio project. Instead, Gradle handles most of the difficult work in the build process. Both joke supplying libraries are listed by Gradle as dependencies in addition to third party libraries. The build script also defines “product flavors” allowing both the paid and free versions to coexist on the same device. Finally, dependencies can be filtered by their product flavor. Only the free version contains ads, so Gradle excludes this dependency from the paid version. Similarly, only paid users can upload jokes, so the free version has no need for the material dialogs library. Only the paid version will include this dependency.

Only free users see ads.
The Challenges:

Compared with previous projects, this app was not particularly complicated. However, there were a few issues encountered during the development.

When configuring the API, I was surprised to find that endpoint names were not those supplied to the “name” parameter of the @ApiMethod annotation. Instead, they used the name of the Java bean the method returned. So with the default GCE template, the “joke” method was named “mybean”. To override this behavior, I learned it’s necessary to use the “path” parameter. So this method

@ApiMethod(name = “getJoke”, path = “get_joke”)
public JokeResponse getJoke() { … }

Would be known as “get_joke” in the endpoint. If this parameter were omitted, it would be known as “JokeResponse”.

There were a couple minor snags along the way, but this one stood out the most. To get the gradient on the “tell a joke” button I used the tool at http://angrytools.com/android/button/. Quite useful if you’re new to Android graphics and want a simple way to learn about each of the properties.

Conclusion:

While not as code-intensive as some of the previous projects, I like how the joke telling app turned out. Nowadays, the freemium model appears to be more common than having separate free and paid versions, but it’s nice to know Gradle product flavors can handle most of the difficult work for you. And abstracting functionality into libraries is certainly something I’ll be using a lot in the future.


10 comments:

  1. is this a blog.com hosted page ?

    ReplyDelete
  2. This is just the information I am finding everywhere. Thanks for your blog, I just subscribe your blog. This is a nice blog.. UC browser mini

    ReplyDelete
  3. I just found this blog and have high hopes for it to continue. Keep up the great work, its hard to find good ones. I have added to my favorites. Thank You. 9apps download

    ReplyDelete
  4. I recently came across your blog and have been reading along. I thought I would leave my first comment. I don’t know what to say except that I have enjoyed reading. Nice blog, I will keep visiting this blog very often. AC Market

    ReplyDelete
  5. Most of the time I don’t make comments on websites, but I'd like to say that this article really forced me to do so. Really nice post! Action Link Wireless

    ReplyDelete
  6. I admire what you have done here. I like the part where you say you are doing this to give back but I would assume by all the comments that this is working for you as well. Download Cydia

    ReplyDelete
  7. This is a great inspiring article.I am pretty much pleased with your good work.You put really very helpful information. Keep it up. Keep blogging. Looking to reading your next post. iFile IPA

    ReplyDelete
  8. This is truly a great read for me. I have bookmarked it and I am looking forward to reading new articles. Keep up the good work!. Download iOS 11.3

    ReplyDelete