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 :-(

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…

thanks for the support, misc stuff

Android developers are having office hours on IRC now. I’m very thankful that they’re willing to provide help, and I hope they use the questions and answers to improve documentation so they’ll have fewer questions to answer in the long run (and fewer frustrated developers wondering what’s going on), but – I wasn’t impressed just yet. I was on channel for the time yesterday, and asked three questions via the moderation tool they’re using, which other users seemed to like. They did answer one question on channel – to say that what I want to do isn’t really possible yet. Didn’t address the others or many questions at all. Looks like the questions to the earlier session didn’t get answers yet – but there were answers to the questions from a week ago. So maybe they’ll get to it, but if you have to wait a week for answers, what’s the point of office hours? Well, maybe the holidays aren’t the best time – I’ll reserve judgment. And frankly, any kind of responsiveness is appreciated. And if I can get answers eventually, I have answers for my problems and new material for the android blog :-)

Know what I figured out today? Resource IDs don’t need to be globally unique. You just can’t inflate the same resource ID from different places in the same context. The R generator doesn’t seem to care that two things generate the same ID. Phew! I was naming my IDs with little prefixes based on the filename so as to keep them all unique globally; it’s not pretty. That was an assumption on my part, but I never saw anything to contradict it… maybe it’s time to read those dev docs more thoroughly!

Outstanding questions/problems:

  • Can I arrange my layout resources into subdirectories? I’m getting to have quite a few. Will have to try this and see if it causes problems – might mess up internationalization, orientation-specific layouts, etc?
  • I know I’m mismanaging my DB handles and cursors somehow – need to look into proper practices there.
  • I haven’t really dealt with lifecycle stuff properly. This shouldn’t be too hard, just need to actually do it. This is one of those areas where formal tests would be most helpful, as it’s hard to manually test the transitions properly.

wordpress <pre> borkage

Sometimes WP doesn’t seem to keep the formatting I put on code. It should all be rendered as <pre> but sometimes it’s changed when I go to edit an article (as inevitably I do, it seems). It remains monotype but the <pre> is gone and formatting is wonky – generally everything is smashed to the left. I think it’s WP itself doing this, although it may be that posting via ScribeFire sets it up for this to happen. Maybe it’s related to tabs not pasting well into the web form. I’ll try to keep the formatting correct, just thought I’d point out what’s happening if I miss something.

Also it looks like WP doesn’t escape HTML I put in the title. Interesting, that.

stumble, stumble – make my listview work dammit!!!

I have a spinner that I need to use and fill from several different components – at least two Activity classes and one Dialog. Looking for a way to reuse the same code and layouts; not clear just yet. But along the way I came across this forum post which I’ll have to look at next time I’m trying to build a custom view.

Also I have a custom dialog that only enables the “OK” button if a text editor has text in it, and wanted to generalize that. The problem is with how much stuff you have to specify to wire it all together. I think what I really want is an AlertDialog with a text field and some extra magic to enable/disable the positive button, but to get all that working I’d pretty much need to subclass AlertDialog.Builder too, and not sure if that’s worth the pain. But perhaps worth a try. You’d think this would be a standard feature, though… a dialog that validates input before enabling the buttons to be pushed.

Next problem: I have a ListView and I want to have a spinner at the top and a text entry box at the bottom. Putting this inside a ScrollView does not work, I get this:

How do I get the ListView to stay fully expanded? I found several forum posts warning against using a ListView within a ScrollView, so that’s out. The main commentator on this seems to be Romain Guy, who’s obviously very knowledgeable, but he’s also really lousy at adequately answering questions. His blog entries on Android are pretty sparse. I still wanna read them but man is it frustrating reading his half-answers in forums.

Looking for ListView attrs… Well, the ListView reference docs say that you can add header and footer elements; any way to do that in XML? Does not look that way. I’ll try it in code first. When I first used ListView, I naively thought that you should place the “empty” item inside the ListView element in the XML. Certainly makes more sense than putting it after, don’t you think? I mean, at least conceptually it’s part of the view; but the designers thought otherwise. Actually, at this point it looks like anything you place after the ListView element is used for the empty view. Anyway, I put a header element before and footer element after in the file, and added them to the ListView in code like so:

        getListView().addHeaderView(findViewById(R.id.il_list_spinner));
        getListView().addFooterView(findViewById(R.id.il_new_item));

This causes a lovely runtime exception, which basically tells you nothing about what went wrong:

 java.lang.RuntimeException: Unable to start activity ComponentInfo{net.sosiouxme.WhenDidI/net.sosiouxme.WhenDidI.activity.ItemList}: java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams
     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2401)
     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2417)
[…]
 Caused by: java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams
     at android.widget.ListView.clearRecycledState(ListView.java:489)
     at android.widget.ListView.resetList(ListView.java:475)
     at android.widget.ListView.setAdapter(ListView.java:417)
[…]

Pretty helpful eh? Yeah. Might as well just say “dude… something’s wrong with your layout.” I’m guessing it doesn’t like me reusing view elements of the current context as elements of the ListView. Or maybe it’s related to the “poorly documented” bit mentioned in this thread (this would be more helpful with a pointer to the back story). And now I can’t figure out how to debug down into platform code – is there some way to attach source code so the debugger can look at it? Can’t seem to find anything on that in a search either. Good grief, this stuff makes me feel like an idiot!

Here’s some articles on customizing ListView to read later. Not germaine to my current purpose AFAICS, unfortunately.

As an aside – the Eclipse tool for building XML layout resources, while helpful, is really annoying. Chief among the annoyances is when you’re trying to scroll through the list of properties for a tag – each attribute has a little blurb about what it’s for, which conveniently pops up to cover what you’re trying to look at every time you pause! And if you’re really lucky, it pops up right under the mouse, keeping you from scrolling. You know, what I need is not automatic popups – I’d rather have a mouse button specifically to give me info about what I’m looking at. The middle mouse button would probably be perfect since I don’t think Eclipse does anything else with it. Looking for preferences I can set to disable or control the hover, but even with all hovers disabled this still pops up. Wonder if it would do me any good to try to fix ADT?

And why is it that adb keeps losing track of its emulators? Kill the server and restart it, and it finds the emulator again… only to lose it again quickly. Bah!