Facebook Login: Lightweight Facebook Library for Android

Integrating Login With Facebook is a common feature in almost every app we develop at Green Halo Labs. More often than not, what we really need is just the Facebook user’s Access Token.

The current Facebook Android SDK has 2,942 methods (181 of those from the Bolt framework). With the current Dex Limit issue most Android developers are having, saving a few thousand methods makes a difference.

My friend Eric Butler (@codebutler) suggested that I extract only the Login part from the Facebook SDK.

The result is this library which only has 250 methods. All it does is return the Access Token after the user authorizes the app. Like the official SDK, it launches the Facebook Android app if it is installed, Otherwise, it uses a Web View.

The library is available on Maven Central and the source code can be viewed at GitHub: https://github.com/greenhalolabs/facebooklogin.

 

Why It’s Time To Support Only Android 4.0 and Above

Part of developing on the Android platform is dealing with the dreaded “F” word which is FRAGMENTATION.

It’s what tech blogs mention when they write about Android. It’s the word that scares some developers away from the platform. It’s what Apple love to put in a pie chart in their product launches to prove that iOS is the most amazing mobile OS yet.

Personally, I’d rather see a Fragmented Android than a Fragmented Mobile OS ecosystem. It’s likely that without Android, we’d be developing apps for Sony OS, Samsung OS, HTC OS, and so on. I can’t imagine that Apple would actually let other companies build phones using iOS.

But still, Fragmentation is a pain. If it can be minimized or eliminated entirely, I’d be happier.

Until recently, I was working at Wedding Party (http://weddingpartyapp.com) as an Android Developer. The app was supporting Android version 2.3 and above.

To create consistent UI for all versions, we used the ActionBarSherlock and HoloEverywhere libraries. Animations should be carefully done since one that runs smoothly on 4.x would, more often than not, be sluggish on 2.3.

The Wedding Party app also deals with a lot of images. High-resolution images were out of the question because it uses a lot of resources & using multiple of these images in one screen would almost certainly crash on older devices.

At Google I/O back in May, Jeff Gilfelt started giving away stickers that says ‘minSdkVersion=”14”’. It was a well-received campaign among Android developers that got this conversation started.

In the same vein was Reto Meier’s talk “Android Protips: Making Apps Work Like Magic”.

What struck me the most was Meier’s advice: “Skate where the puck is going” and “Create the best possible app for every user especially those on the latest devices.”

Jeff’s minSdkVersion=14 sticker campaign and Reto Meier’s talk made me think about the Wedding Party app.

Because we were supporting older Android versions, it was holding us back. We were skating where the puck was. Before we develop new features for the app, we needed make sure first that it would work on older devices.

After Google IO, I pitched the minSdkVersion=14 idea to the Wedding Party team. There were some hesitation at first but after looking at our Android stats and the pace of our development (development of Android app was at least six months behind the IPhone), we were convinced that minSdkVersion=14 was the way to go.

Installs for the Wedding Party app is constantly growing since its release for all versions of Android. While the overall number is getting bigger, Android 2.x’s slice of the pie is shrinking. Share of the Android 4.x devices, on the other hand, is growing at a fast pace.

What we did was create two versions of our code. Our current code would be for 2.x devices and we created a new branch of the code for 4.0 and above.

As a developer, it made my life easier.

We removed all the 3rd-party compatibility libraries and purged all code specific to supporting older devices. We became more adventurous with the UI especially with the animations. We switched to using high-resolution images without much issue.

Our automated (Robotium) tests run more consistently. (On Android 2.x, we had to use longer timeouts so the tests would not fail.) We also had fewer phones to do our manual testing in.

Overall, our development time was a lot quicker. For a good stretch of time, we were able to do weekly releases except when developing major features.

While we only actively developed for 4.0 and above. Our 2.x users can still download an old version of the app since Google Play has Multiple APK support.

When we made the decision to stop supporting older devices, we made several assumptions.

Owners of older devices do not expect a high-quality app. Fortunately, there wasn’t much complaints from users on why some features are not available on their phones.

Since a large part of Wedding Party users are in the US and US smartphone users would likely have newer devices, Android 2.x share would continue to shrink over time. (Android 2.x % for Wedding Party have been dropping a few percentage points every month).

Our decision was made a lot easier knowing that several developers went in the same direction.

Popular apps like Vine & the latest version of Holo Sudoku  only supports 4.0 and above and there wasn’t much of an uproar.

More recently, Square Cash and Flyne have the same requirement.

Jake Wharton, who works on Android at Square, also popularly known for his ActionBarSherlock library, said that developer productivity was the main factor on why the Cash app only supports 4.0 and above.

Developer productivity is #1. The app cannot ship unless it gets finished. Cash was developed primarily by one person with a tiny bit of support from other Android engineers. Could we have supported Android 2.x and hit our ship date? Probably. Could we hit our ship date only supporting Android 4.x+. Absolutely. Cash is a beautiful app. This can be achieved on Android 2.x but it requires more effort.” says Jake.

The type of app Cash is was also something they considered. According to Jake, “We conducted some simple research into our user base and have seen that the kinds of people who would be willing to download an email-based money moving product on Android are overwhelmingly on 4.0 and above.”

NPR will also support only 4.0 and above in their upcoming app which will have streaming audio and video.

According to Mike Seifollahi, one of developers building the NPR app, “codec support on older devices is hit or miss.  When trying to deliver the best user experience for our streaming audio and video content, being able to support the right codecs is essential.  Having to write/deal with software decoding for older device support is not a good use of resources.”

Android 4.0+ APIs also shows the maturity of the platform.

”Android 4.0 is a grass-is-greener ideal that actually is the greenest damn thing you’ll see. APIs are sane and normalized. There are new APIs for rich, dynamic, declarative development that allows you to engage the user more effectively. This version of Android is the first which actually helps you write better apps.” added Jake.

Jeff Gilfelt shares the same sentiment. “API 14 is when Android got serious. When design became a first class citizen and the default wasn’t ugly. It was a milestone release in many ways, and in 2013 I think it is a sensible line in the sand. Furthermore, multiple APK support in Google Play means you can still distribute a stable legacy version of your app to new customers who are running older platform versions.”

There may be some cases where supporting only 4.0 and above may not apply. If your app relies on network effects (similar to Twitter or Facebook) and/or target a worldwide audience (specifically India and China), you might need to support older versions.

If your app does not fall in the above categories, the positives of minSdkVersion=14 greatly outweigh the negatives.

With the holiday season coming, expect the share of Android 2.x devices to fall sharply. A huge number of Android device activations happen during this time and all of them would have at least Android 4.0. I won’t be surprised if 2.x share would be in the single digits by January 2014.

To reiterate Reto Meier’s point above, let’s start building the best possible Android app for every user.

Now go to your AndroidManifest.xml and change the minSdkVersion to 14!

How I Built My 1st Glassware: Glass To Phone (Part 1 of 2)

I received my Google Glass in May 8 which finally gave me access to the Mirror API. After a week of using it, I finally had an idea for what app I should be building for it.

On Glass, there are only limited options to which social networks you can share your pictures. Among them are Google+, Facebook and Twitter.

I wanted a way to share my photos to pretty much any app I wish. For me to do that is by having access to my photos on my phone.

This is why I built Glass To Phone (http://glasstophone.com). It’s a pretty simple app that acts as a Contact in your Glass.

glass-to-phone-contact-photo

When you share your photo to Glass To Phone, it will be downloaded to your phone and you can share it to any of your Android apps or move it to your photo gallery.

Glass To Phone has web and Android apps. The web app was developed using Python and Django and is hosted on Heroku.

Android was done natively with Google Play Services for authentication, Kevin Sawicki’s http-request for Http & Square’s Picasso for image loading. You can download the Android app on Google Play.

glasstophone_small_1

glasstophone_small_2

The database used by both the web and Android apps is powered by Parse.

Initially, I wanted it to be just an Android app. However, Google Play Services does not allow your app to request offline access so I was forced to have a web client.

The web app has the authentication to access the Glass Timeline. I also needed offline access for the callback page that the Mirror API hits when a user shares to my app.

For Part 2, I’ll go into detail on how I built the web & android apps including the code.

FourSquare Hackathon Entry: Burp’s Most Popular Places By Checkins

My co-founder Dan Kwon (@dankwonjr) & I built a small app for the FourSquare Hackathon a few weeks ago.

It ranks Popular Places for Barbecue, Fried Chicken, Wings and Burgers in different cities. Check it out!

http://goburp.com/popular/

Sign In With Google & Get User Info from Google+ Profile

At the start, authentication options for our site Burp (http://goburp.com) include regular email/password & Facebook Connect. For quite a while, I’ve been wanting to integrate Google Accounts Authentication.

I’ve looked at django-socialauth (http://social.matiasaguirre.net/) but it uses OpenID. I prefer a pure OAuth2 implementation similar to what Facebook & FourSquare uses.

Looking at Google’s documentation, it’s not easy to figure out. The Federated Login (http://code.google.com/apis/accounts/docs/OpenID.html) is just a pain to implement.

Google recently streamlined their API & they have libraries for every major programming language. Implementation is too complex though which includes a separate model to store credentials (see http://code.google.com/p/google-api-python-client/source/browse/oauth2client/django_orm.py).

OAuth2 implementation by FourSquare & Facebook is so simple that there must be a way to do that with Google: Get an authorization url, Get a code back & Exchange that for an access token. Then use that access token to access the API. Google has documentation for OAuth2 but it actually lacks information on how to get a user’s email address (http://code.google.com/apis/accounts/docs/OAuth2.html).

After scouring the internets, I finally stumbled into a PHP implementation. It has the scope (https://www.googleapis.com/auth/userinfo#email) that I’ve been looking for which is missing from Google’s documentation (http://code.google.com/apis/gdata/faq.html#AuthScopes). The OAuth2 steps are pretty standard except that the access token can be added to the header of the request instead of as a parameter in the url (http://code.google.com/apis/accounts/docs/OAuth2.html#CallingAnAPI).

This, however, only gets me the email address of the user. I also want to get the user’s name, location, gender, etc.

Luckily, Google just opened up an API for Google+.

By adding the scope – https://www.googleapis.com/auth/plus.me – to the OAuth2 call, our app will have access to the public info the user provided in their Google+ Profile. The People:get method (http://developers.google.com/+/api/latest/people/get) will provide you with the user’s Display Name, Location, and Profile Picture Url among others.

You can view the sample Django project at https://github.com/dannyroa/sign-in-with-google.

Taskyo: Access Google Tasks on your mobile device

I’m a big user of Google Tasks. It’s barebones but I like it mainly because of its integration with GMail & Google Calendar. However, Google doesn’t have a mobile-friendly site to use Google Tasks.

Over the weekend, I built Taskyo (http://www.taskyo.com). It is not meant to replace the main Google Tasks site but instead supplement it. This is why the features for Taskyo is limited – no editing of lists, ordering of tasks among others. Being able to create a list, create a task, marking a task as ‘Complete’ and deleting a task pretty much covers everything you need when accessing it on the go.

I built this using Python on App Engine and JQuery Mobile. It works well on the phone and on the tablet too.

Developing this app also allowed to me play with the new Google APIs for the first time. I really like what Google did. All the APIs are consistent and centralized. There are libraries for Java, Python, and PHP. The API Explorer (https://code.google.com/apis/explorer/) was particularly useful.

I found some hiccups though especially how to do OAuth2. The authorization example they have for Google Tasks (http://code.google.com/apis/tasks/v1/using.html) was not for websites. But having worked on the Twitter & Foursquare API using OAuth2, I eventually figured it out. With the other issues I had, the Google Tasks Developer Forum helped me solved them (http://code.google.com/apis/tasks/forum.html).

Taskyo

MapMyPhotos Now on Android Market

After a week of development, my new Android app, Map My Photos, is now available on the Android Market. It comes in a Lite version (Ad-supported and only 50 photos) and Paid version ($0.99; No ads and unlimited photos).

Map My Photos lets you browse your geo-tagged photos from the camera folder by cities and on a map. This is similar to the IPhone’s built-in Photo app.

Available on the Android Market:

or if you are browsing from your Android phone, click here.

2010: Year In Review

Career:

I was employed full-time 7 months out of the year which is a one-month improvement from 2009. I was supposed to work for Movity (Winter 2009 -YCombinator) and be their first employee. But right before the YC session started, I got offered a job by another startup. I consider the Movity founders good friends but I had to make an objective decision and joined Mingle.com instead. I felt bad backing out at the last-minute but it turned out really well for Movity since they got a more talented developer in Zain (@zainy).

I didn’t leave Movity completely. I helped them out during the YC session.  On weekends, there were seven of us cramped in a very small office. It’s one of my most enjoyable coding experiences where I was surrounded by people who are focused on one goal.

I worked for Mingle.com for seven months. I learned a lot more about Django since I was surrounded by smart & experienced Django developers (e.g. @david_ziegler). I left Mingle last July when I decided I need to do my own startup. To pay the bills, I did a short-term, part-time gig for Votizen.com.

Health & Fitness:

Working a lot has taken a toll on my health earlier this year. Working full-time at Mingle and part-time for Movity stressed me out a lot. It weakened my immune system and this led me to get shingles. Fortunately, it wasn’t a painful experience and I just had to rest for a week.

Despite that, I was generally healthy in 2010 and able to play sports a lot. I had the motivation to work out a lot even just by myself. I don’t have the workout regimen I had back in 2008 though when I was doing ActiveX at my old company in San Diego.

I started playing water polo again but my stamina wasn’t there. I ended up ruining the game for other people. I quit after a month but I plan to be back sometime in 2011.

I did Mission Bay Tri again (my second sprint race) and improved by almost 10 minutes (From 1:29:29 to 1:20:10).

I joined the Palo Alto soccer league in the summer and  started running with Burt (@burtherman) & Brian (@dustball). I had to stop running though after having some foot problems. I got an Xray and found no broken bones. Therapy helped a little bit but I basically can’t run more than 5 miles now.

Bay Area:

Hacker Dojo in Mountain View is my second home. Well, actually, I spend a lot more time there than at home. The place has great energy and I became friends with a lot of good people.

I got sick of the Bay Area for a little bit. This area is inside a bubble in both good and bad ways. Bay Area sets a lot of technology trends but it is not mainstream. What happens here is very different from the rest of the US and even the world but Bay Area people think that it is the same everywhere else.

This has led me to shun a lot of networking events because of the group-think. This is also why I decided to travel to Argentina, to get away from the area for a bit.

I still love the Bay Area though. This is where I belong and I can’t imagine being anywhere else.

Travel:

The only travel I did was Buenos Aires. I went with my cofounder Dan Kwon (@dankwonjr) for a month. It was more of a team-building for us. I learned a lot about my cofounder and also about myself. I have been a loner for the past few years and it’s refreshing to hang out with somebody a lot and hear what they think about me.

Lessons Learned:

Never settle: Time and time again, settling for something has brought me unhappiness. I have always wanted to have my own company but I tried to convince myself to stay at Mingle instead. This has led me to be unhappy at work. I finally came to my senses and resigned. I’ve been happier since. I work on projects I’m passionate about and started building a startup with @dankwonjr. There are some financial uncertainties though since I don’t have a lot of liquid savings so I do some part-time work from time to time.

Always Be Positive: It’s been tough for me since I moved from DC to the West Coast. I became a bit negative and it has held me back on a lot of things. Lately though, I make it a point to be more positive. I always try not to get angry and not complain. This is largely influenced by the people I surround myself with. I plan to continue this habit indefinitely.

Believing in Myself: I doubt myself a lot. It has gotten worse when I moved to the Bay Area. I’m surrounded by more intelligent and more experienced developers. The good thing is this motivated me to get better by learning new things. I picked up Python/Django in 2009 and it paid off for me in 2010. I also have been doing a lot of Android development. Learning a new programming language or framework doesn’t intimidate me anymore. I’m also not scared to take on projects that maybe over my head. I know that I can figure out a way to build it.

===============================================================================

2010 was a good year for me but it is actually more of a build-up for the great years to come. For the next few years, my plan is to continue learning and be more open to new experiences.

Default values when creating new row in Django Admin

In one of the apps I’m developing at work, I wanted to make it easy for our content admins to create a new row in the Django Admin. Most of the time, they need to create a new row that is associated to their own user account. It would save them a couple of steps if the user field is set to a default value. Thanks to my coworker, Dave Ziegler,  for helping me  figure this out.

Extra tip:
use raw_id_fields in Django Admin. This is especially useful when you have plenty of users. What you’ll see is the id of the user in the text field with a link to look up users next to it (instead of a dropdown containing usernames of all the users).
If you don’t set the raw_id_fields, it would take a long time for Django Admin to load the ‘Change ‘ page since all the users in your database needs to be loaded.

Diving into Google Chrome Extensions Development

Last Friday, I  joined CodeFest2 which is part of the AddOn Conference.

I decided to create an extension that will display additional information when browsing a Craigslist Housing Ad. The additional information includes displaying the address on a Google Map and listing businesses (restaurants, bars, groceries, and gyms) nearby. You can find my extension, Craigslist Housing Helper here.

I have never developed a browser extension of any kind before. However, I wasn’t too intimidated having read that developing Google Chrome Extensions are very easy since it uses Html, Javascript, and CSS.

I started with the tutorial (link). It was very to follow and I literally had an extension running in 2 minutes.

I then proceed to working on my extension. I started with displaying the address of the Craigslist ad on a map. Luckily, one of Google’s samples, Mappy, exactly does that. I only had to tweak the code on how it finds the address.

Next, I used Ajax to access Yelp’s API. It was a simple javascript call and I was able to use JQuery.

I was able to get my extension running in less than 2 hours. I’m not sure how easy it would have been if I tried to develop one for Firefox. (Mozilla, however,  will be launching Jetpack soon that would allow developing of extensions using Html, Javascript, and CSS).

Here are some tips based on what I learned while developing my first Chrome Extension:

  • When testing your extension locally, there is no need to reload if you only made changes to the Html pages (e.g. background.html, popup.html). However, you need to reload if you made changes to the Javascript files.
  • If you have seen an extension that does some functionality of the extension you are developing, you can easily explore their code. Go to chrome://extensions and grab the Id of the extensions. Then go to C:Users{ your username }AppDataLocalGoogleChromeUser DataDefaultExtensions{ extension id } to browse the code.

  • Use Javascript frameworks. I used JQuery for my extension. JQuery has a number of functions and shortcuts that will help you in development. Same thing with using other frameworks such as Prototype, YUI, etc. You can either download the source, add it to your extension directory  and include it in “content scripts” of your manifest.json file. Sample: “js”: [“jquery-1.3.2.min.js”, “content_script.js”]. Alternatively, you can use Google’s Ajax Library and make sure you add “http://www.google.com/*” in the Permissions section of the Json manifest.

The next step for my extension aside from improving its UI is to have it automatically rewrite the Craiglist Ad and have Google Map and Yelp data appear in the same page. I tried it before but I had difficulty making the map work mainly because of the domain and Api Key conflict.

Also, modifying the content of the page is cumbersome since you can only do it on the content_script.js file. However, the Readibility extension seems to be doing something similar so I’ll be looking at its code shortly.

Overall, I enjoyed developing Chrome Extensions. Being able to use Html, Javascript, and CSS is a definite plus. Google will expose more of Chrome thorough the API so expect more powerful extensions in the future.