android-apt 1.2

My Gradle plugin to support annotation processors in Android Gradle builds & Android Studio, android-apt, got another update! Version 1.2 now also supports library projects. This version requires the android plugin version 0.7 or up, since that version supports a new API that I use in the plugin. So upgrade your Android Gradle builds and generate some code :)

Check out the project site for more info and docs: https://bitbucket.org/hvisser/android-apt

Droidcon UK Cupboard talk

I did a talk on Cupboard at the excellent Droidcon UK conference this year. The talk was recorded and published at Skills Matter. The talk outlines some of the history and goals of Cupboard and shows a few examples of using the library from different contexts. You can checkout the video from this link: http://skillsmatter.com/podcast/os-mobile-server/simple-persistence-with-cupboard

I’ve also recently set up a Google+ Community for Cupboard, where we can have a friendly discussion about anything related to Cupboard, like feature requests, issues or general questions. Feel free to join, I’m really curious and exciting to hear how Cupboard is used in the wild!

android-apt Gradle plugin 1.1 is out

This plugin helps supporting annotation processors in Android Studio. See this post: https://plus.google.com/102164807080986038267/posts/7Wr3FcdNVxR for more info.This release fixes a minor bug that occured when you did not apply the android plugin to your project, but more importantly it’s now possible to pass extra configuration arguments to the annotation processor, which is something that the popular Android Annotations library needs. The project site has an example on how to configure annotation processor parameters.Thanks to +Thomas Bruyelle for sending the PR and testing the final implementation of this feature!It should be live on Maven Central shortly.

Next up is making the plugin use a new API that has been introduced with the Android Gradle plugin.
#androiddev #gradle

Embedded Link

hvisser / android-apt

View this post on Google+

Cupboard v1.0.4

I just pushed another minor update to Cupboard! Cupboard now supports limiting the result set (through the SQL LIMIT clause) and distinct queries if you need them. There’s also a new variant for bulk put’s that takes a Collection, which might come in handy if you are getting your entities from services like Parse.comTo learn more about Cupboard visit https://bitbucket.org/qbusict/cupboardAdditionally I’ve setup a community for Cupboard for questions and discussion here: https://plus.google.com/communities/102678039256081927502
It’s spanking brand new, so nothing is there yet, but feel free to join and discuss anything with regards to Cupboard if you like.
#androiddev

Gradle android-apt plugin

Here’s a small Gradle plugin that helps out if you have a project that includes an annotation processor. There are two use cases for this plugin:1. You have a processor that has a compiler part and an api part, you don’t want to get the compiler in your app. For this purpose the plugin sets up an apt configuration.
2. Your annotation processor produces source which you want to reference in Android Studio. By default these kinds of projects build fine in Android Studio, but the generated source isn’t on any source path in Android Studio so you might get errors there. The plugin will add the generated source to a source set so that AS will recognize it. This is also true for the first case btw; if the processor generates source, it will be added to the source set for the current flavor.

This is all based of a script that I’ve been using https://bitbucket.org/qbusict/android-gradle-scripts/src/60394ba8f5efa64badb17c9388f38b89f09c5d9a/annotations.groovy?at=default but it got a bit cumbersome to check out the script for each project and I thought providing it as a plugin might be useful for others as well.

One thing that is still missing is the option for passing in arguments to the annotation processors, when I have the need for it I’ll add it, but pull requests are welcome.

It’s live on Maven Central so easy to add to your build if you need it.
More info and source is here: https://bitbucket.org/hvisser/android-apt

View this post on Google+

Minor update to Cupboard

I just released a new version of Cupboard that adds support for Enum types and fixes a bug where private fields would not be persisted, in the case you prefer “normal” POJO’s with getters and setters. It should arrive in Maven Central shortly. For more info on Cupboard, refer to the project site at https://bitbucket.org/qbusict/cupboard

Embedded Link

qbusict / cupboard
The simple way to persist objects in an Android SQLite database.

Cupboard slides from Droidcon UK

I presented on Cupboard at the Droidcon UK barcamp, if you are curious, you can find the slides of that talk here: https://docs.google.com/presentation/d/1giCUSlDwdG2ghbbuHBvrL-gqfnw0Q3RSlTBOCVmouPQ/pub

Example of custom states in Android components

A while ago, I built a form based app with lots of input fields and all the things that come with that, like validation and error messages.

In one of the situations, if a section is invalid, the field labels should turn red. Easy right? Here’s the example layout:

And a naive way to switch the label colors when there’s an error:

But this is kinda ugly. We need to get “not-error” color from each component, store it, switch the color to red and if the error is fixed, restore the colors again. There’s too much code that deals with updating the view in here and it only gets worse if we add more labels.

Using selectors

You’ve probably worked with selectors before. In this particular case we’ll be using a ColorStateList selector to change the color of the TextView. First, here’s the selector:

This is just like any other ColorStateList xml. You place it in the res/color/ folder of your project. This selector has one thing extra though: the app namespace and the app:state_error state. In effect this selector says:

  • If the state is error the color used is color_error as defined in color.xml
  • If the state is pressed, for example if the TextView is clickable and you click on it, the color used is color_pressed
  • By default the color is default_color

By know you probably see where I’m going…If we can change the state of the TextView to app:state_error then the color should be set by the Android framework to the color_error that is defined. But how do we do that?

First we have to actually define the new state in res/values/attrs.xml:

Then we should actually apply that state. We can do that in two ways:

  1. Extend TextView
  2. Extend the LinearLayout containing the TextViews

In this case we’ll extend the LinearLayout like this:

This code should be easy to follow. We add an extra property mError to keep track of the error state. At line 3 a constant is defined containing an array of states that are set when mError is true. Then it’s just a matter of overriding onCreateDrawableState() which takes an int called extraSpace. Since potentially we’d like to add one extra state if the mError flag is set, the code calls super.onCreateDrawableState() with extraSpace + 1. Then, depending on the mError flag the error state is added to the list of states.

The final layout using this new component looks like this:

Things to notice in this layout:

  • In stead of LinearLayout, ErrorStateLinearLayout is used as the main container
  • Each TextView has android:duplicateParentState=”true” meaning that the TextView will inherit any states from the parent view group.
  • Each TextView has it’s textColor set to error_color which would be the color state selector

Now we can finally update the view when there’s an error like this:

Much cleaner code, less bugs, yay for us!

Conclusion

By leveraging core Android principles, in this case using selectors, we can simplify our code a lot. By moving things that are related to the view out to xml resources not only our code gets cleaner, but we could also use the resources system to customize the ui based on the device configuration.

PS: ViewGroup has android:addStatesFromChildren which is equally useful!

Comment on this post on Google+

Gradle vs Maven

For some reason, now that Android is moving to a Gradle based build system, there’s some discussion whether Maven is better than Gradle or vice versa. There’s what I like most from Gradle compared to Maven:
1. Fast builds. Run a build twice: 2nd time you’ll see only “UP-TO-DATE” if nothing changed.
2. Dependencies choice: Artifacts in a maven repo? Have a library as a jar in your project? No problem, you can mix and match. A big improvement IMHO over the “everything has to be in a repo” approach that Maven has. Don’t make me maven install things or force me to have a repository manager. It doesn’t always make sense to have one.
3. Flexible configuration. For example: if you have some common configuration that you’d like to do in every build file, you can easily create a script for it and include it. Another example: in a multi project setup, you can configure a project from the top level build file, which is very convenient if you are including third party code without a build.gradle through a subrepository / submodule.
4. No more heaps of XML.
5. Gradle wrapper. Just checkout the project, and run gradlew to build the project.

Manage Android state with bundles @Frozen

This morning this post showed up in my stream by +Philippe Breault. About the caveats when treating the Application object as global state.

Although the advice that he gives, don’t store stuff in the Application object, is sane the example doesn’t really illustrate the problem. His argument is that when the activity is recreated, the application is recreated and therefore the state is lost. While this is true, the real issue is that the GreetLoudlyActivity from his example isn’t saving any state, which it should.

Luckily, this is easy to fix! A little while ago I wrote bundles, a set of two annotation processors for Android. The @Frozen annotation makes it easier to save and restore state in Activities and Fragments. So let’s fix the GreetLoudlyActivity:

If you don’t want to use custom code for it, this is how you would do it without @Frozen:

Remember, there’s a setting in the development settings section of your phone (ICS or up) to test for these kinds of bugs. It’s the “don’t keep activities” option.