abstractwankery.com
taking it to the next level
Detecting scrolls in an Android ScrollView widget
Posted by Nick at 1:58 PM
So, Android.

You would think that Google would have an event available for when someone scrolls a ScrollView widget. After all, it's the basic way to make some view scroll. Even better, there is an event for the AbsListView and other scrollable widgets. Turns out, there is an event that gets fired in a ScrollView, but you have to subclass the widget to get at it. Then, you have to figure out how to get that message back to your controller.

Lame.

So, for those of you who want to see if a scroll changed on a ScrollView, do the following:

1) Create a class, call it whatever you'd like, but subclass ScrollView. You'll probably need to override the three existing constructors to be able to instantiate from your controller or XML layout.


public class ExampleScrollView extends ScrollView {
    public ExampleScrollView(Context context) {
        super(context);
    }

    public ExampleScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ExampleScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
}


2) Add an interface within our new class to be able to set a listener. We'll call it something different so we don't override any existing OnScrollListeners.


public interface OnScrollViewListener {
    void onScrollChanged( ExampleScrollView v, int l, int t, int oldl, int oldt );
}


3) Let's add a private attribute and a way to set that listener in the class.


private OnScrollViewListener mOnScrollViewListener;

public void setOnScrollViewListener(OnScrollViewListener l) {
    this.mOnScrollViewListener = l;
}


4) Now, set onScrollChanged to fire the event we provide.


protected void onScrollChanged(int l, int t, int oldl, int oldt) {
    mOnScrollViewListener.onScrollChanged( this, l, t, oldl, oldt );
    super.onScrollChanged( l, t, oldl, oldt );
}


You're done! You can now set up one of these in your XML layout, or built on the fly. Set your new listener like this, provided you have one in your layout with an id of 'example_scroll_view':


ExampleScrollView exampleScrollView = (ExampleScrollView) findViewById( R.id.example_scroll_view);
exampleScrollView.setOnScrollViewListener( new OnScrollViewListener() {
    public void onScrollChanged( ExampleScrollView v, int l, int t, int oldl, int oldt ) {
        Log.d( "Scroller", "I changed!" );
    }
} );
0 comments
Lifecycle of an Android Application
Posted by Nick at 1:58 PM
Every time I get a new gadget, something possesses me to try to write an application for it. It's happened with dang near everything since the Newton, yet only a few gadgets have ever had a finished project. I tried the hardest on Symbian, but never came up with anything useful. I'd like to blame the SDK, but you should never blame your tools, no matter how much they completely sucked.

In October of 2008, a brand new T-Mobile G1 arrived via UPS, one of the first Google Android devices to hit the market. I had always owned smartphones, whether they ran Windows Mobile or Symbian (S60 or S80), but I wanted to get something that was easy to develop for, and would work well on my network. So, Symbian was out (hated the SDK), iPhone was out (Just started supporting apps, plus no one wants to be on AT&T), Blackberry was out (SDK even worse). Android seemed like a really neat, but young option. Being on the bleeding edge never scared me, it just usually screwed over other people.

So, approximately 3 days after receiving that G1, I downloaded the SDK, and started to use my extremely rusty Java skills to bang out a LiveJournal client for Android. It's not as though I still really used LiveJournal, but I felt like it'd help me try out all of the neat APIs in Android. Web services, location tracking, image capture and manipulation, they were all there and usable. A shell of an application started to emerge around a series of mocked up layouts, and I was able to hook up login, posting, preferences, and user pictures in a short amount of time. ElJay was born, and I even wrote about it here. I'm amused at how proud I was that it was pretty complete after a few days -- because it shows. Since I decided to dive right in instead of going through tutorials and example applications, it was subject to many of the first time Android developer errors. Screen rotation would lose settings, or interrupt a login, or interrupt a post. Web activity would throw exceptions that I never caught. Nothing was in a service, so switching applications or views would interrupt the same interruptables as above. Everything I did was in onCreate, so switching back to the application after Android cleaned house meant that someone would have to log in again. Sometimes, state wasn't kept, so you'd post to no account at all. It was a barrel of laughs. I updated and updated until it was a mess of spaghetti code and generic exception catching. Android 2.0 finally broke it, and I didn't care for a while.

I eventually pulled it from the market.

... until the screams entered my inbox.

A few weeks ago, I recommitted to ElJay, but instead of running through to try to fix it, I made the best and worst choice I could make, and started over. This time, I started it as if I were doing one of my Perl-based web applications, or writing a desktop application -- I started with the back end. My first task was my XML-RPC interface, followed by my LiveJournal model. I created a unit test suite for those external interfaces. I created a suite for all of my display controllers. After a while, I got to the point where I had a decent unit test suite, and a few test accounts that passed the unit test suite. This process took a lot longer than the "few days" it took to bang out the first version, but from a system level, it worked well. It also helped me solve a long-standing bug I ran into in the first version, where the default Java XML library used by Android doesn't handle some output from LJ very well. Hey, I could have saved myself from a rewrite! ... Nah.

Tangent.

Only then did I start working on the user interface. This time, I could actually plan for exception handling, threading, the external service, the sync API, even basic user interaction. It also honors resolution independence properly, since I'm no longer using pixels as measurement. :P It's amazing how much more confidence I feel in this application -- not that I believe it's bug free or foolproof, beta testing will prove that wrong within minutes -- but that I can easily work with it, fix issues, and section pieces out for later. Things are getting really close now, and the beta rolls out in less than two weeks.

For those keeping track, the first version allowed posting with user pictures, security options, tracked your location, worked with tags and moods, and allowed you to save entries for later. The new one does all of that -- and well -- but also adds friends list support, attaching photos to your posts, and with any luck, manage your messages. I'm also throwing ads in, but they're optional.

It does live.

1 comment
Fun facts for hard times
Posted by Nick at 8:17 PM
When developing for Android, the default button height is 48 dip.
0 comments
Things that are dumb: Android Emulator
Posted by Nick at 5:35 PM
In today's episode of Things That Are Dumb:

I sat here fighting with the Android emulator, trying to get it to work in Snow Leopard. Every time I started it up, no matter if I started the Android 2.0 SDK or the 1.6 SDK, it would start, then force quit with a EXC_BAD_ACCESS error. Twenty minutes of this crap, no luck. I'm rebooting, moving things around, and finally pull everything from the machine.

It was my USB headset.

That's dumb.
0 comments
ElJay, a LiveJournal Client for Android
Posted by Nick at 9:47 AM
This morning, I uploaded my first application to the Android Market. As a quick background, Android is Google's new mobile operating system, designed for smartphones and similar mobile internet devices, and similar in theory to the iPhone operating system. The Android Market allows third party developers to distribute their software through a centralized location for a small fee. As of right now, all software on the market is free, so you don't make any money on the process.

I decided, for some reason, that my first application was going to be a LiveJournal client, that is, an application that enables easy posting to a LiveJournal blog. I would be able to work with simple HTTP requests, design a simple but effective user interface, play with threads a little bit, and touch the Location Manager (GPS/Tracking) if I was lucky.

I was.

I'm happy with the final product, and it's modular enough that I can add to it later if I wanted to, or fork it to a generic blog posting tool if I felt crazy enough. You can log into your LJ account, select user pictures from a live gallery of all of your user icons, dynamically retrieve your location from GPS or fuzzy tracking, add moods or your current music. It's remarkably complete for a few days of work, and I think I want to add the ability to attach photos later on, as well as limit to certain friend groups or post to other communities. Trivial tasks in the long run, but I wanted to get it out there as soon as possible.

Click through if you want to see what it looks like.
You can click these images to get a full 320x480 view.


Login screen, pretty simple. This authenticates you to LJ, so ElJay can grab user pictures, moods, groups, etc.


Initial post screen, with a subject and a body. It starts out bare so you have room to type, but via the below menu or the Settings menu, you can set which fields it shows by default.


When you hit the menu key, this is what appears. Change settings, edit the user picture, or add fields to your post screen.


This is the post screen after adding all three fields. You can even use the built in wifi/cell mapping or GPS to get your actual or approximate location via the 'Get' button.


Userpic browser. Uses the standard image chooser in Android to show you all of your user pics. Just flick your finger to scroll through the available pictures. Hit back to cancel.
2 comments