Dec 4, 2015 - My First Android App

Since I purchased my first Android device, the much-loved Nexus One, I have had a desire to build and distribute my first app for the Android platform. Unfortunately, with each attempt on starting an app, I ran four of the most difficult roadblocks for a hobbyist developer: getting an idea for an app, finding the time to work on an app once an idea was found, not getting into paralyzing infinite loop of restarting the project each time the platform changed, and feature creep.

Finding good app ideas was never a hard thing for me, but finding one that I could work on in a short period of time and had a small scope that a single hobbyist developer could work on was another. Though I am certainly an experienced Java developer, working with the Android platform in itself has a small learning curve. Moreover, the ideas I had usually involved some sort of webservice as well, complicating the project in many ways. Questions like “What framework should I build it with?” and “What sync mechanism should I use?” to “How much is it going to cost to host this service?” and “What should I do about securing user data?” swam through my mind. The complications made the walls steep, and the first lines of code had not even been written yet. These questions usually discouraged progress, even though most of the answers to the questions were “Who cares? Deal with it later.”

However, there were other times when I came across ideas for self-contained apps that were fairly simple. I’ve repeatedly had one such idea, which essentially was a way for me to stop using Google Forms to track some information and use an app instead. It had a well-defined scope, and allowed me to explore some of the most important parts of the Android platform. But after starting the project, making some progress, and pausing to spend time on the other things that my life demanded my attention on, I found it difficult to go back to the project and continue where I left off, mainly for my third roadblock.

Whenever I had time to return to my app projects, Google released a new version of the Android platform. In earlier versions (pre-Honeycomb), this usually wasn’t a big deal since a lot of the changes were enhancements to the platform. However, after Honeycomb, there were a lot of UI-related changes: Fragments, Holo, then Material. I wanted the UI of my app to look-and-feel like it belonged on the platform. Rather than try to refactor the current code (which wasn’t much), I figured I’d restart the project, using the new paradigms from the beginning. This caused me to restart the project quite a few times.

Then, with each platform update, I got more ideas that could be put into the project. And with each idea, I’d stop what I was doing and start on the new idea. Sometimes, the new ideas were changes to things that I had already done, causing me to rewrite pieces over and over again. Feature creep and refactoring hell were my enemies at this point and my projects were caught in a state of perpetual “IN PROGRESS”.

It actually became a joke for me. I had been a part of the San Diego Android Developers Group for many years, practically from its start, but I hadn’t finished a single app. Long-time members of the group knew me and knew the problem I had. It was’t a technical problem, just a PEBCAK one. However, this past November, an app idea was sparked in me, with a small scope and with such limited UI (read: almost none) that it was nearly impossible for me to get caught up in the vicious stagnation cycles that paralyzed me in the past.

The idea stemmed from an annoyance I had with my fiancee’s sister’s (let’s call her A) use of Instagram. Since she had a tight-knit family and I was a part of it, I wanted to be involved in family (having known her sister since they were pretty young). The issue was that A wanted to keep some pictures she came across on Instagram. In order to do this, she would reshare the original post, open the image and screenshot it, then delete the post. However, because I had post notifications for her, I’d see a post notification pop up on my phone, but when I tried to open it, Instagram would complain that the post had been deleted. It was rather annoying.

I also felt it was pretty annoying that Instagram didn’t have a facility to save images to the device - but there were ways. I had had enough of the annoying notifications (she is a teenager, so you could imagine the volume of notifications I would receive), but didn’t want to sacrifice not receiving the notifications for her. So, after doing a little bit of research into the capabilities of the Android platform, I found a quick solution that almost required no UI. After one spending some time one Saturday coding it up, I had not only a working prototype, but a nearly-finished app (yes, the requirements of the app were that small).

I finished the app, and knowing that in order to distribute updates to the app I needed to use the Play Store, I published my app (at the time of writing this, the app is in public beta) so that when I fixed problems or added features, she would automatically get them on her device. Unfortunately, the original name of the my app was already taken (ironically enough by another app that did pretty the same thing mine did), so the first submission was rejected by Google. However, after renaming it and retrying, it was accepted as Keepagram and published.

So, that’s the long story behind my first app, Keepagram. It is embarrassingly simple, and in no way a shining example of the depth and breadth of my skills as as software engineer, but as someone who has been paralyzed by making my pet projects overly-complicated, I am very proud that after so many years I have finally been able to get something done.

If you’d like to join the public beta for the app, click here. I am definitely looking for feedback on it, so feel free to let me know what you think.

Jul 2, 2015 - The Exact Middle of the Year Redux

Over six years ago I wrote a post on my old Blogger blog about what I believed the exact middle of the year was. When I had written it, I remember feeling that the computations that I did were faulty since there was just something odd about the numbers I was getting.

Today, I remembered about my old post, on this year’s “Middle of the Year Day,” and wanted to revisit the computations that I used. Re-reading the post, the computations made logical sense, but, again, the result just felt wrong. Especially when you introduce leap seconds into the logic, things became much more murky. But then I realized something simple that I had actually accounted for, but was subtle and forgotten as you continued to read the post: the calculations that the exact middle of the year was made by grouping 4 years together, and dividing the four into equal pieces. Therefore, the calculation of the time of July 2nd at 15:04:34 is not “the exact middle of the year”, but rather the “quarter marker of the current leap year cycle”. In other words, on July 2nd at 15:04:34, we would be crossing another 25% through the current leap year cycle (in my parlance, a “leap year cycle” is every 4 years).

However, we do not usually look at the calendar and think about time in 4-year cycles. We usually subdivide time based on our non-scientific concept of a year, which means 365 days on a non-leap year and 366 days on a leap year. Thus, given this, the middle of the year - to the hour - is July 2nd at noon on a 365 day year. According to Wikipedia, we keep July 2nd at noon as the middle of the year on leap years too.

But, then there are timezones, so July 2nd at noon occurs at different times for different timezones. If you remained in the same timezone throughout the year, then the exact middle of the year would be July 2nd at noon for you, but if you were in Los Angeles and talked to someone in New York, you would find that they had their exact middle of the year 3 hours before you. To alleviate this discrepency across timezones, we could use a common timezone, UTC (or GMT), and just change the time for everyone depending on where you are in the world. Thus, if the exact middle of the year is July 2nd at 12:00 UTC, for myself living in the Los Angeles timezone, the middle of the year is July 2nd at 5AM (UTC-7 during summer time; or 4AM if you don’t take into account Daylight Savings, which is UTC-8). So, depending on how you look at time, you could celebrate the middle of the year at either noon or whatever time noon in UTC is in your own timezone.

So, six years ago, I sought to find the exact middle of the year, and over the last half decade, the concept of the “middle of the year” became complicated by leap years and seconds and timezones, and just the general perception of time. Though I may have missed this year’s crossing into the last half of the year, I feel better in knowing that I was wrong, because being wrong gave me the opportunity to look back at the question, and gave me the opportunity to evaluate my findings in a broader context.

May 31, 2015 - Setting up Magic Lantern on an Eye-Fi card for a T3i/600D

So today I wanted to take a quick detour from my normal software engineering posts and talk a little bit about a problem that I finally re-solved for my other hobby: photography. As many hobbyist photographers know, MagicLantern is an awesome open-source alternative firmware for many Canon cameras. I myself own a T3i/600D and have been using MagicLantern on it for a while now. I also own an old Eye-Fi GeoX2 card to make it easier for me to geotag and sync my pictures.

A couple years ago I managed to do what many said was difficult or impossible to do: get MagicLantern to work with the Eye-Fi cards. And the marriage between the two worked nearly flawlessly for a long time. However, a few months ago, the card had become corrupted and I had to low-level format the card. From this point on, MagicLantern did not want to work with the card. It did not help that I did not note down what I did to get the solution to work. I gave up on it for the time being, assuming that I would get back to fixing it at some point later.

Well, a much longer time passed than I expected and I now had a new need for my camera - and I wanted to be able to use MagicLantern’s features again. So today I sat down in front of my computer & began hammering at it to get it to work. I finally came upon the answer and got it working.

  1. Copy the images that are currently on the Eye-Fi card by connecting the card to the dongle that came with the card, and let Eye-Fi sync the images. To make sure Eye-Fi didn’t miss any images, manually copy the images again to another place off the card.
  2. Eject the Eye-Fi card. Then end the Eye-Fi Helper service.
  3. Plug the Eye-Fi card back in, then use Explorer to format the card. Do not do a quick format - do not select “ExFat” as the file system type.
  4. Open the MagicLantern firmware in 7-Zip, then select all the files and drag them to the root of the Eye-Fi card.
  5. Eject the Eye-Fi card.
  6. With the camera off, switch the camera to “M” (Manual) and make sure that there are no accessories (except the lens, of course) attached.
  7. Insert the Eye-Fi card into the T3i/600D.
  8. Turn the camera on. If the firmware update menu for MagicLantern shows up, great! Otherwise, press Menu and navigate to “Firmware v…”
  9. Click on the “Firmware v…” to update the firmware and enable MagicLantern.
  10. Once the menu mentions that the card has been marked bootable, turn the camera off, wait about 5 seconds (make sure the busy LED is not illuminated), then turn the camera back on.
  11. At this point, MagicLantern should be installed. You will notice the time show up and the free space of the Eye-Fi show up in the bottom-right corner.
  12. Go to Menu > Eye-Fi Settings and Enable the Eye-Fi card to attempt syncing again. Once the sync is complete, you can turn off the camera.

As you can see, the process is not very difficult - it just seems like a lot of steps because I’m a bit verbose. However, from this point, you should be able to take advantage of both Eye-Fi’s syncing and MagicLantern’s features on your T3i. However, don’t rely on this - things can still go wrong, as they did for me. Your results may very.