Thursday, October 18, 2012

Android AutoCompleteTextView suggestion list from an external Web Service

Android offers an AutoCompleteTextView widget. If you peer into the source code of the AutoCompleteTextView widget you'll notice that it contains a ListView that renders the suggestion list. This ListView is generally fed by an ArrayAdapter. It's fairly trivial to stick an array like data structure in this ArrayAdapter to display suggestions. This works well for static data. However, if you plan to poll an external Web Service to build your list of suggestions, things get tricky. My first thoughts were to build a custom ListAdapter that would go out to the Web Service on every getView() call. I quickly discarded that idea since it wouldn't mesh well with the ListAdapter/ListView interaction model. I finally settled on using a custom Filter to build the suggestions list from a Web Service. An added advantage of using a custom Filter is that the filter() method is run on its own worker thread. This obviates the need to make the web service call on an AsyncTask. Here's the code:

    private class AutoCompleteAdapter extends ArrayAdapter {
        @Override
        public Filter getFilter() {
            //This is important.
            return new MyFilter();
        }
        
        final class MyFilter extends Filter {
            @Override
            protected FilterResults performFiltering(
                    CharSequence constraint) {
                //This method gets called on a worker thread
                //so no AsyncTasks required here
                FilterResults result = new FilterResults();
                try {
                    URL feedUrl = new URL(...);
                    URLConnection conn = feedUrl.openConnection();
                    InputStream is = conn.getInputStream();
                    //Read from InputStream
                    //Build a List of suggestions
                    result.values = suggestions;
                    result.count = suggestions.size();
                } catch (MalformedURLException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                } 
                return result;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                clear();
                if (results.count > 0) {
                    for (String s : (List) results.values) {
                        add(s);
                    }
                }
                notifyDataSetChanged();
            }
        }
    }

Tuesday, September 25, 2012

When my little boy grows up


In no particular order, when my little boy grows up:

I'll miss...
.. how he runs and hugs me when I come home
.. how he looks at me with big curious eyes when I explain something
.. how he assumes that his daddy can do anything and everything
.. how he loves it when I hold him close and read to him
.. how he endlessly plays silly little games
.. how he dances without getting self conscious
.. how he learns everything as quickly as he does
.. how much he loves his mother
.. how there's so much trepidation and excitement in his eyes about something new
.. how he runs around the house without a break
.. how he loves to hide behind things and play peek-a-boo
.. how the most silly thing makes him laugh out loud
.. holding him close to me when he's scared
.. how much he loves to ride on my back
.. how he takes the most incredible things at face value
.. how he never lies, even if that gets him into trouble
.. how he's the most maddening person ever by far
.. how he holds my finger when we go out for a walk
.. how he holds on to my finger from his crib when I lie down next to him on the floor
.. how his mother and I cannot stop talking about him
.. how he walks around the house with his stuffed dog in his arms
.. how much he depends upon me
.. how he makes me smile
.. his cute mispronunciations

I'll miss that little boy when he grows up.

Android In-app Billing notes

In the notes below, I have distilled the knowledge I gained implementing Android In-app billing. All of this is current and correct as of this writing (Sept 2012). However, given the pace at which the In-app billing framework seems to evolve, a lot of this might not be applicable by the time you read this. Take it for what it's worth.

Development

- Read this http://developer.android.com/guide/google/play/billing/index.html carefully. All of it. Multiple times.
- Don't start from scratch. Grab the in-app billing sample that ships with the SDK and re-purpose it. Create a library from the sample app after stripping out things you don't need. Include that in your main application.
- Changes made in the Play developer console don't take effect instantaneously. Sometimes for hours. Don't despair if you see unexpected responses from the Play service.
- If your app is about subscriptions rather than plain old one-time purchases, do yourself a favor and implement a service on your backend to keep track of subscriptions. This will eliminate a whole host of edge cases that arise if you don't have a backend to keep track of active subscriptions and cancellations.
- Make sure that the ITEM_TYPE property in the request bundle passed in sendBillingRequest is correct. If there's a mismatch between the product type configured in Play and your request you'll just get an ITEM_UNAVAILABLE response with no explanations.
- Stackoverflow is your friend. See the in-app-billing tag
- This is another great resource to save you some heartache.

Developer testing

Pay careful attention to the table in this section: http://developer.android.com/guide/google/play/billing/billing_testing.html#billing-testing-static.  The table is fairly confusing, but the bottom line is this: use a developer account for testing responses from Play.

Here's a good way to test your app during development:
1. Make sure you have the com.android.vending.BILLING permission in your Manifest.
2. Upload the app to the Play Console and leave it unpublished. Make sure the versionCode of the latest uploaded APK in Play is the same as in the app you test with. This is important. You won't get signed responses unless these match.
3. Make sure the primary account on the device that you plan to test with is configured as a developer in your Google Play account. This is especially important if your app has never been published before. You won't get a signed response otherwise.
4. Don't test till at least a few hours have elapsed from the time you uploaded your app. For best results test it the next day.
5. Test your app's flow using static test product IDs e.g. android.test.purchased.
6. If you wish to test it with a real product ID make sure you wait for some time after creating the product in Play before testing with that ID.

QA

Final testing just before launch
1. Bump up your app's versionCode and upload the APK again. Leave the app unpublished.
2. If this app has never been published before, test using a developer account. If your app has been published before you can use any account. 

Gotchas

- Can't stress on this enough. Changes made in the Play console don't necessarily take effect right away. If you don't see an updated response from the Play service, give it some time to catch up.
- If you upload an app and leave it unpublished, unless you are added as a devloper in the Play dev console, you'll always see an empty signature string. 
- Google Play doesn't let you query published products for pricing information. If you plan to display the price of a product in your app, make sure there's a way to keep the price published in Play in synch with what you display in the app. This should be via a CMS or something similar.
- Google Play will not let you edit products once they are created. Publish with care.

Sunday, September 16, 2012

Shaving the Yak

All I wanted, was to choose the right wordpress theme for some blog I was helping set up. To do this I had to install MySQL. To do that I ended up upgrading my Ubuntu install from 12.04 to 12.04.1. All of this to decide which wordpress theme to mooch off of. Talk about Yak Shaving.

Monday, December 21, 2009

Remapping the Show Desktop key combination on Gnome

I use both Ubuntu and Windows XP desktops at the same time. I am used to hitting Win+M on windows to minimize all my windows and show the desktop. It bugs me no end that I cannot do the same on Ubuntu. But some quick searching led me to 2 forum posts that helped me nail this. The default key combination for showing your desktop on Ubuntu is Ctrl+Alt+D. So the first thing you'll have to do is to assign a new sequence to that action. You do this by using either the gconftool command line tool or the gconf-editor GUI. The command line method works thus:


gconftool-2 -t str --set /apps/metacity/global_keybindings/show_desktop "<Super>m"


If you decide to use the gconf-editor tool instead, navigate to apps -> Metacity -> global_keybindings and look for the "show_desktop" key in the right side pane. Here replace the existing value with "<Super>m" (without the quotes).

If you have compiz installed the "Negative" plugin in compiz inverts your screen colors on hitting Win+M and restores your colors on hitting Win+M again. You'll have to disable this. If you use gconftool from the command line, here's the incantation that'll do the trick:


gconftool-2 -t str -s /apps/compiz/plugins/neg/allscreens/options/screen_toggle_key ""
gconftool-2 -t str -s /apps/compiz/plugins/neg/allscreens/options/window_toggle_key ""


If you choose to use the GUI gconf-editor instead, you'll have to navigate to the right key and update it's value, similar to the show_desktop example above.

And there you have it.

Monday, August 17, 2009

BlindSearch

The recent Yahoo-Microsoft search deal inspired the BlindSearch search engine comparator. Michael Kordahi, the creator of this cool site, posted the results of his experiment here. In short the results till Aug 10 2009 are as follows:

Query count: 559,239
Results: Google: 41%, Bing: 31%, Yahoo: 28%

I decided to take this out for a spin myself and see if my experience was in line with the above. Here are the searches I tried:

  1. digital camera deals
  2. offline word list unix
  3. java 1.6 docs
  4. cheap new york hotels
  5. jquery docs
  6. words beginning with Q in english

Google returned me the best results for all but the last query. Yahoo was better with "words beginning with Q in english".

Now, to be fair I think the phrases above might not be what most others search for as is evident from the list of top searches on the site, but hey this was my test drive to see what I would get. I think I agree that a single company's search hegemony is not such a great idea for the web in general, but I think I'll stick with Google search till someone proves to me that their search is superior to Google's.

Thursday, August 13, 2009

My experiments with twitter - I

As with most other "social-networky" things I was hesitant to use twitter, although I had signed up a while ago. I guess I am a tad (my wife would say very) paranoid when it comes to my online presence. Be that as it may, it's been almost a week since I have started tweeting regularly and I think I really enjoy it. I lack the discipline and patience required for posting full blown blogs - a quick look on the right at my blog's archives will tell you as much. The short 140 character messages seem ideal for the indolent scribe in me.

But that's not what this post is about. I meant to share my experience using the awesome twitter client I am currently using. I had experimented with other twitter clients in the past but none of them seemed as capable as this one. So what was I looking for? I was looking for at least the following things:
1. Ability to group the people I follow into separate lists
2. Ability to synch up this structure on multiple clients
3. Clean uncluttered display

I was almost about to start writing my own little twitter app that I would run in an embedded jetty instance on my box at work and at home, but then I stumbled across TweetDeck. And boy, was I pleased! Not only did it satisfy my requirements, it threw in a slick polished UI as a bonus. Since I use my iPhone prodigiously as well, I was really overjoyed when I found that TweetDeck had a client for the iPhone too that looked and behaved almost exactly like the desktop version. I'll not lengthen this post by walking you through all the details about TweetDeck - others more accomplished than myself have done that already.

Here's to a lot of time whiled away tweeting happily...

Monday, August 10, 2009

Twitter

I had a mostly dormant twitter account for a while. My tweets were few and far in between as was the frequency at which I read tweets from people that I follow. But all that's about to change. Twitter, here I come!


Follow me on twitter.

Monday, October 15, 2007

User defined types with JsonMarshaller

I came across the JsonMarshaller project while searching for a Java library for unmarshalling JSON. This is a nifty little framework and uses Java 5 annotations for marshalling and unmarshalling JSON.

JsonMarshaller provides simple annotations @Entity and @Value for marking up your classes for marshalling and unmarshalling. However, I wanted something more than what the base framework provides - the ability to convert dates back and forth. The framework supports a so called type option to specify a user defined type for a value. This is a cool idea for extending the basic types supported out of the box. The (simplified) code for my DateType class that solved my problem is below:



public class DateType implements Type {

@Override
public Class getReturnedClass() {
return Date.class;
}

@Override
public Object marshall(Date entity) {
SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
return format.format(entity);
}

@Override
public Date unmarshall(Object object) {
String date = (String) object;
Date d = null;
try {
d = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").parse(date);
} catch (ParseException e) {
e.printStackTrace();
}
return d;
}
}




This simple class can read a String representing a date in most commonly used formats and return a java.util.Date. It can also read a java.util.Date and return a String representing that date.

Create your family tree with Geni

I came across this really cool website that let's you create your family tree. It's got a cool interface that let's you and family members you invite add new members to your tree. Really cool - loved it.

Claiming my blog in Technorati

Technorati Profile

Thursday, October 11, 2007

TightVNC client getting killed after Windows locked?

If you are wondering, like I was, why your TightVNC viewer dies after your Windows workstation running the server is locked, here's the answer.

Briefly, from the link above:
"This is a standard behavior. You have to run TightVNC Server as a service if you want to avoid this problem."
So there.

Pidgin + Pidgin plugin pack on Ubuntu

Pidgin is an open source multi-protocol chat client. Since I use AIM at work and most of my friends listen in on GTalk, I decided to install Pidgin. A quick Google search unearthed this link. But hey, what's the point of being on Linux and not performing the configure-make-make-install drill? Besides, I wanted the Pidgin Plugin Pack as well (which btw can also be installed by following the instructions here without building the sources). This pack has an extremely useful plugin - Mystatusbox - that allows you to selectively set the status of each of your IM accounts. So here's how I got around to getting both Pidgin and Pidgin plugin pack on my box:
  1. download pidgin 2.2.1 source from sourceforge
  2. downloaded various dependent sources (libxml-dev, libgtk-dev) and installed these
  3. ./configure && make && sudo make install
  4. downloaded the pidgin plugin pack from here
  5. ./configure && make && sudo make install
I threw in a desktop launcher for good measure, and I was good to go.

Friday, September 21, 2007

Refactoring your tests

Martin Fowler's seminal book on refactoring speaks about the various code smells that you need to watch out for to keep your code healthy. Along with refactoring your code however, it's essential that you refactor your unit tests as well. Here's a nice paper that I found that describes various unit-test smells.

Refactoring and unit tests

It's an established fact that refactoring needs a strong scaffolding in the form of unit tests. If you have a good unit test suite, it gives you that extra boost of confidence to refactor your code, knowing fully well that you are not breaking anything. All this is well documented by several people way smarter than me, but here's an instance where unit tests saved the day for me.

What I had was a class similar to the one below:



public class Foo {
public Foo() {
initThis();
initThat();
initTheOther();
}

public void someOtherMethod() {
}
...
...
}




I figured that the code above might not be the most optimum since all the initXXX() methods were not exactly cheap and calling them eagerly on class construction was not exactly necessary. Therefore, I fired up eclipse and moved the three calls into a single public method init() that could be invoked by a callee before using an instance of foo(). I was happy that I had achieved a neat little refactoring by postponing heavy initialization to when it was needed.



public class Foo {
public Foo() {
//nothing here now
}

/* Call this before you use this instance */
public void init() {
initThis();
initThat();
initTheOther();
}

public void someOtherMethod() {
}
}




But, on running my unit tests for someOtherMethod(), I started getting inexplicable NPEs all over the place. This made me realize that something that happened in one of the initXXX() methods was required for executing someOtherMethod() successfully. That led me to add a call to init() in the constructor - something that wouldn't have come to my notice until somebody had actually run the application and reported a bug. Unit tests saved me a lot of time that I would have had to spend much later.

Agreed, I probably should've redesigned my class to call init() from someOtherMethod(), but that probably wouldn't have been the best choice if all the other methods in my class depended upon init() being called beforehand.

Saturday, August 25, 2007

Hello, World!

Everyone and their uncle blogs these days. So why not me? I intend to publish things here that strike me as interesting.

Stay tuned...