LogMyLife alpha release – try it out!

It’s time for LogMyLife to see the light of day outside my house – I’m calling it alpha-ready today. Go check it out. I’ve had it with fiddling around and no one seeing the results :-) It’s actually pretty functional, but it’s not as pretty as it could be and I know there are a few corner cases where things are a little wonky. And there’s so much functionality left to add… but it’s been a great project for me to familiarize myself with a lot of Android UI. And that will continue.

Some interesting stuff I just learned recently:

What’s in a name?

The application name and the name you see on its home screen/launcher icon need not match (though it’s probably wisest if they do). The application has a label in the manifest, and so does each activity (potentially).

If you look up the application in the settings page, it will show the application name (probably also in any market interactions). The launcher icon will show the label on the launcher activity. Presumably this is because you could conceivably have multiple launching activities for the same app (different entry points).

In my case, I wanted to show a different label (“LogMyLife – Main”) to the user once they launch the app than the application name (“LogMyLife”), so they’re oriented once they return; so I just created a shell activity (“Launcher”) with the correct app label which simply replaces itself with the real front Activity, just so I could get the labelling right. There’s probably a better way, like changing the label once the activity launches. In fact, I just tried that out (setTitle at the beginning of onCreate) and it works fine. Heh – live and learn.

Also interestingly, when I noticed this and changed the label, Android didn’t handle the change very well, at least in the 1.5 emulator where I test this (likely fixed since). The icon with the old label remained, but it wouldn’t actually load the app (error), and there was no new icon/label. I had to un-install and re-install the app to get it to launch properly.

Displaying DB data

I was going to follow up a bit on my last post, but I think I’ll do it with another post.

Onward

Anyway, the release is out there, so please let me know what you think of it. And feel free to hack it up if you want to see your own improvements! Github can have your own clone set up in seconds.

I may start working on the website for this sooner rather than later. SpringSource released some kind of library to assist with Android so I’m itching to try it out!

Android UI – making the simple things virtually impossible

Know what I need? A “Stupid Android UI Tricks” book. I swear, there’s just so much about programming the native UI that just seems completely random and ass-backward. Are all UI APIs this bad?

Here’s the latest fun: I created a dialog where you can enter something in a text editor field. Only, you can’t on my Nexus, because the soft keyboard won’t come up. I don’t know if that’s normal behavior or if I attached something to the field that gets in the way of the keyboard showing up. I thought maybe it was the OnFocusChangeListener I’d set, but I commented that bit out and it still won’t come up. As an aside, sort of, it’s stupid that you can only add one listener for any given event. I have a dialog where I attach a listener in the generic superclass, and then I want to add to that event’s behavior in a subclass. Can’t  do it. I’d have to duplicate or proxy all of the behavior from the parent listener. Where’s the reuse of code? Why aren’t listeners all implemented as daisy chains?

While I’m ranting, why do I even bother creating dialogs? Every time I do, I find something about its intended behavior that requires an Activity to be in play. The latest: I have a dialog where I want to let the user pick a ringtone. Problem is, the only API exposed for this involves a call to startActivityForResult, and how is that result returned? By the onActivityResult callback on the calling Activity. So if you have a dialog and want the user to pick a ringtone, you have to get the Activity to relay the result to the dialog, which means recording the current dialog in a field somewhere in the activity, and adding a callback method on the activity that could have been totally avoided just by adding an implementation of startActivityForResult that accepted a listener for the result. Would that be so hard? Anyway I think the lesson is to create all non-trivial dialogs as Activities that are just styled as dialogs.

Back to the problem at hand. What else might be going on with my missing keyboard? Here’s someone with a similar problem, (and a long thread on the same topic), though I think they’re just not getting the keyboard at dialog start, not failing to get it ever. Anyway I shouldn’t have to add a listener just to get a keyboard. That’s ridiculous. Android should handle this automatically. What could I be doing that’s interfering?

BTW, its layout looks like this:

<EditText
 android:id="@+id/editor"
 android:layout_height="wrap_content"
 android:inputType="number"
 android:maxLength="5"
 android:layout_weight="1"
 android:layout_width="wrap_content" />

I created a completely unattached text editor (no listeners or anything) in my dialog and also couldn’t get a keyboard to come up for that.

Another random ranty aside: seriously, WordPress, why is the post input text area so small by default? The post is the center of attention; it should be as big as possible without crowding out the editing icons. Yeah, I know I can drag around the corner to resize, but I don’t wanna, ok?

Activity odds n ends, and eclipse platform source attach

It’s worth noting this bit of oddity about adding headers/footers to ListView and the ListView getting a wrapped adapter. On the other hand, he implements no empty view. I went back and looked at my reference app for a lot of how I want things to work, gtasks (wish the developer would open source it!). And wouldn’t ya know it – the text entry field that he has as the header? can’t be reached by navigation. I don’t feel so bad now :-) Though it’s still a nifty implementation I want to copy.

Another thought about having an “Add item” list header/footer – if it’s in the footer, the virtual keyboard will helpfully cover it up so the user can’t see what s/he is typing. So that’s a good argument for having it in the header. Though I think I’m gonna just try having a header element that acts like a list item and goes elsewhere to create a new item; I don’t think it’ll even require a custom adapter.

An interesting tidbit: Activity.finish() evidently is not a trap door like “exit” in C or bash; whatever method you’re in continues execution, and only when you complete whatever callback you’re in the middle of (since *everything* in an Activity is driven by some callback) does the Activity see that it’s time to leave and heads for the exits in an orderly fashion (first calling onPause() where you can helpfully check isFinishing() to perform any last-minute actions, then onStop, then onDestroy). I guess it seems obvious now that I think about it, but it was surprising at first.

Checking for isFinishing() in onPause() is probably a better way to handle the back key than onKeyDown() which gets called on every type of keypress.

I need to make a note to read this post on styles and themes more thoroughly. For now I’m just gonna use it to find out what I can put in textAppearance :-)

Ooh! A more coherent post about attaching platform source in Eclipse! It’s not trivial (which is good to know) but doesn’t look too bad. IRC folks helped me with that… damn IRC folks can be helpful! This was written quite some time ago, so I think it could use a little updating. Notably, you want to get a version of the repos that matches what you’re developing against. It’s not immediately evident which branch names to use – there doesn’t seem to be a logical scheme like “release-1.0, release 1.1, release 1.5…” When repo gets a project, it lists the branches and tags for it, which look something like this:
 * [new branch]      cupcake    -> korg/cupcake
 * [new branch]      cupcake-release -> korg/cupcake-release
 * [new branch]      donut      -> korg/donut
 * [new branch]      donut-release -> korg/donut-release
 * [new branch]      eclair     -> korg/eclair
 * [new branch]      master     -> korg/master
 * [new branch]      release-1.0 -> korg/release-1.0
 * [new tag]         android-1.0 -> android-1.0
 * [new tag]         android-1.5 -> android-1.5
 * [new tag]         android-1.5r2 -> android-1.5r2
 * [new tag]         android-1.5r3 -> android-1.5r3
 * [new tag]         android-1.5r4 -> android-1.5r4
 * [new tag]         android-1.6_r1 -> android-1.6_r1
 * [new tag]         android-1.6_r1.1 -> android-1.6_r1.1
 * [new tag]         android-1.6_r1.2 -> android-1.6_r1.2

…but often with a lot of clutter that varies from project to project. Now if you try to do repo -b with one of the tags (which seem logically named), it complains, probably because tags aren’t branches. Maybe there’s a flag to access those. But to get a branch, the way to go seems to be getting it by codename, i.e. cupcake, donut, eclair. Those are probably moving targets, while -release ones will be old. (You can’t win.)

And then when you’ve finally downloaded it, it needs moving around before you can even use it. And then there’s the poor guy saying his download never finishes. You know what? After I’ve got this figured out, maybe I’ll upload snapshots of zipped-up attachable code for each release to my free web hosting space for others to use without all the fuss :-)