aapt, aapt 🎶

This week is the Android release for Elements.

I'm a bit ashamed to admit that over the past couple of years, we have been neglecting the Android toolchain a bit. Google introduced some significant changes to their tooling a while back, including the new d8 engine for converting Java byte code (which our compiler for Java and Android emits) to Android's Dalvik bytecode, and the new aapt2 tool for processing resources – a very messy system on Android, if you ask me.

These new tools broke a lot of things, and their usage (outside of Google's own Gradle build toolchain) wasnt'/isn't very well documented, and at some point we just kind of threw the towel 🤷‍♀️. Simple Android apps are still built, but anything more complex depends on dependencies and resources had problems getting past aapt2.

Over the past month or so, I've been working on the side to bring one of my personal pet projects back to life. At first, the plan was to only focus on the iPhone version (done and done), but my partners in crime at the Meteorological Department Curaçao convinced me to also take another stab at reviving the Android version – Android being a very popular platform here.

Just like with iOS, this started by taking a deep dive into our Android toolchain in EBuild, and making many improvements. And i'm happy to say that with the help of a good friend, I was able to finally sort out all the intricacies with getting aapt2 and the rest of the gang to work as they should, and consistently. This involved improvements and fixes to

  • Gradle/Maven package resolving
  • Pre-processing of resources from .aar ("Android Archive" – essentially a .zip with a .jar, resource files, and other stuff)
  • Pre-converting ("pre-dexing") external .jar references
  • Build caching
  • Packaging the final product
  • ...and more.

In the end, my existing (at this stage, pretty old) app once again builds okay – with virtually no changes to the code needed, so I'm now ready to work on it again.

Android Push Notifications

With that out of the way, I set out to do one more Android-related task that I had been postponing for a long time, and that is implementing a clean system for Push Notifications for Android – which leads me to a small teaser for an upcoming new product.

When I first started working on Curaçao Weather, almost 10 years ago now, one of my goals was to make the app essentially "serverless". Yes, there is a server component that performs regular, scheduled processing of data (such as gathering weather data from multiple sources and putting it into a consistent format that the app can rely on). But the app doesn't talk to that server. Instead, all the data is stored in a semi-public S3 bucket whenever the processing runs, and the app can just download all the information it needs from there. I simply didn't want to worry about scaling issues (even though I am, of course, sure our software stack can handle them – it's what it was designed for, after all). But just plain static HTTPS removed a lot of that complexity.

But there were two features we couldn't handle with just that, and those were letting users send reports for weather impacts from the app back to the server occasionally, and – more importantly – handling Push Notifications.

Being a big fan of Amazon AWS in general (we use it for all our hosting, and much more), I turned to two solutions provided by AWS for solving this – even though I was reluctant to rely on third-party abstractions like that, and would end up being proven right.

AWS provided/provides abstracted support for cross-platform push notifications that merely required some (convoluted) setup on their system, and use of Amazon's client library inside the app – both on iOS and Android.  The system worked well... until it didn't, some five years ago, when it just stopped working. And, being a convoluted abstraction on top of many lower-level AWS systems, it was impossible to get to the bottom of it – so I scrapped it all, and implemented Push myself (something I had done before), but for iOS only.

I still liked the idea of being "serverless" for this app, so I thought: if I did have to create a server for the app to talk to, why not make it a general-purpose server for any app that needs similar functionality?

And with that (and some other ongoing projects), a new set of twin projects had been born:

Quantum Server & RemObjects Infrastructure

QuantumServer and RemObjects Infrastructure are two new products we have in the works, and they are, if you will, flip-sides of the same coin.

RemObjects Infrastructure is a set of Enterprise-level libraries (primarily for .NET, but some cross-platform) that implement functionality commonly needed in enterprise server back-ends. It includes things such as login and identity management, abstracted file storage, Push Notifications and email, AI model access and AI chat, and much more.

It builds on top of Remoting SDK and Data Abstract (where applicable), built on Oxygene, and is meant to be used by developers creating their own backend. While not publicly available yet, it has been successfully deployed by a range of initial development partners who helped drive its development. CodeBot in Fire and Water is also built on the AI layer provided by Infrastructure.

It is also the foundation of Quantum Server.

RemObjects QuantumServer is a stand-alone precompiled server application that exposes (or will expose) much of the functionality provided by Infrastructure, but without the need to build your own backend. You just install and configure it, then focus on creating "client" applications that can depend on it.

Curaçao Weather was one of the first projects to use QuantumServer, and now uses it for Push Notifications on both iOS and Android, as well as "dead drop" for one-way delivery of reports users want to share with the weather department.

As a result, I was able to drop any third-party dependencies on the AWS client libraries and similar components from the app.

Read more: