Archive for the ‘Android’ 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.

Just recently I switch my mobile carrier from Rogers to WIND Mobile. Their Holiday Miracle plan was just to good to pass up – even paying the penalty to break my Rogers contract I will still save money in the long run.

Anyway, once the number got transferred over, I didn’t have a 3G connection, even after selecting the WIND Home APN.  After a bit of google, it seems that what I had to do is to setup an APN.  In case I can’t find it later, here are the APN settings:

APN mms.WINDmobile.ca
Proxy <Not Set>
Port <Not Set>
Username <Not Set>
Password <Not Set>
Server <Not Set>
MMSC http://mms.WINDmobile.ca
MMS proxy 74.115.197.70
MMS port 8080
MMC 302
MNC 490
Authentication type <Not set>
APN type mms

After setting this up, bingo, got my 3G connection going.

(Or, things to do when you have a sick kid)

election

One of the new data catalogues that the City of Edmonton has put up is the 2010 Election Results.  This Thanksgiving Long Weekend I was kind of “grounded” at home when my son came down with a nasty inner ear infection.  I was hanging out with him, and thought I could use the time to see how hard it would be and how quickly I could put together an Android application that would poll these results and show leading candidate in each contest for a given ward.  Turns out it was not that hard at all.  Development time was less than one day, and then I had the application running on my phone for a couple of days.

If you search the Android market place for YEG Vote, and you’re running Android 1.6 or higher you should able to find the application and install it (assuming, of course, you care about the election results).  The application itself is pretty bare bones.  It will get the results every five minutes, and then show the leading candidate.

I think my next trick will be to duplicate the application in C# and MonoDroid just to get a feel for the differences and such.  I’d wager that it will take even less time in MonoDroid for me, given that I’m much more fluent in C# than I am in Java.  I’d have done this in MonoDroid to being with, but MonoDroid is currently in a limited preview and one of the conditions of being in the preview program is that you can’t distribute applications written in MonoDroid yet. I would have tried a Windows Phone 7 port, but it just doesn’t make much sense, given that the number of people in Alberta with actually WP7 devices is probably less than 10.  Maybe next election.

If you have any suggestions or ideas, feel free to let me know. If I can scrounge up some time this weekend before the election I’ll see if I can implement them.

And, it goes without saying, regardless of what you think about this application, if you live in Alberta, make sure you get out and vote this Monday (October 18th, 2010).

screenshot1

My trusty old ADP1 is beginning to show it’s age, and I’m thinking that it’s time to get a new Android based smart phone.  So, what should a guy get?  My criteria (to be modified as thoughts come to mind):

  • Not carrier locked
  • Would prefer it compatible with the frequencies used by Rogers (I’ve got about 18 months left on my contract with them).
  • I can install CyanogenMod on it.  More to the point:  I can install the latest versions of Android as they become available.  CyanogenMod seems to be the handiest way to do so.

Personally, I’m thinking either an HTC Desire or a Samsung Galaxy S.

I’m not against a Windows Phone 7 device, but there aren’t any on the market now, and I’m thinking that I don’t want to take the pain of a first generation Windows based device.

If you’ve got any thoughts/suggestions/comments/tips, feel free to post them in the comments.

Last night I pushed a new build of YEG Buildings out to the Android Market. The two changes with this one:

  • Rather than showing the latitude/longitude of were you are, the application will try to translate that into a more human-friendly address.  Note that the address might not be 100% accurate.  It depends on how much accuracy the GPS has.
  • The application no longer uses Google Maps and a KML feed when show where all the historical buildings in Edmonton are.  The map of Edmonton is now rendered locally, and all

Just for fun, I also submitted YEG Buildings as part of the Apps4Edmonton contest.  So, feel free to check out the contest page – there are a lot of neat applications there.  Also feel free to vote mine up.  :)

If you are using or have used YEG Buildings, feel free to let me know your thoughts.  If you find a bug, let me know.  If you have a feature you’d like to see, I’d love to hear about it.

After a few months of neglect, I put a new version of my Edmonton Historical Buildings application up on the Android Market.  I’ve renamed it to just YEG Buildings, as I’d like to eventually include buildings that aren’t historical, but interesting in general for some reason.  The previous version had a nasty bug that would crash when you tried to view the location of a building on the map.  Was one of those curious things where it worked in the emulator but not on a real device.  I’ve tried it out on my HTC Dream running Cyanogen 6.0 RC3 (this is Android 2.2), and it seemed to work. 

I’ve also added a feature where you could see all the Historical Buildings from the City Of Edmonton’s Data Catalogue at once in Google Maps.  It’s a bit slow (mostly for reasons beyond my control at this point), but it basically works.

You can download it from the Android Market, or via this handy page at AndroidZoom.  You’ll need Android 1.6 or higher.

A while ago, I posted a blog article about using IntelliJ for Android development.  Given that was a year ago, and one version of IntelliJ later, I thought I would do a follow up post.  Long story short (and to sound like a TV commercial):  I liked IntelliJ IDEA 9 so much, I bought a license.

Since I blogged last year, the Android plug-in for IntelliJ has really matured.  I guess the only draw back to it is that you only get the Android plug-in when you buy the Unlimited Edition of IntelliJ – it’s not in the Community Edition.  Here are some general comments/thoughts/observations of mine:

  • It’s cool to have IntelliSense in the XML files.  One of the biggest failings of Android (perhaps Java in general?) is the painful lack of a surface designer for a user interface.  DroidDraw is tolerable with enough scotch.  One could say say the same thing about the UI “designer” that comes with the ADT.  So, much of the time I find myself just plugging away at the UI in XML.  Sub-optimal, but I don’t have the resources to write a nice designer for the Android layout files, so I’ll just pour another double of Talisker and carry on.  :)
  • I like the fact that, as a Resharper junkie, IntelliJ seems very natural to me to use.  The keyboard mappings are not 100% between IntelliJ and Resharper, but that is merely semantics. I find that within about 30 minutes or so I’ve recovered from the differences and that I don’t suffer to much of a penalty switching between the two.
  • I’m a bit more structured when it comes to deplopyment.  I don’t like how IntelliJ wraps all the deployment magic for me.  Don’t get me wrong – it’s handy as all hell for development and getting an APK on my phone real quick.  For production level stuff though, I’m finding that Rake more than handles what I need done.

Of course, with Monodroid now in a closed beta and looming in the future, perhaps IntelliJ will be redundant to me?  Can I actually just write my Android applications in C# and forget about Java? As Monodroid is in a closed beta, I can’t really comment much about it at this point in time.  I think I can say, without the Mono gods smiting me from above with hail, thunder, and lightening, that I’m cautiously optimistic that Monodroid will be appealing to those who want to target mobile devices.

So, over-all impression: 

  • I like IntelliJ better than Eclipse for Android development.
  • I’d say that IntelliJ is worth the money I spent on the unlimited license. 

This claim may not be valid in all states.  It is also void where prohibited by law.  There is a good chance that it may not apply in Quebec.  This definitely does not include batteries.  YMMV.

Just to follow up on my last post about embedding Google Maps into your Android application (this part is kind of anti-climatic).

So, by now you’ve signed your application.  This is the “hardest” (i.e. busiest part) of the whole process.  The next part, getting your Goggle apiKey, is the easy part.  First you  need to get the MD5 fingerprint of your keystore:

keytool -list -alias androiddebugkey -keystore <path_to_debug_keystore>.keystore -storepass android -keypass android

Once that is done, you and register for a Google Maps API key.  You need a Google account, and have to agree to some terms of service legal mumbo-jumbo, but it’s pretty simple.  Once you click “Generate API Key”, you will get your key string.  You then simply add the Maps API key to your MapView in your application.  There are a couple of ways to do this, heres how you would do it if you were using the XML layout files:

Of course, after all this is done, the next trick is managing these keys.  You see, when you are working locally, your application is automatically signed using a debug key.  This is fine and dandy for most development.  However, when you deploy your application, you sign the application using your keystore that you created in Step 1.  You may have a brief moment of clarity here and realize that the apiKey from your debug keystore and your deployment keystore are different.  I’ve got some ideas on how to deal with that that, but that will be for another day.

Full documentation for all this can be found on the Android developer’s website.

Thanks to all who attended my “Induction into the Android Army” talk this afternoon at the monthly Edmonton Java User’s Group meeting.  I’d say it was a good turn out, especially when one considers that this is only the second monthly meeting for EJUG.  It was a pretty basic talk, and didn’t dive to deeply into the “fun” Android stuff.  If anybody from EJUG wants a follow up presentation that’s a bit more in depth, give a shout out on the EJUG mailing list.  If there is enough interest, I’d be happy to put something together.

If you want to browse the code and don’t want to download the Android SDK, you can do so at the Android website.  Otherwise if you have downloaded the SDK,  you can the samples/Notepad folder.  For those who want the PowerPoint slide deck, please hang tight and I’ll get a link to that shortly.  Basil already has a copy of it, and he’ll probably post it to the Google Group shortly as well.

Google-Android-army