These weeks I’ve proposed myself to have a look at Google’s Android and try to learn how to write applications on it.
I went to the Android main page and, from there, I followed the “getting started” stuff to download the SDK, Eclipse and started to understand the framework.
The framework is a bit different from what I’m used to. The applications have 4 building blocks:
- Activity: Tasks that the application performs (from the user point of view). For example, manage a collection of text notes. Activities can also request “intents”, that is, use the system to locate a component that can manage the action that the app wants to be done. For example, edit a single note. Intents are a clever way to reuse functionality.
- Intent receiver: These are methods to attend external events asynchronously.
- Service: Functionality provided to another applications by running code in the background.
- Contend provider: A standard way to provide data to other applications.
Android features nice pieces of code, like SQLite database. The intended way of working relies heavily on XML config files, which make easier to build user interfaces and makes me remember the way UIs are done on other frameworks (I’ve heard that Glade uses XML files too).
My wish about Android would be to develop “Caterpillar”, a robotized (this is, for Android) version of Berto’s Vagalume. But for that there’s still a long way to go through.
At this moment, I’ve already created the “Hello Android” app and I’m following the tutorial. I’ve just completed exercise 2 this night. As I advance more, I’ll update this post to let you know about my progress.
The three exercises of the tutorial plus the extra credit one are now completed. The next step will be to have a look to common Android tasks and to continue learning from there. I’d also like to try DroidDraw for GUI designing.
I’ve started to write Caterpillar. An early version of the GUI was designed using DroidDraw (see the previous update) and fine tuned by hand. Fortunately, DroidDraw lets you not only export, but also import a layout text description.
The very first task I tried was to try to play an arbitrary MP3 file. I looked into the media APIs and tried some methods to load the test sound (as a raw resource, as an external URL and as a local file), but didn’t succeed. At first I thought that the emulator hadn’t the audio enabled, but after adding the “-useaudio” option, that shown not to be the problem.
Then I found this post (spanish) and this other that gave me some hints. At this moment I know that the sound system works, because I can hear the system sound when raising up the volume, but my media player instance is still null, despite I’m using an MP3 lesser than 1 MB in size. Yeah, the emulator has a 1 MB limitation on that. :-/
On this Google groups thread there are people saying that Android has problems playing MP3 from online streams, because it pretends to copy the whole stream to disk (SD card or whatever) and then play it. The problem has been reported to the Android bug tracking system.
After a month of silence I have to say that I’ve continued my work on Caterpillar in my spare time. Having a look to the Vagalume source code and doing some tests with Firefox and wget, I’ve developed the session management and playlist fetching and parsing code, so I can end up with a bunch of tracks and all the required information about them: title, author, album, picture, audio file URL…
I’ve decided to overcome the limitations of the Android media player by downloading the tracks one by one and feeding them to the media player as local files, erasing them when the media player has finished playing each one. It’s a bit weird solution but is the only one I’ve found.
The TrackDownloader, as I’ve named it, is created by the controller, which registers itself as an observer. When the downloader has got enough data, it notifies the controller, which starts up the media player. In the meanwhile, the downloader keeps downloading in the background and, when the transfer is about to finish, notifies the controller about that, just to spawn another TrackDownloader for the next track. When the track has definitely ended, the controller dismisses it and it’s erased from disk to save space. I haven’t tested the TrackDownloader for the moment, only coded it.
I’ll keep hacking. Stay tuned!