Reflection on the development of Animol – an Android app for Chemistry

The summer, I took a job offer from a lecturer that taught me in the last semester. The task was to develop Animol – a “simple” Android app for a lecturer from Chemistry department. The main functions proposed were displaying videos and short info for different experiments, synchronising experiment data with the server, on which new experiments can be added. I was in charge of developing the Android app, there are two more students working on iOS and server respectively.

The app was release under NUS account, but is no longer visible in Play Store for some reason. There is a brief description about it on NUS website.

The initial UI proposed looked very simple, so I did not expecting to spend too much time on it. After all, accepting the offer would mean that I will be working on 2 programming projects this summer, the other one being the orbital. I thought that my experience in Android game development would make this an easy job. As it turned out, making a “normal” Android app is somehow harder than making a simple Android game.

I started working on the project in late May. To set up the basic structure of the app, I need to learn about ListView and ListAdapter, to be able to populate data into a list. This did not take very long. After reading a few tutorials, I managed to find a good template that includes a ListView and a ListAdapter for displaying a list of songs. After removing some extra items, the basic list layout was done. Along with the ListView I also learnt simple SQLite functions to insert and retrieve data from Android’s SQLiteDatabase.

From there I got the basic framework and started working on specific requirements of the project. The next big thing is the embedded YouTube video. This was relatively easy for me(as compared to my counterpart working on iOS version of the app) as Google provides a YouTube Android Player API. (It was only later that I found out the downsides of the API.)

As I expected, the part that took the most time is the layout/UI. I had one YouTubePlayerView, several ImageViews and  scrollable TextViews and the whole layout also needs to be scrollable. So I did some research and followed the recommended way: Wrap all the ImageViews and scrollable TextViews in a LinearLayout which is then wrapped in a ScrollView. I also need to add some codes in the Activity to prevent scrolling conflicts between the inner views and the ScrollView wrapper.

After several modifications according to the requirements, my UI for the app was accepted in the weekly meeting. Then we all started working on server communication, I had a few choices here. I can either use the DefaultHttpClient (inherited from HttpClient) from Apache for Android, or the AndroidHttpClient (deprecated). Since there were several templates for DefaultHttpClient, I just followed the templates and wrote a ServiceHandler Class(just a utility Class, not inherited from Service or Handler Class) that handles the http calls. Then, I can use AsyncTasks in my activities to call methods in ServiceHandler for server communications.

It was on 1 July that things that things got a bit messy. I got my new MacBook Air and decided to shift all programming related work there. It just so happened that Android Studio had update moments ago. So it was a cross-platform and cross-version migration of an Android Studio project. This caused me several problems:

First, the Gradle version needed to be updated for the new Android Studio version, however my project was already set up for the old Gradle version and there was no way to do a straight forward upgrade of my project. So I decided to create a fresh project and copy paste my old codes into it, saving time to research on solving the compatibility issues.

The other problem was that the new build versions (version 19 and 20) does not seem to have good support for the package com.android.support:appcompat-v7. So I decided to strip the support package and made my app only compatible with devices running SDK version 15 (Android 4.0.1) or above.

The last and the most annoying one is the rendering of the ActionBarView in Android Studio. For some strange reasons, after I migrated the project, all the views stopped showing previews in Android Studio, saying that there are some problems with the ActionBarView. It worked fine on phones but lack of preview made it extremely difficult for me to design the layout as required. So I raised the issue on stack overflow. It seemed that removing the appcompat package helped to some extent but the new views created still has errors in rendering. Hence, this problem is still not solved.

Having solved most issues with the migration, I then started on more sophisticated operations involving retrieving and processing data from server and updating local database accordingly, as well as sending app usage statistics(click counts for each experiments) back to the server. There was an interesting problem regarding the timing for server communication. Initially, my implementation was to fetch new experiments and send the counts when the user opens the app (via onCreate in the splash screen activity). However, the concern was that the Android user may not have the habit to close the apps and server communication won’t happen unless the user explicitly kills the app. Then I planned to change the implementation to sending the count  and fetching new data when the app is sent to the background, but the disappointing news is that this is very hard for Android to detect sending app to background unless I use some hacks(which may not work in a long term).

So to ensure that the count is sent to the server, I created a BaseActivity that extends Activity, in which onPause will trigger AsyncTask to send count and onResume will trigger AsyncTask to fetch new data. This implementation suited the purpose, but it cost too much network traffic. This is because when user navigates from activity A to activity B, onPause in A and onResume in B are both called, effectively meaning 2 http calls will be executed for each tap on the screen.

Hence, the final decision was to add an interval of 30 seconds between any two server communications. This means after the first server communication, a timestamp is saved to the SharedPreferencesSubsequent server communications will need to go trough a check on timestamp to see if 30 seconds has passed from the previous server communication. This way, we can be sure that when the user launches the app (or relaunch from background), new data will be fetched. And for each subsequent navigation, onPause will be called before onResume, ensuring that the count will be sent in the next server communication.

The next big thing is push notification. This function was not in the original plan, but we all agreed that this should be an important part of the app in the event that we want to notify the users of new experiments or announcements. As it turned out, Google was kind enough to provide a Google Cloud Messaging(GCM) service for Android. The implementation was quite straight forward, except for the fact that it requires Google Play Services, which could be a potential problem for phones purchased in other countries that do not have Google services pre-installed.

The last problem was to dynamically refresh the view when the database gets updated by background server communications. I did not researched into how I can get a result from AsyncTask in my activity and the Android app is structured such that the views are drawn in onCreate of the activity, via setContentView(R.layout.activity_main); .  So in order to refresh the view with updated data, I need to either redraw the whole view or detect the changes to database and update the corresponding view elements. And I can either do it in onResume or set up a listener for database activities. In the end, I took the easy way out and forced a re-draw of the views in onResume (with 2 seconds delay) for each successful fetching of new data in the background.

Overall, I would say that this an awesome experience for me. I learnt a lot of things, not only on Android development but also on server communication techniques involving http request/response and database operations with SQLite. I am looking forward to working on my next Android project, or even pick up an iOS one if I have the necessary resources.

[Solved]Get back Grub in Windows 8.1

I was using grub to dual boot my Lenovo Y410P with Windows 8 and Ubuntu 14.04.

Recently I finally decided to upgrade my Windows 8 to Windows 8.1 considering it should be pretty stable by now. However, to my horror(or rather not surprisingly), my default bootloader has been changed to Windows Bootloader which means I could not access my Ubuntu 14.04.

Usually this takes a while to fix, involving repairing grub/BCD and tend to be tedious. However, I managed to found a much simpler and direct solution to this.

With the new UEFI specification, we can actually choose the default boot manager instead of replacing one with another. All it takes is to go to UEFI Firmware settings and change the order of boot managers. Which means grub and Windows boot manager can co-exist somewhere in the hard disk and we can choose which one to use in the BIOS UEFI settings.

Accessing UEFI settings in Windows 8.1 is a bit different from what happens in Windows 8, you can follow these links:

http://www.thewindowsclub.com/access-uefi-firmware-settings-windows-8-1

http://acer-au.custhelp.com/app/answers/detail/a_id/32048/~/accessing-uefi-in-windows-8.1

The menu is something like this:

UEFI Settings

UEFI Settings

One you are in the UEFI boot priority settings, you can simply change the position of Ubuntu to the top so that grub will load when the PC is turned on:

UEFI Boot order priority setting

UEFI Boot order priority setting

(All photos taken by me)

 

 

Year 1 Sem 2 – Result and stuff

Uhm…

I did not do as good as I expected for this sem.

A- for CS2020, which is kinda still within expectations since I did badly for final.

B for CS2100, this is still acceptable considering the difficulty level of the final.

B- for IS1103, this is quite a shock for me because I thought I did well enough for final to get at least a B+. Well, maybe it is because of the first assignment in which I did not pay much attention to. Or maybe the instructor has lied when she said our group’s project looks fine.

B for PC1143, this is also depressing for me, considering the fact that I devoted a lot of time on this physics module. To be honest I did not really master the content as compared to the physics majors, but I tried very hard. Maybe I lacked some exercise to help me understand how to approach the questions in the final.

B- for GEK1505, although I was already planning to SU this module no matter what at the beginning of the semester, I did not expect me to get such a low grade for such an easy module. I thought I did okay for final, confident of scoring at least 60% of the marks, but the result is the lowest I could imagine. Maybe it is the bell curve, who knows.

Apart from the depression from the release of results, I remained happy most of the time, chilling in my house, playing games and watching TV. Maybe it is a good time to put more time into my 2 programming projects.

Good luck to the rest of my holidays.

End of Year 1, Start of holidays

Today is my last paper for sem 2 of year 1 in NUS.

Not a bad sem, but certainly can be better.

I slacked through most of the semester, playing osu! and dota2. I did go to the lectures and tutorials, most of them. I also tried making notes along the progress of the modules for both CS2100 and PC1143 which are more content heavy. I guess it helped during revision since I can recognize the terminologies and understand the concepts better.

Still, I did pretty badly for all exams because I did not really study as hard as last semester. During the reading week and exam week, I put most of the time doing travelling around the campus and sitting in front of computer playing games or browsing through other people’ lives.

Let me try to predict the grades while I still remember how I did for the finals:

For GEK1505, I never really studied but I guess the concepts are okay, final is a bit hard so I guess I can get B+.

CS2100 final is a disaster, I left almost half question blank because I got stuck at the first structured question. Given my “still okay” CA marks, I should be getting B+.

IS1103 is okay, I did not do well for the first individual assignment because I did not know it was graded, but final and term report are okay, this should also be a B+.

PC1143 is hard, I could understand the concepts but I could not solve most of the questions in final. Given that the percentage of final is not that high, I hope I could get at least a B.

And CS2020 should be fine, except for the final where I did not perform up to my standard, A or A-.

Holidays, as usual, is packed with agendas.

First thing on my mind is my peer mentor position at RVRC. As peer mentors, we are supposed to organize an orientation event for the freshmen, this could take a long time, especially considering the fact that we have only less than 20 people in total now and we are all not very experienced in organizing orientation. I guess I will just try my best to contribute ideas and do some videos for the events. And I may also want to be some kind of “game master”, it looked fun to me when I was an OG kid.

I also need to do an orbital project with my teammate. This should not be too hard once we have our ideas laid down. We could try to use some new tools like Meteor. Hopefully we can spend several weeks on this and get a nice and useful application done.

I am also planning to do an implementation project with my CS2100 lecturer on Android. It looks easy to code, so should not take too long as long as I am not one coding the back-end.

Then I could also do some projects for Computing Club if I have time to spare, such as the “module tree” app which guides you in choosing modules throughout entire uni life.

I hope the holidays does not end up being dota2 everyday. Haha.