brain food, good buy, futzing with Gallery

Found Beer Planet yesterday morning, now I have a lot more reading to do.

I bought this Compaq nx 7400 laptop from Craigslist earlier this month just so I’d have something to take to meetups and use the Android SDK on. Didn’t realize it would become my favorite device in the house – seems I’m valuing flexibility and comfort over even the allure of dual monitors. Anyway, a damn good investment at $150.

I thought I’d try creating a little app that displays/demonstrates all of the android.R resources – I mean how do you know what an icon or layout will look like until you try it in an app? So, starting with a gallery of android.R.drawable – should be pretty easy, right? Hahahah. Funny, not a lot of info on the dev guide about Gallery, and following the examples got me a big fat ClassCastException about Gallery$LayoutParams. Geez I hate that thing. There’s no way to relate it back to what I actually did wrong. *sigh*

BTW I created a custom adapter (just extend BaseAdapter) so I could use reflection on android.R.drawable and turn all of the fields into items for the gallery (field value for image resource ID and field name for caption) – that way I don’t need to make a long list and any variation between platforms is captured automatically. I thought that was pretty clever and it’s really not very hard, except for this business of filling in the view.

An initial glance at Gallery reference doc indicates maybe I should try using a simple ImageView as the gallery item just to get going – the Gallery.LayoutParams need to be applied to the Gallery item, but currently my item is actually a LinearLayout holding the image and a caption TextView. That seems to “fix” the ClassCast problem but I’m only seeing one item, no scrolling. How does this Gallery thing work? Time to google… oh wait, there is a Gallery tutorial in the dev guide after all. Durrr. But! I try to use this code:

TypedArray a = obtainStyledAttributes(android.R.styleable.Theme);
mGalleryItemBackground = a.getResourceId(
        android.R.styleable.Theme_galleryItemBackground, 0);
a.recycle();

… and now Eclipse tells me there’s no such thing as android.R.styleable – example fail! WTF? NOW it’s time to google. That doesn’t help; looking at the APIDemos examples, I notice that for 1.5 it used its own R.styleable and not android.R.styleable, so maybe the latter didn’t come into existence until a later API level. The class reference helpfully doesn’t say. And I need to stop here for today :-(

Advertisements

debugging and learning by lending a hand

I start out the day with a lovely SQLite error:

ERROR/AndroidRuntime(800): Caused by: android.database.sqlite.SQLiteException: near “Group”: syntax error: , while compiling: SELECT _id, name FROM Group

Now, I did just change (almost) all of my table and column names, but I don’t see anything wrong with that SQL. Hm; surely there’s a way to get SQLite to log the exact statements it’s running? Maybe that would help. Hmm, maybe, but given the statement above looked fine, maybe I should just try it directly by firing up adb shell and checking the DB myself with sqlite3.

# sqlite3 whendidi.db
SQLite version 3.5.9
Enter “.help” for instructions
sqlite> SELECT _id, name FROM Group;
SQL error: near “Group”: syntax error
sqlite> .schema Group
sqlite> .schema
CREATE TABLE android_metadata (locale TEXT);
sqlite>

So there’s the problem – the “Group” table wasn’t created (for that matter, none were). Pretty simple, but why do I get this as a “Syntax error” rather than “Table doesn’t exist” error? Oh, duh – “group” is a reserved word in SQL. Hahahah, the wacky things I do sometimes… and I would’ve noticed it earlier if I’d paid attention the first time I tried to run the app and it failed (while creating the DB, instead of now while trying to use tables that should have been created the first time).

I got a chance to be AndroidDev support for AndroidFTW today. His problem was simple enough, needed to know how to hook up a ListView and its menu to respond to user clicks. Along the way, I noticed that there are two parallel methods for handling selections from the options menu: the one I’ve been using (probably saw it in books) – onMenuItemSelected(int, MenuItem) and the one that’s in the online guide, onOptionsItemSelected(MenuItem). Doesn’t hurt to use the former but makes more sense to use the latter.

is it too much to ask…

Would it be too much to ask that when I use the ADT resource generator tools, they produce XML that looks not like this:

… but instead actually readable like this:

I mean, I suppose if I just wrote it directly in the first place (Eclipse does offer good completion help), I wouldn’t care. But it’s nice to use the graphical tools just for getting started sometimes, and then it sucks to reposition the text so I can make sense of it.

Am I the only person complaining?

UPDATE: Score! This is exactly what I need. Wow, looks like this guy has a ton of other useful information too. Blogrolled!

Hmm, minor little problem – I added a key shortcut for “Clean up” but it’s not firing. I guess I can remember Alt-S, C, Return.

customization

Been fiddling with Twitter today. I used twitbacks to create a background picture so my profile isn’t quite so mundane. I finally started using lists (now if echofon would just let me see tweets from a list that would be something). I looked around for other #androiddev folks – not too many active at the moment, but then it is the holidays. I see some of the value of twitter but at this point it still seems like more of a time sink for me than a value. I have a feeling I shouldn’t miss out, though, ought to expand my usage, link everything I’m doing together and promote it. Because I do feel like I can add a lot of value to a corner of this internet.

I thought I’d take a crack at subclassing AlertDialog like I wanted. The goal is this: customize the view to include a text entry field linked to the positive button such that there has to be some content in the text entry field before the button is enabled. Simple enough for a single custom dialog – just set a key listener on the entry field and enable/disable the button accordingly. But I want to do this in several places so it seemed like a good idea to make a custom dialog class that could be configured a little differently each time but with the same general behavior. I thought all I need is AlertDialog with a custom view (it doesn’t allow any sort of text input) and some added behavior, right?

Subclassing AlertDialog turns out to be tricky. I mean, a simple subclass is trivial, of course, but the problem is the actual building of the dialog, which is normally accomplished by the AlertDialog.Builder inner class. This in turn relies on AlertController.AlertParams to hold the parameters that will be applied to the dialog when finally it’s built. Unless I’m mistaken, I’d have to recreate all that behavior in my builder. Suck! Forget it! I think what I’ll do instead is just have the custom dialog I already almost finished expect to be given a view with certain element IDs and wire them up. Well – even that is sucky because getting at the elements inside the dialog from outside the dialog pretty much sucks – which is why an AlertDialog would have been nice in the first place. Ok. I’ll make a fairly stupid class that just supplies the button-wiring behavior and let specific dialogs subclass from that and specify what gets wired. That works.

RTFMing some more. Defining preferences from XML isn’t described anywhere in the dev guide – but “Hello, Android” is helpful here. However, I had to use a little trial and error to figure out how to use a ListPreference (well – probably there are examples in the sample programs, but I figured it out). Here’s what a ListPreference definition looks like:

<ListPreference android:title=”Tracker click”
 android:summary=”What should happen when you click on a tracker?”
 android:key=”trackerClickBehavior”
 android:entries=”@array/trackerClickBehaviorVisible”
 android:entryValues=”@array/trackerClickBehaviorStored”
 android:defaultValue=”view”
 />

Of course the arrays are defined in values resources like so:

<string-array name=”trackerClickBehaviorVisible”>
    <item>Create instant log</item>
    <item>Create detailed log</item>
    <item>View tracker details</item>
</string-array>

Simple enough.

It’s good to know that you can create a custom toast layout if you so desire.

Android menus – another look

Browsing the Android “Creating menus” guide. Bits of note:

  • Now I know what the “group” setting is for on menus. Grouping items doesn’t make any visual difference, but in code you can do things to the group as a whole – enable/disable, make visible, etc.; also can use them to define mutually exclusive radio buttons.
  • Menu items can be in checked/unchecked state (setCheckable) – this includes options menu items, however these don’t have checkbox indicators, have to change icon or otherwise indicate state of checked-ness manually.
  • You can set a menu option to automatically start an intent when selected; however I’m not sure how useful this is – is there any advantage over firing the intent from a normal menu-item-pressed callback? It seems like having multiple places to define menu item behavior would just be confusing. Hard to imagine a situation so dynamic that this would really be necessary. But actually, the docs give the example of having an unknown set of intents (depending on other apps installed) to handle something; the example that comes to my mind is “Share” options where you click on e.g. a link and you can share via IM, SMS, twitter, Facebook, etc if you have those apps installed. So there’s some valuable juju in such cases, but otherwise it seems unwise.
  • Something to verify: is onCreateContextMenu() called once for each item that’s long-pressed? i.e. can we potentially create different context menus per item? Given the checkability thing above, it would seem likely. Also the prepare menu. Something for me to experiment with.
  • Adding keyboard shortcuts – I’m wondering how many Android devices this is really going to be useful on? With a touchscreen it’s completely useless – worse, in fact, as it will be a distraction. But given there are Android netbooks in the works, I suppose there’ll be some cases with no touchscreen where a keyboard shortcut will be more accessible than navigation.

RTFM

Going back to re-scan the Android dev guide now that I understand a bit better what’s going on. It makes a lot more sense now.

First I had a look at binding list views to data. This bit of code had some nuggets:

ArrayAdapter adapter = ArrayAdapter.createFromResource(
   
this, R.array.colors, android.R.layout.simple_spinner_item);
adapter
.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);

My code was similar, except the setDropDownViewResource call was commented out because the method was unavailable when I tried it; looking more closely I saw that I’d set adapter to type SpinnerAdapter – which is just an interface without the actual methods of an actual Adapter; wonder where I got that from? Correct typing allowed me to use the method. I had not noticed before that there were prefab views available for the spinner; oddly, however, using these resulted in invisible text and strange buttons on the dropdown:

(And, just now noticing that ScribeFire isn’t inserting an image intuitively. Bleh. Not that WordPress hasn’t given me “shaking fist syndrome” from trying to insert images too.)

Also discovered notifyDataSetChanged() which keeps me from having to create a new cursor and adapter when I know or suspect the data for the view has changed. I guess that’s one of the benefits of Activity cursor management? Just requires retrieval and careful casting of the adapter to call the method. Going to try it now. In my case, with a custom adapter (subclassing SimpleCursorAdapter), it looks like so for my ListActivity:
    ((EventCursorAdapter) getListAdapter()).notifyDataSetChanged();
Well, that does not in fact re-run the query and get the new data. So that’s a bit misleading. But it DOES seem to work for my spinner:
    ((SimpleCursorAdapter) mSpinner.getAdapter()).notifyDataSetChanged();
Hmm… what’s the difference? Stack Overflow has someone recommending futzing with the cursor directly on the ListActivity though the next response indicates notifyDataSetChanged should work. Comments on this ListActivity tutorial indicate some puzzlement about the issue as well. A response here indicates it should work.

It looks like SimpleCursorAdapter gets its notifyDataSetChanged method from BaseAdapter, which probably does nothing but update the view as no query logic could be involved. That doesn’t explain why there’s different behavior between a Spinner and ListActivity which both use SimpeCursorAdapters, but it suggests I can try overriding the method in my custom adapter and requerying the cursor.
    @Override
    public void notifyDataSetChanged() {
        getCursor().requery();
        super.notifyDataSetChanged();
    }

Ooh! Bad idea! Apparently the requery causes notifyDataSetChanged to be called and it recurses into a stack overflow. I can add a separate method to try the same thing, though. And… that works – and the cursor requery automatically kicks off the notify and redraw.

I must be missing something. I don’t understand why I’d need to explicitly requery in the case of an adapter for ListActivity and only need to notify for a Spinner.

Link shorteners in Firefox

I don’t understand what it is about Firefox URL shortener extensions that causes me problems; they must interact badly with other plugins I use or something. After having a setup that seemed stable for a week or so, I installed Shorten URL and when I restarted the browser, my saved tabs wouldn’t load; so that was a non-starter (literally!). Other reviewers complain of various bad interactions on that as well. Then I tried the specific is.gd shortener, and that works great except that when I shortened a URL with it, half the time it crashed the browser and I’d lose whatever post or tweet I was working on – not so helpful. Honestly, what is it about URL shorteners that’s so invasive? Seems like it’d be simple enough to just add a context menu item or two and fire off an HTTP request. Other shorteners all look dodgy in some way; I’ll try LNK.sk and see how that goes.

UPDATE: that seems to work, although everything’s in… Swedish? Icelandic? I don’t know! Oy. Why can’t I just twitter like a normal person…