Tip: The 360|AnDev 2016 Android application is available for download from Google Play
I'm a low-level developer at heart. I'm most comfortable toggling pin states, dealing with radios, and parsing protocols. In general, the higher up the stack we move, the less comfortable I become.
As one of the co-organizers of 360|AnDev, I recently took it upon myself to build the conference Android app. This meant integrating a data back-end that didn't exist and discovering a way to use cloud messaging without writing server-side code.
As I said, higher level services like cloud APIs make me uncomfortable (I'm also fairly certain I'm allergic to JavaScript). Throughout my career as a software developer, I have always worked with wonderful teams that were capable of handling that side of development and I was a bit unnerved at the idea of having to learn and manage that all myself.
I had known about Firebase for quite some time, and decided it was time to give it a fair shake. The 360|AnDev 2016 app is built on top of several Firebase services, and I'm not sure I could have done it without them. The web console and client libraries made building this app simply a breeze.
NOTE: If you haven't already registered for 360|AnDev, what are you waiting for?! We've put together an amazing lineup of folks for you to mingle with in the Mile High City!
Firebase Database
One of my biggest concerns was where to put the data for speakers, sessions, venue, etc. without hard-coding it into the application. We collected most of this data on spreadsheets so there was no "web back-end" to speak of. I also had concerns about offline performance and caching since we all know how wonderful conference Wi-Fi connections are for the attendees.
Enter Firebase Database with what felt like nothing short of pure magic. With Firebase, everything is a URL and all data is a series of key/value pairs that can easily be represented by blobs of JSON. Using the web console, I was able to manually create the data we needed to display without getting bogged down by schemas. I could also manipulate the data live at any time and the changes would be reflected on the clients immediately.
The client SDKs make you forget your data is coming from a remote source. I was almost certain several times that I had to be doing something on the wrong thread or missing an edge case, but everything just worked. Fetching data, subscribing to a change event, and even updating values all work through the same set of simple callbacks so my code just worked no matter what happened to the data.
FirebaseDatabase database = FirebaseDatabase.getInstance();
database.setPersistenceEnabled(true);
Firebase Database also managed all the networking constraints automatically. Fetched data is locally cached to persistence, and value changes are queued until they can successfully complete on the remote. This mean that my offline worries were handled without even giving it a second thought. I can't tell you how many times I tested this part because I just couldn't believe it could be that easy.
NOTE: It's a good idea to cache the root DatabaseReference
(and possibly others that get referenced often), otherwise Firebase will end up
doing more disk reads than you probably would like (at least on Android).
Firebase Notifications
During the conference, we want to be able to reach out to everyone attending as best we can. There's a lot going on over the course of two days and nobody wants to feel like they missed something important. The obvious choice here is to integrate a cloud messaging solution.
With Google Cloud Messaging transitioning to Firebase Cloud Messaging (FCM), it was nice to have a solution to this already built-in to the tool. Specifically, Firebase Notifications presented a seamless way to create, schedule, and send notification messages to users directly from the web console. I didn't have to write a single line of server-side code to push those messages (I think you understand by now how much I didn't want to do that).
On the client side, you can get away with writing literally no code here if
you wish. To capture messages when your application is in the foreground, however,
a custom FirebaseMessagingService
should be integrated. The simple one we put
into the 360|AnDev application is all of 30 lines of code.
FCM is capable of so much more, but using Notifications is a simple way to get started with cloud messaging that also includes analytics on user engagement from your messages. I fully expect that I will never look at this, but some people absolutely love those metrics so I think they're great too!
Not All Ponies and Roses
While things went remarkably well integrating Firebase, there were a few drawbacks that I felt were worth mentioning. The first is the feature set of the Firebase data console. Since our use case meant manually entering and maintaining the data set (rather than having a web application do it), I relied very heavily on the web console — and it made me grumpy more than a few times.
Adding new entries in the console is not the easiest task. Especially if those entries are nested objects. Objects can't be created empty, and if you want to add elements to a new object you have to either hand-write the JSON in the "value" field or craft the object with it's first child key and then iteratively add the rest. Object cannot be moved between parent keys either. Overall, the data entry was just a tedious process - though I realize my use case probably wasn't on the the top of their priority list. Nevertheless, improvements could be made to the console editor to make data manipulation more friendly.
Along the same lines, the JSON import feature is a bit too heavy-handed. I found myself exporting the JSON a lot and manipulating the data in a separate tool to compensate for the lacking features in the web console editor. The problem is that the JSON import doesn't support importing partial data. I can't edit and import the data under just one child, I have to import the entire data store again. The import assumes that nodes which are missing ought to be deleted, rather than simply left alone.
Database Security and Rules
A more subtle issue came with configuring database access rules. Much
attention is given in the documentation to the appropriate values for read
,
write
, and validate
elements, but the structure of the rules themselves
is never really discussed. It took me far too long to determine that a read
rule for the path root/child/item
should be:
{
"rules": {
"root": {
"child": {
"item": {
".read": true,
".write": false
}
}
}
}
}
Similarly, the use of wildcards to match any part of a particular path doesn't receive enough attention in the docs, in my opinion. As far as I can tell, variables are the only way to do this — and I discovered that by pure trial and error.
Summary
This was my first experience with Firebase and I probably did a ton of things wrong. Overall, though, I'm pretty impressed by the product, and I look forward to learning more about it so we can make the 360|AnDev 2017 app even better! Who knows? Maybe I'll even shed my web fear and build a server-side application to feed the data next year.
Join Us at 360|AnDev
Android experts from Google and the community are descending on Denver, Colorado for two days of technical sessions and summer fun in the Mile High City. Chat with Jake Wharton about Java 8 features, ask Romain Guy your ConstraintLayout questions, or discuss the inside details of RecyclerView with Yiğit Boyar.
For making it all the way to the end of this article, here's a registration coupon for http://360andev.com/#tile_registration[360|AnDev 2016^]. Use the coupon code DroidCommunity for 15% off when you register!
So why haven't you registered yet? You need to be in Denver July 28-29!