Instantanea is my latest invention. A simple camera application for Android devices, with an emphasis on speed and ease of use.
I usually go around with a pocket camera in my bag, but since I got the Nexus One I'm tending to leave the camera home and simply use the phone to take pictures. But I was getting increasingly frustrated with the stock camera application, and instead of writing a post detailing how horrible it was and how their programmers should be hanged upside down from their toes, I decided to write my own camera application :-)
Since you can read all about its features in its page, I'll get technical here instead. So let's go!
Shhhhhht (it's silent)
The first thing I do when getting a new digital camera is removing any shutter or focus sound. They are idiotic, specially because they are not traditional cameras with a big shutter that opens and closes and makes a lot of noise in the meantime, so why should my phone do it?
The reason why you get a shutter sound with cameras in phones is because some _ _ _ _ _ _ * politicians decided it was worth to legislate and impose this restriction in the name of decency or whatever. Like there aren't worse issues to think about.
I personally think it is incredibly silly, inconvenient and annoying, and although you can avoid it by silencing the phone before taking a picture, I forgot doing that most of the time, scaring everybody that heard that abominable sound every time a picture was taken.
So away went the noises (programmatically). When you leave the activity, the volume levels are restored. It hasn't got much mystery, but it's quite sad we're forced to do these things to work around idiocracy. What about free will?
There's another way to silence the phone if you have rooted it, which is just replacing the shutter ogg file with a silent one, but it is equally sad to have to root a phone in order to control what it does.
Maybe you'd like to star this bug?
Crashed? Reboot to fix it!
I found that if an activity that was using the camera crashes without releasing it, then nobody else can use the camera again until you reboot the phone. I was making the application crash a lot at the beginning of development, but I thought it was only me. Then I discovered that the stock Camera app was also able to crash and kidnap the camera, thus preventing my application to use it!
I wonder if that's a desired behaviour or just something that will be fixed in the future. But the only solution for the time being is to reboot the phone :-/
Custom widgets and attributes
I've learnt a lot about developing custom widgets --and at the end, all the elements in the GUI are customized versions of standard widgets or totally new widgets. It's been fun for the most part of it, except some desperation moments such as when I couldn't understand why Eclipse wouldn't stop spitting errors about custom attributes I had just defined and it couldn't find, and it kept droning on and on and on and on and on... thus preventing me to fix the errors, because the error console got focus. Very helpful.
The reason for that infinite complaint is that aapt seems to be very sensitive and strict, and if it finds something slightly inappropriate it will just refuse to continue processing and just die, leaving the generated R.java file in an unfinished state. The best of all was that even when I fixed all errors, Eclipse still showed a red cross over the project folder and refused to build anything. I found the solution for this was to clean the project (Project → Clean...) and then press Build as usual.
Connecting with the Gallery and Media Database
This was one of the most confusing aspects in the whole development process (probably right after the custom attributes thing).
Why do we need to add pictures to the media database?, I see you asking. Well, turns out that Android devices maintain an internal database of media files, and make that database available to multimedia applications so that they don't have to iterate through every folder in the SD card to find about songs, videos, images, etc. Every time the SD card is mounted, this database is regenerated.
If you took pictures without adding them to the media database and then went to the Gallery application, you wouldn't be able to find your recently taken pictures, unless you rebooted your phone before opening the Gallery. Not very convenient, is it?
Therefore what I'm doing is adding the picture once it has been taken, by using a MediaScannerConnection and some voodoo. I've seen some people recommending to trigger a "sd card mounted" intent but that's overkill and inefficient: you're forcing the system to regenerate the entire media database! Please don't do that. Just add one file!
With regards to the Gallery, to open a picture in the gallery you need to send an Intent with action = ACTION_VIEW and a content:// style Uri as data parameter. But it seems it only accepts certain Uris: the ones that the MediaScannerConnection returns once it scans a file for adding it to the media database.
So even if you can take any File object and convert it to a Uri (with Uri.fromFile) the gallery will just refuse to open it. It will only accept Uris that begin with content://, not file://.
It was mildly annoying to discover that (specially because I couldn't find any warning about that anywhere).
In any case I've got user suggestions asking for a simplified, integrated custom gallery, so I might ditch the Gallery stuff entirely and just implement a simpler one myself ;-)
2.1 or better
Although my main phone is a Nexus One running Froyo (2.2) and 2.2 provides more options and nicer interfaces in some cases, I decided to support 2.1 too. For this, I've built the project with target SDK = Android 2.2, set the minSdkVersion to 7 (or 2.1 in other words), and I'm detecting in run-time which version the device is running, by using the android.os.Build.VERSION.SDK_INT constant. Then it's a matter of comparing with (for example) Build.VERSION_CODES.FROYO in order to execute this or that code branch.
And of course, being the type of application it is, which involves lots of physical stuff such as GPS, orientation changes, camera... there's a lot of testing in the real devices!
Every time I added some new functionality I tested it in both devices to make sure it worked properly, specially if the functionality involved a different code path depending on the specific SDK version.
And I'm really glad I came up with this idea, because I've changed their design and sizes a lot of times during the development and I'm pretty sure I would have felt way more reluctant to change anything if I had had to redo bitmap icons every time.
It's been quite funny to learn more about Inkscape. It is super powerful with only a handful of tricks... maybe I should write about them. Meanwhile, I highly recommend it! Although you need to be extra cautious about crashes, and keep your fingers ready to trigger a CTRL+S as soon as you do something that you don't want to lose. I found Inkscape crashed a lot when editing moderately complex paths.
I've got several ideas for the future, but I'll keep them secret until I actually implement them. That way they will be a pleasant surprise when you find them in an update ;-)