Two bits that annoy me about standard Android apps

Perhaps I should start a running list, as there are sure to be more.

1. Facebook – every link that leads to the browser wastes my time going through some stupid Facebook warning *in the browser* that links can, you know, lead to unpredictable stuff, so be careful. Something that if it were necessary at all, would make a lot more sense on a PC (where no such warning is given) than a mobile device IMHO, and did I mention, wastes my freaking time and can’t be disabled as far as I can see.
2. The email app is atrocious. Not GMail, talking about what you use for e.g. an Exchange account. Has only rudimentary understanding of folders, and no way of getting notifications only for specific folders. Wonder if there’s a better app for that.

I also had a new idea for an app (probably already implemented somewhere) – hotspot fast track. When you’re at a public hotspot (or e.g. one at a hotel), every time you connect it wants you to go to some BS web page (usually requiring BS JavaScript) and click through some BS agreement to actually use the internet. As if everyone only ever used the web and anyone gave a shit about the stupid agreement. When you’re on a mobile this is a huge PITA, not least because you don’t tend to maintain a steady connection, and find yourself going back at that BS web page once you notice the network doesn’t seem to be working. The hotspot fast track app would look for wifi connections, test for BS portal redirections, and automatically “click through” known portal types that you authorize.

Advertisements

quick look at ActiveAndroid #androiddev

Just checking out ActiveAndroid, and while it seems to do a lot to make Android DB access easier, a few criticisms appear right up front:

  • Doesn’t having to extend the proprietary base class as your Application class seem a little… invasive? It’s like saying, this isn’t my application, this is an ActiveAndroid application!
  • I’m sure it wasn’t intended this way, but looking at the licensing terms:

The SOFTWARE PRODUCT is licensed as follows:
(a) Installation and Use.
Michael Pardo grants you the right to install and use copies of the SOFTWARE PRODUCT on your computer running a validly licensed copy of the operating system for which the SOFTWARE PRODUCT was designed [e.g., Windows 95, Windows NT, Windows 98, Windows 2000, Windows 2003, Windows XP, Windows ME, Windows Vista].

Let’s ignore for the moment the question of what OS this intended for… but isn’t this JAR going to be built into our app? Doesn’t this technically mean we can’t distribute the app?

  • This is based on reflection, right? So isn’t that gonna be kind of slow on Android?

Import/Export for LogMyLife #androiddev

Over the past few nights I whipped out an import/export capability for LogMyLife. Right now all it does is basically package up the database and a version file; later I expect I’ll include saving properties, which is why I’m including format version in the archive (I thought that was good foresight, as who knows what else might change). I wrapped it up in an activity you can call from the menu of the Main activity.

The implementation is reasonably straightforward, although I didn’t know a thing about handling files from Java. It’s predictably verbose but not too outrageous. I got a lot of help from this StackOverflow entry and this sun.com article. If you’re thinking of doing this you might check out how I did it for inspiration. I’d certainly encourage everyone to provide this capability so users can back up and transfer their app data!

I faced an odd little problem on importing: of course, it replaces the app’s DB. When I returned to the main activity, I returned a result code indicating this had happened, and had it close the database handle and reinitialize the components that displayed information from the database. But something seemed to be holding on to a database cursor and requerying it, and I couldn’t quite figure out why that was happening. Eventually I decided it would probably be simplest if I just have the activity restart itself from scratch. An answer on StackOverflow helped with how to do that – it’s not totally obvious; basically, just finish() the activity, and then (before exiting the same method) start it again.

Gingerbread is out, woo! And the Nexus S is coming; but I want a phone with a keyboard, dammit. Once my Nexus One gets 2.3 I’ll likely try to sell it in favor of the G2. Even though tethering is extra, which is wrong and bad and to be vehemently discouraged, but I don’t use tethering anyway.

Exploring ApiDemos; misc Android

Android 1.5 is down below 8% market share. If my wife’s Cliq ever gets an upgrade I’m dropping that platform like a hot potato. What’s interesting is that Eclair is actually still more common than Froyo (40%) – you’d think if they’ve done the work to get the device to 2.1, and seen how quickly versions change, it shouldn’t be too big a step to 2.2. Oh well.

I’ve been looking through ApiDemos to learn. While most of the demo classes seem well-commented, amusingly the ApiDemos.java file itself is not, and it does some non-obvious things involving searching the package manager for intents to dynamically create the lists being browsed. The upshot is it’s less than obvious how to find the sample code that matches the sample functionality you browse to – nothing tells you how to make the mapping, and it’s not always obvious. The actual mapping is between the label listed in the AndroidManifest.xml file for the activity (which is what you see in the app’s list browser, except that in many cases the actual text is in the strings.xml file) and the class name listed with it, e.g.:

<activity android:name=".view.Tabs1" android:label="Views/Tabs/Content By Id">

I would argue that the mapping between what you see (Views/Tabs/Content By Id – which again is often in strings.xml for no good reason I can see) and the class (com.example.android.apis.view.Tabs1) is far from obvious. Call me crazy, I think a README or at least a couple lines of comments in the main class would be in order. I should submit a patch.

Found a little nugget in ApiDemosApplication.java (which is otherwise empty):

PreferenceManager.setDefaultValues(this, R.xml.default_values, false);

This is a one-time setting of default prefs. Now of course, default_values.xml couldn’t be something simple like key-value pairs. It’s a PreferenceScreen like you would use for defining a PreferenceActivity. You wouldn’t know about those from the dev guide, unless you like decyphering reference docs. But as it happens I learned about these at some point and created a prefs screen with them in LogMyLife… which currently has no effect, so I need to do something about that.

I finally got around to gathering sources for the 2.2 platform to attach in Eclipse. I’ll have to update my article one of these days. Aside from the new sources, I should include the Apache license files in order to be proper.

I’m looking at migrating this blog to Blogspot. WordPress has neat themes but it deliberately blocks integration with tools like Adsense and Google Analytics. Also this editor drives me nuts. We’ll see.

App inventor first fiddlings

I’m finally getting a chance to try out App Inventor.

The first thing I found is that Java applets and jnlp seem to crash firefox on Fedora 13. That’s a shame. But the Chrome browser seems to do better, so I proceeded forward with that. Also, it looks like Google heard my complaint and, in addition to a .deb package, now provides a simple tarball for non-deb Linux users (that wasn’t so hard, was it?).

The first thing that comes up when you visit the site and have access is some kind of UI builder thing. Among the first things I noticed about this is that it only has LinearLayout and TableLayout. I guess that’s for the sake of simplicity, but… no RelativeLayout? It’s not obvious how to use everything that’s there, or how to hook anything up to actions. Things became more interesting when I discovered the “Blocks Editor”.

BTW, was there some kind of manual to read? I don’t remember seeing one, but I probably breezed by it. Ah yes – I started there and headed down the installation rabbit trail. Back to the intro; it brings up both the Designer (that’s the first thingy) and the Blocks Editor right away. So there it is.

Of course I quickly built a layout with a text editor and button and deployed it to my phone (emulator, actually) right off to see it in action. That worked. However later on when I was working on a regular app in Eclipse and tried to deploy it, that seemed to fail. The log was full of errors I’m not used to – something about not matching a certificate. Did app inventor’s tooling ruin my emulator for other development? Good to find out before I try it on my actual phone.

So, I just tried the first tutorial. It’s fairly cool that while you’re building your app in the tool, it’s being updated at the same time on the phone. Obviously, there’s an app inventor component running on the phone to make that happen. When you’re done building it, you can package it as a standalone app. While I was waiting for that to finish, I brought up adb logcat to see what was going on. It said that the adb server was “out of date” and restarted it – this apparently cut app inventor’s connection. I don’t know if this is specific to Linux or even my system, but it doesn’t seem like you can use it in parallel with the other SDK tools. Then again, logcat didn’t get cut off when I reconnected app inventor.

As I read initially, there doesn’t seem to be any ability to create multiple screens. But there’s a “canvas” block that looks promising for achieving a multi-screen effect.

When I went to add some contacts for the second tutorial, the act of leaving the app inventor setup evidently triggered the “server is out of date” problem again. I wasn’t able to reconnect app inventor to the emulator; I eventually restarted the Blocks Editor. It seems to be necessary to re-download the Blocks Editor each time – I can’t just re-start the one I already have, or it doesn’t come up with the project contents.

That’s about all I have time for now. It looks like an interesting way to introduce someone to creating simple apps to the phone – especially if they’re graphically minded. I’ll show this to my Android group tomorrow.

 

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?

Exploring Android ListView

Some time ago I summarized some things I’d discovered about headers and footers on ListView in Android. Oddly enough, despite the dearth of real content there, it is consistently one of the top-viewed pages on this rather esoteric and scatter-brained blog. I think the simple reason is this: ListView is frustratingly obtuse if you try to do anything that’s not explicitly described in the docs, and because everyone needs to use Listview to display lists of information, everyone is looking for solutions to fairly common usage problems.

Recently I’ve had reason to revisit ListView’s oddities with a vengeance. I created some example code I could play with. I think this may be useful to others, so I created a github repo to share it – it will evolve as I try things out / figure things out. Let me know if it’s useful to you or if you have any better ideas for how to accomplish what I’m attempting.

Continue reading