Archive for the ‘Mobile’ Category

I have a simple little pet project (for Android), and one of the things I wanted to do was to to have a text field that would show me previous values as I typed in the text box (see screenshot below). Of course, this control is already a part of the Android SDK – it’s our good friend the AutoCompleteTextView.

To populate the drop-down, I have an SQLite table called vehicle_descriptions, which looks something like the screenshot below. What I want is for a given vehicle (a value derived from another control on my Activity) to show me the value of the description column in the table.

At first I started out by sub-classing CursorAdapter, but that just seemed to be a bit to heavy. What I had worked, but it seemed like there should be a simpler way to do this. CursorAdapter is probably a better choice for more elaborate requirements (maybe displaying images or doing some calculations), but in this case it struck me as overkill – I just wanted to do a simple lookup against a table. Turns out I was right – the easy way is to just use a SimpleCursorAdapter.

    <AutoCompleteTextView android:id="@+id/description"
                          android:completionThreshold="1"
                          android:layout_height="wrap_content"
                          android:layout_width="fill_parent"
                          android:hint="Trip Description (optional)"
                          android:lines="1" />

To setup my control, I have created a function that I call inside onCreate() of my Activity. Here is the code, and then I will explain it in more detail:

    private void initializeDescription() {
        _descriptionText = (AutoCompleteTextView) findViewById(R.id.description);
        final int[] to = new int[]{android.R.id.text1};
        final String[] from = new String[]{VehicleDescriptionsTable.DESCRIPTION};
        SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
                android.R.layout.simple_dropdown_item_1line,
                null,
                from,
                to);

        // This will provide the labels for the choices to be displayed in the AutoCompleteTextView
        adapter.setCursorToStringConverter(new SimpleCursorAdapter.CursorToStringConverter() {
            @Override
            public CharSequence convertToString(Cursor cursor) {
                final int colIndex = cursor.getColumnIndexOrThrow(VehicleDescriptionsTable.DESCRIPTION);
                return cursor.getString(colIndex);
            }
        });

        // This will run a query to find the descriptions for a given vehicle.
        adapter.setFilterQueryProvider(new FilterQueryProvider() {
            @Override
            public Cursor runQuery(CharSequence description) {
                String vehicle = getSelectedVehicle();
                Cursor managedCursor = _helper.getDescriptionsFor(vehicle, description.toString());
                Log.d(TAG, "Query has " + managedCursor.getCount() + " rows of description for " + vehicle);
                return managedCursor;
            }
        });

        _descriptionText.setAdapter(adapter);
    }

So, first things first. We setup two arrays. The to[] array holds a list of resource id’s that will be used to display the text values in the drop down. I just want to display the items in a list, so I used android.R.id.text1. The other array, from[] hold the name of the column that will hold the values to display. As I mentioned above, I want to show the values in the description column.

After that we new up a SimpleCursorAdapter. The line itself should be pretty obvious. The null that we’re passing into the constructor is because we don’t yet have a cursor available. In this simple case, the 3rd parameter is android.R.layout.simple_dropdown_item1line will suffice. If we were making our own view for display description, then we’d pass in the resource id of the control that would display the text value.

After instantiating the adapter, we provide some direction as to how we should convert the cursor to a string value that can be displayed. We do this with a CursorStringConverter. All we do here is retrieve the value of the description column in the cursor as a string and return that.

The final part is to use a FilterQueryProvider to get a Cursor holding the rows and columns we want to display – note that I’m doing this by actually running a query each time. There are probably more efficient ways to do it (and if you have a better way I’d love to hear it). The line _helper.getDescriptionsFor() will return a cursor holding all the rows from my vehicle_descriptions table for a given vehicle. The user will select the vehicle from my vehicle spinner. I created the method getSelectedVehicle() as a convenience method to return the text that is selected in the spinner.

And of course, the final thing is to provide the adapter to the AutoCompleteTextView.

For the sake of completeness, here is what getDescriptionsFor() looks like. The _activity below is a reference to whatever Activity. The code here is should be pretty simple – we just return a managedQuery from the ContentProvider for this application. Note that with our projection we return both the _id column and the description column. The SimpleCursorAdapter requires the _id filed be present. Anyway, without further adieu – the code:

    public Cursor getDescriptionsFor(String vehicle, String descriptionFragment) {
        String[] projection = new String[]{VehicleDescriptionsTable._ID, VehicleDescriptionsTable.DESCRIPTION};
        String[] selectionArgs = new String[]{vehicle};

        StringBuffer selection = new StringBuffer(VehicleDescriptionsTable.DESCRIPTION)
                .append(" LIKE '")
                .append(descriptionFragment)
                .append("%' AND ")
                .append(VehicleDescriptionsTable.VEHICLE)
                .append("=?");
        String sortOrder = VehicleDescriptionsTable.DESCRIPTION;

        return _activity.managedQuery(VehicleDescriptionsTable.VEHICLE_DESCRIPTION_URI,
                projection,
                selection.toString(),
                selectionArgs, sortOrder);
    }

There you have it – AutoCompleteTextView and SimpleCursorAdapter together at last.

For those wanted the slide-decks and code from my talks at Prairie Developer’s Conference 2011, you can find them up on GitHub. Thanks to all who attended.  Maybe we’ll see you again next year.

I’ve spent a bit of my spare time in the past week looking at Windows Phone 7 from a developer’s point of view.  I’d have started sooner, but honestly, I didn’t see the point until there were actually devices that I could hold and use.  I know that in the U.S., some guys got developer phones from Microsoft, but I don’t think that anybody up here in Canada was that lucky.

So, over the past year or so I’ve been dabbling with Android and I actually like programming for Android.  The biggest issues I’ve run into with Android are my lack of Java skills – I keep doing things the C# way (you really don’t realize how handy Linq is until you don’t have it) and the fact that Android doesn’t have a decent UI designer.  But otherwise, I like Android.

So, I was curious what the developer experience was for WP7.  In a nutshell – it’s not bad, and in some ways better than that of Android.

Things I like about WP7 development:

  • Being a C# guy, it was pretty easy and fast for me to get going with WP7.  Of course, Novell now has MonoDroid which in theory should lessen the learning curve for a C# guy to create Android applications.
  • It’s nice to have good tooling to help with creating my UI’s.  Blend and Cider are pretty decent. Android does have DroidDraw, but I’ve never really found that tool to be good to work with.  Eclipse has some sort of an GUI designer thingy, but again, I’ve found it to be kind of lack-lustre at best.  That, and I don’t use Eclipse – I prefer IntelliJ.
  • The Emulator seems to start up faster to me that the Android emulator – but that could just be me.
  • The MVVM pattern.  I know the theory, and am now learning the more practical side of it.  Was worried that WP7 was going to decent into the path of darkness and pain that was/is Web Forms.
  • I think that the debugger integrates better with the WP7 emulator.  Not that, generally speaking, I spend a lot of time in the debugger, but when you need it, it does seem to be more natural to me.  Again, this could just be because by day I do a lot of C# development so I’m more used to the Microsoft tooling to begin with.

Some things I didn’t like about WP7 development:

  • You have to have Vista or Windows 7.  Yes, I know, XP is almost 10 years old, time to move on.  Call me an O/S curmudgeon.  I don’t mind Windows 7, but Vista sucks/sucked.
  • It seems like to build your apps, you have to use Visual Studio 2010.  Not a problem for a developer, but I’m old school when it comes to compiling applications, and your build server shouldn’t be tainted by your IDE.
  • I’m use to the relatively easy going Google marketplace and the fact I have numerous avenues available to me to distribute Android applications.  No such joy with WP7 apps.
  • Editing XAML by hand.  But, I suppose it’s no worse that the XML resource files that Android uses.
  • Not seeing a lot of projects whose code I can read.  Granted it’s still early, so hopefully that will change.  Or not.  .NET doesn’t seem to have the same OSS community spirit that Java does.

Microsoft has always tried to be pretty good to developers (sometimes to their own detriment), but I think Windows Phone 7 does have some things going for it, from a developer’s point of view anyway.  Here’s to hoping that strategy pays off – that cool apps will get written for WP7, and that it will be commercially viable.  Competition is good – it will keep Apple and Google on their toes.  Smile