I started this project back in the Summer of 2019. Fresh off of a round of failed internship interviews and an Android programming class, I wanted to add something to my portfolio outside of school or work. I also felt like I had been ignoring many of my long time friends so I could focus on school. I wanted to reconnect with my friends and practice programming at the same time so I figured creating an app that would automatically text people on their birthday would be a great solution.
The Nuts and Bolts
It seemed like a simple concept and I liked the idea that the people on the receiving end of the texts would have no idea that it came from an app instead of me. I dove into the Android docs and decided that I could rely on Android to do most of the heavy lifting for my. My app essentially had four main tasks:
- Store Birthdays
- Get Today’s Birthdays
- Send Texts
- Repeat Each Day
None of these were groundbreaking concepts or required elaborate algorithms. In fact, all of these tasks are things Android does already. I just needed to figure out which API’s to use. And that is where I made my life more difficult than it needed to be.
Storing Birthdays
This wasn’t too hard, Android’s contact schema includes a birthday field. Since the Contacts app already has a way to handle adding and storing birthdays, I’d use that for now and integrate it later.
Getting Today’s Birthdays
My first thought was to retrieve all the contacts and compare the birthday to the current date. It seemed simple, but then I learned that retreiving contracts is not as simple as allContacts = getAllContacts()
. No, Android is built to handle multiple sources of contacts for multiple accounts so there are several API’s that require queries that are pretty similar to SQL. I didn’t know SQL so instead of learning it, I tried to find a shortcut.
I discovered that birthday events are automatically added to Google Calendar when you add a birthday to a contact. While calendar events are stored behind and equally cryptic database system, I found the code to get today’s events on StackOverflow and then parsed out events not containing the word ‘birthday’. It looked something like this:
Uri.Builder builder = CalendarContract.Instances.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, startMills);
ContentUris.appendId(builder, endMills);
Cursor eventCursor = cr.query(builder.build(), new String[]{CalendarContract.Instances.TITLE,
CalendarContract.Instances.BEGIN, CalendarContract.Instances.END, CalendarContract.Instances.DESCRIPTION}, null, null, null);
if (eventCursor != null) {
while (eventCursor.moveToNext()) {
final String title = eventCursor.getString(0);
if (title.contains("birthday")) {
birthdayEvents.add(title);
}
}
eventCursor.close();
}
Sending Texts
The code above gave me a list of people’s names who had a birthday today. I then had to figure out how to get their phone number and send them a text. I went to StackOverflow again and found code to retreive a contact by their name and retrieve a contact’s phone number by their contact id. Once I had all the data I needed, sending the text was pretty easy:
for (Person person: people) {
String destination = getDestination(person);
String message = "Happy Birthday " + person.getFirstName() + "!";
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage(destination, null, message, null, null);
}
Repeat Each Day
For the last step I just needed to schedule a repeating task that did these steps once a day. Android has several methods of scheduling tasks. I settled for using a JobScheduler
because it was the first way I could find that let me schedule a task on an exact 24 hour repetition schedule and not be interrupted by rebooting the phone. The downside is I didn’t create a method to select what time the job runs. Instead, it just runs every 24 hours from the second it’s started by the app. Meaning, you have to wait for the time of day you want texts to be sent to start the job.
The Results
With that all done I declared my app a success!
Yes, I agree. It looks amazing.
Over the next few months I let it run and it worked excatly as I wanted it to. I just didn’t take into account that I may have waited a little too long to reconnect with my friends…
There were three types of reactions to my automated texts: they were annoyed, I was annoyed, or they genuinely appreciative which made me feel guilty. I told a lot of my friends about this super cool project I was working on so when they got a text from me they knew it was fake and were annoyed that I didn’t personalize it to them. People who I hadn’t talked to in months were excited to hear from me, but I got annoyed when they asked what was new in my life. I didn’t want to have a small talk conversation over text so I never responded. Some people were actually (as far as I could tell) happy to get a text from me and didn’t know that it was fake. Their genuine response made me feel like I was tricking them into thinking I cared about them. Though, I’d argue this app shows more that I care about them than just texting because I spent hours making sure my phone would text them instead of taking 30 seconds to text them myself…
At this point school got busy so I just left the app running for the next 6 or 7 months. I had to do a quick patch because my brother’s last name has an apostrophe in it (yes, it is also my last name) which broke the contact queries. Aside from that, it worked great and I felt accomplished.
Starting From Scratch (Again)
I work as a back end developer so I wanted to get some more experience on the front end. In Spring time 2020, I took a design class and I decided that I could make an actual interface for this and rewrite everything in Kotlin while I was at it.
Covid had shut everything down so I had hours and hours to time at home to figure out how to build an interface in Kotlin. I was really happy with how concise Kotlin is compared to Java and it felt like I didn’t have to search as long to find answers to how to do something. I started out with mock designs in AdobeXd and did user testing and ended up with this as my final product:
This class was only focused on the design so this wasn’t functional. Over the Summer I took the time to rewrite the logic in Kotlin and do it in a more efficient way. Instead of relying on the calendar events I learned how to create a query that would retrieve the contacts I needed with their phone numbers included. I also created a database for my app that would store which contacts were supposed to receive a text. I added a contacts tab that allows users to edit contacts birthdays within the app and choose if a contacts name should be included in the message.
I’ve got all of that pretty much working. I redirected all the messages to my own phone while I’m working out the bugs. I’m also still working on figuring out how to let users set the time the texts are sent at. I have some good ideas on how to do that and maybe one day I’ll get around to polishing everything and publishing it on the Play Store.
If you’re interested in the source code take a look: First Approach Second Approach