To start my journey learning Android, I chose to make a revolutionary app... A todo app!!
Fine, it's actually been made before. You can try out a few dozen ones on the Play Store. Still, none of them satisfied my requirements:
- free and ad-free
- location reminders
- phone notifications
- day of week/time reminders
- reminders disappear only after you mark them as Done
- persists data online so that I can access my data from multiple devices
- easy to reorder
Nice to have's:
- being able to add reminders by talking to my phone, Android watch, or Google Home
- getting notifications on my watch
- integrating with Google Calendar: it could send me invites to organize my weekend if it sees I am free to accomplish some tasks.
After trying out 7 of them, I figured I should make my own instead. It would be a good learning experience.
Based on my requirements, I listed the features I wanted for my minimum viable product (MVP):
- cloud storage
- location reminder
- reorder reminders
Then I considered how I could build it.
- Authentication: I may want to integrate with Google Calendar, so authenticating with Google is a good place to start.
- Cloud storage: should I use a SQL or NoSQL database? I've used both in the past and do not have a strong preference. NoSQL is slightly scary because I don't know about data sanity. What if I decide to change how data is stored, and a user uses different versions of my app, which expect a different schema? Scale-wise, I do not expect high usage, so it is not an issue.
For the backend, do I use a regular backend application? A Node.js or Golang application running on a VM? Or forego the server and use some managed database like Firebase Realtime Database?
- Client: should it be a web app, native Android or iOS app? If it is a native app, should it be built with a tool like Flutter or React Native so that I can build it once and it runs on both Android and iOS?
After researching a bit, here's what I found:
- Client: the Notifications API is not supported by most browsers (compatibility table). Only on Chrome and Firefox desktop. Not mobile web. Ok then, should I use Flutter or React Native, in order to support both Android and iOS? Should I go for pure Android? In the end I still wanted to learn stock Android, so I chose Android. And since Kotlin has been announced at Google I/O 2017, why not do Kotlin while we are at it? A further look at the developer pages on developer.android.com showed that it would be relatively easy to make the MVP. After all, I just need a list of items, a plus button to add new tasks. A second View to edit a new or existing task. Another cool thing I found was the parts about using geolocation. It seems easy to get the phone's location, and even reverse geocode coordinates to find the name of the place.
- Backend: I've never used a managed backend service before. I would always build my own backend application. However in this case, there is not much server logic. The app needs to store location and time reminders. The phone app knows where the user is, it knows the time too. When the criteria are met, show a notification. No server needed. I stumbled upon Firebase Realtime Database. One really sweet feature is the fact that it caches data offline, so if the phone loses connectivity, the app still works. Later when the phone goes online again, the library syncs again. For no extra work! Pricing wise, I anticipate usage to be really low, so I will comfortably stay in the free tier.
- Authentication: a quick search on Youtube for "firebase authentication android" returns the following video:
Firebase Auth UI, on Android (7min). In 7 minutes, the presenter sets up authentication by email, Google, Facebook with a few clicks, and a few lines of code. It just works! Even the UI is handled by the Firebase library. I'm sold.
- Nice to have's: while I was at it, I looked up how to add custom Assistant commands so I can talk to my watch, phone, or Google Home to add reminders. This video demos a simple application in 15 minutes. Doable too! Let's do it.
At this point I had decided on the stack:
- native Android app in Kotlin
- serverless using Firebase Auth and Firebase Realtime Database
Building the MVP
Learning from a tutorial
Not knowing Android much, I went through Building your first app. Installing Android Studio and its SDK and dependencies was straightforward. I went for the Preview version to get the latest and greatest. The tutorial was well-made. What most pleasantly surprised me was the Layout Editor. There is a ConstraintLayout that lets you place elements in your View with constraints relative to one another. This means that you can set up a whole View with only one level of hierarchy. On the Web, you'd have to make nested hierarchies of FlexBox layouts for example.
Publishing an app
Now that I had a (mostly empty) app, I wanted to make an end to end flow as soon as possible. So I went on to the Play Publishing Console. Before I could publish it, I had to fill out a few forms about my app. Name, description, whether it was paid or free, whether it had ads or not, if it complied with the law, etc. Then I uploaded the APK. That's the name of the compiled binary for Android.
Signing the app
The Console threw an error message upon uploading the APK. I had uploaded a debug build. It turns out Android Studio had generated a debug build of my application, and it was not even signed for publishing. I later learned that Android Studio, when compiling an app for testing on your device for the first time, sets up a keystore that contains a signing key, but only for debug builds. In order to publish an app, you have to set up your own Key store. I spent quite some time on the Android Studio page on app signing. Once you create your key store, you modify your project settings to add the signing config using your newly created store, then create a second flavor or your app: the first one is the default "debug". The one you create is the "release" flavor that uses the signing config.
After setting those up, you open the Build Variants tab and select Release instead of Debug, then build the APK.
The Console also requires at least
- 2 screenshots
- 1 high-res icon (512 × 512)
- 1 feature graphic (1024 w x 500 h)
I used those tools to quickly generate them:
- Screenshots: I took a screenshot on the emulator
- Icon: Launcher Icon generator
- Feature graphic: Android feature graphic generator. The tool doesn't vertically center the text, but for now it will do.
Since I did not want to publicly publish the app, I set up the app for an Alpha release: I added my email address to the whitelist, then release the app.
Publishing (to Alpha)
Publishing to Alpha only took a few minutes. The Console gave me a link to a sign up page to the alpha test of my app. After signing up, I was invited to go download the app on the Play Store. After installing, I ran it and it worked! Empty app.
Next I will talk about Authentication.