Over the past 2 weeks, I’ve been working on this Issue and the corresponding Pull Request is here. The feature request is pretty simple – when the application starts, it should sync the Birthday info of a new Contact if it’s given the required Android app Permission to access the Contacts. However, it is quite a tedious Issue to tackle as it’s concerned with a variety of Android development topics that I haven’t touched before – namely Threads and Android app Permissions. At first my approach to this problem was to use the Android WorkManager API but this proved to be way complicated necessary for the intended purpose and debugging it became a pain because it involved injecting new dependencies for the SimpleCalendar app.
So what was the solution that I ultimately ended up using? I used old fashioned way of using a Thread lambda function. It’s simple but it just works.
When you start an Android app, it always runs on a Main thread and you usually don’t need to worry about this because if your app is simple enough, one Thread should be enough and there’s no need to worry about multi-threading. However, if your app has grown large enough and there are tens of requests to be performed at the same time, you will need to learn and use multi-threading because if you only use the Main thread to execute all the resource intensive API calls, eventually your app will slow down and possibly crash as its UI becomes unresponsive to the user. In essence, the use of multi-threading is concerned with utilizing multiple Threads to execute API calls so that the Main thread – which is mostly concerned with the UI – would not be slowed down. Think of the process concept of multi-threading as organizing a group of people to perform multiple tasks that eventually aim to deliver one result. When you don’t use multi-threading, you’re essentially forcing multiple tasks upon 1 person and you can immediately recognize the problem.
Background Syncing of Contact’s Birthday Information
So how is Threading useful for implementing the feature request? It is useful because we don’t want to use the Main thread to run the background sync as the Main thread itself needs to run many function at start and there might be possible complications (i.e. race conditions) that might happen when we use the Main thread for this process.
As shown above, I spawned a new Thread to handle this background task. There are two functions to pay attention to in the above screenshot –
addContactsEvents() function basically takes care of handling how to process a Contact that has a Birthday information available in one of its fields. However, this only proceeds if the
PEMRISSION_READ_CONTACTS condition is true – which means that if the SimpleCalendar app has the Permission to read the device’s Contacts, it can then add a Contact’s Birthday information to the calendar.
Take note that the aforementioned process happens in the background – basically it doesn’t update the UI yet until the
updateViewPager() function is called. When the
updateViewPager() function is called, the UI (which runs from the Main thread) is updated since there are now new Birthday events added to the Calendar. Why is this the case? This is the case because the SimpleCalendar app follows the MVC (Model-View-Controller) architecture.
When 2 processes above are completed, the SimpleCalendar app’s UI refreshed with the new Birthday event of a Contact updated. In the following demos, I would cover all three cases possible when this feature is implemented.
SimpleCalendar when no new Contact Birthday
SimpleCalendar – A new Contact with Birthday information available has been successfully added
SimpleCalendar – The app has been denied permission to sync Contacts