Most of my posts up until this point have avoided a real discussion of the actual code behind my Androids apps. I didn’t want to bore anybody with details they didn’t care about; but since it seems like some people do care, I’ll start sharing some Android coding tips! I also had the realization that if/when the lab has to replace me with another Android coder, that person may benefit from what I blog. Bus factor++ indeed!
Before I delve too far into things, I feel it would be worthwhile to think about some structure to this series of blog entries. For today I will blog some of my fresh discoveries, lest I forget them in typical programmer fashion! In the future, I will try to write a couple of entries a week with guides and gotchas written out for future Edwardslab (or any other) Android coders. Without further adieu, I shall explain a bunch of knowledge that just kicked my butt for the past couple of days! (See the Read More cut for random knowledge)
I had been working coding the asynchronous downloads for MM using the Thread and Handler classes, and the Message object. As usual when dealing with this type of code, I made some mistakes with the way the UI was managed, and Android got mad at me. (Sidenote: in Android, only the thread which creates a UI object is allowed to modify it! That means that you can’t update a text box or other display from a worker thread.) I was googling around for the proper solution to my problem when I stumbled upon this little gem. Yes, that is a specific AsyncTask class that Romain Guy is talking about towards the bottom half of that post, and yes, I felt stupid for never knowing about it before.
What AsyncTask does is simplify the whole business of thread creation and handlers for you. I found it a bit too much to really understand quickly, but once I wrestled with it for a couple of hours it made sense to me. Essentially you have four methods: onPreExecute() , doInBackground(Params…), onProgressUpdate(Progress…), and onPostExecute(Result). doInBackground() is the only one of those four that you cannot touch the UI with. The other three are designed to run in the main UI thread and initialize, update, and destroy (respectively) your progress bar or whatever. They are also where you load up the results of whatever work you were doing.
There were also a host of discoveries I made while working on my personal app (more on that another time…), which I found very interesting. I was mentioning to Rob that I think I sometimes get tunnel vision with MM, and coding something separate often ends up teaching me a lot. I usually find tough problems a bit easier after a short mid-day break working on something different. One such discovery was this page, which showed me that there are a lot of ways to manipulate the user interface in Android. The options given by RelativeView are great for generating a basic layout by describing where things should be in relation to eachother. However, it is useful to augment this with the Scale-independent Pixel (written ##sp) spacing. Also described on the same page are the color formats Android accepts, and information on the 9patch image format.
9patches allow users to add custom graphics to Android. I toyed with this a little bit, but haven’t completed the code for it yet (by that point I was itching to get back to work on MM). Basically the image format allows a designer to specify which parts of an image should stretch when it needs to become bigger. For example, if a button graphic needs to fit more text, the button needs to know how and where it can stretch. This is done by adding a 1px by 1px border around the image, and drawing black lines on the edge to show where it can stretch.
One last tidbit before I conclude this (rather long) post, was a discovery of how to keep the screen from sleeping: getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); This is effective only for the application in question, and (though I didn’t look up the exact command) there should also be a way of turning it back off. If an application must display information to the user for an extended period of time, without expecting user input in response, this is a helpful flag to set!