Friday, March 27, 2009

Dynamic Code Loading

I've been looking for a way to upgrade an Android application without any interaction with the user, and pushed through several options. Along the way, I found a few dusty corners of Android which I think are worth mentioning.
The first thing I wanted to try is just remotely installing an application - download it from some server, and then install it. Long story short: can't be done. Applications don't have the security permissions to install other applications. Certainly, that's a good thing, and it was a relief to see that it isn't so easy.
So then I thought "Why not just use a framework that dynamically loads some class files and executes them on some standard interface, such as Runnable. As I expected, I wasn't the first to think this. It turns out that some really sharp guys got it running for Apache Felix, which is a framework that does basically what I'm looking to do. But the trick is, they did it with 0.9 of the SDK. When Google put out 1.0, they changed some permissions so that it would no longer work. The in's and out's of this are interesting, so let's delve a little deeper.
As you may know, Android uses a custom VM called dalvik to run Java. Why? Maybe just to circumvent Sun, but my guess is they have some other trick up their sleeves. Dalvik doesn't use standard Java .class files, but instead uses .dex files - a format that has yet to be finalized (They're still fiddling with the opcodes). With an ordinary JVM, a developer could download a jar, unpack it, and use the classes inside. With dalvik, developers need to re-code their .class files into .dex files before loading them. That gets done by a tool called dx that ships with the Android SDK. So far, so good. Now, standard java class loaders can't handle .dex files, so the use of a different class loader is needed. Here's where it gets problematic. 
First of all, there's no documentation. Up until October, that was no problem. But when Google released SDK 1.0, they locked up some security. Now the undocumented class loader puts the bytes of the unpacked class into a part of the disk that only the system has access to. If an application tries to load a class there, it fails the permissions check. Is there a workaround? Not that I can find or figure out. Luckily, I'm not the only one trying to do this. In fact, Google is going to be officially releasing a dynamic code loading API in Cupcake. Those of you with Macs or Linux boxes can download the source and see it in action. But if you're looking to put something on the Market now that can load code dynamically, I'm afraid you're just out of luck.

Saturday, March 14, 2009

Launch Day!!

After getting some fresh graphics for the Toddler Percentile Calculator, I'm happy to announce that it is now available on the Android Market. The price is $0.99, and like all apps on the Android Market, there's a 24-hour return policy. So give it a try, risk free, and if you don't like it, just return it. Also, I'd love to hear your thoughts about it. Anything missing? Want it to support older kids? Shoot me an email and let me know!

Wednesday, February 25, 2009

Android 101: Launching dialogs - part 2

So, we went over a simple method of getting user data from a dialog last time, now let's get a little more complicated.  In lots of situations, getting one piece of data per dialog isn't good design.  Wouldn't it be great if we could package a bunch of data together and move it between dialogs as a single unit?  Before we get into data passing, though, let's take a step back and quickly touch on how to launch a dialog.  Last time, we used an AlertDialog.  That's good for a quick popup, and getting a boolean-style answer, but it's not meant for really anything else.  Most of the time, it's best to subclass Activity.  If you're just looking to launch a dialog and don't need to get a result, it can easily be done like this:
Intent custom = new Intent(this, MyDialog.class);
startActivity(custom);
On the other hand, when you want to do something (such as get data from the dialog) after it closes, it gets called like so:
Intent custom = new Intent(this, MyDialog.class);
startActivityForResult(custom);
When the dialog is finished collecting information, it fires the calling class's onActivityResult().  The call signature is simple enough:
protected void onActivityResult(int requestCode, int resultCode, Intent data);
The key piece we care about right now is that Intent.  What's in there?  That depends on what that dialog did.  Let's say the dialog took a String input which is meant to be given to the calling method.
// Package up the relevant data for the calling method
Bundle bundle = new Bundle();
bundle.putString("question", question);
Intent returnIntent = new Intent();
// Insert the data into the Intent that gets passed to onActivityResult()
returnIntent.putExtras(bundle);
setResult(RESULT_OK, returnIntent);
// Close the dialog
finish();
As you can imagine, unpacking is basically the reverse of packing, and it goes in onActivityResult(), as I mentioned earlier:
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
Bundle extras = data.getExtras();
String question = extras.getString("question");
// use the data here
}
Notice the use of a string key.  I don't like putting hard-coded strings in code - they're bad for internationalization and belong in strings.xml.  But since these strings don't normally end up displayed to the user, there's no need for internationalization, so hard coding is easier to write and faster at runtime.    Anyway, be sure to use matching keys. So, that's all for part 2.  Drop me a line if there's a particular topic you'd like to hear about.  Happy coding!

Friday, February 6, 2009

Android 101: Launching dialogs - part 1

Hello!  We're going to talk today about a common task in Android, and user interfaces in general - launching a dialog to retrieve data.  
If we want very simple information, such as an OK/Cancel or Yes/No, we can use AlertDialog.  The code would look like this:
new AlertDialog.Builder(this)
     .setMessage("Should I buy a new cell phone?")
     .setPositiveButton("Yes", myClickListener)
     .setNegativeButton("No", myClickListener)
     .show();
It often makes more sense to implement OnClickListener in the class that's launching the dialog so that the data is sent to the object that launched the dialog.  Here's how that generally looks:
public class MyDialog extends Activity implements OnClickListener{
...
public void foo()
{
 new AlertDialog.Builder(this)
      .setMessage("Should I buy a new cell phone?")
      .setPositiveButton("Yes", (OnClickListener)this)
      .setNegativeButton("No", (OnClickListener)this)
      .show();
}
@Override
public void onClick(DialogInterface dialog, int which) {
// "which" contains the result of the alert dialog
}
}
Execution passes from foo() to the AlertDialog.  When the user presses "Yes" or "No", the dialog is closed and onClick() is called.  From there, we can update object members and take other actions based on the results of the dialog.  It's a pretty straightforward mechanism once you watch it work, and it's a useful way to keep from writing tons of tiny classes that are tightly coupled.
Part two will talk about how to return multiple variables from a dialog using Bundle and Intent.

Sunday, February 1, 2009

Flarb!

I'm happy to announce that we've got a new contract with Flarb LLC. We'll be porting Flarb's upcoming iPhone/iPod Touch release of Rune Stone Reader to the Android. Stay tuned for further details, but you can expect to see it on the Android Market this quarter.

Thursday, January 22, 2009

SlideMe & Voeveo

There are now two places that you can purchase the Toddler Percentile Calculator: SlideMe and Voeveo.

Wednesday, November 5, 2008

Toddler Percentile Calculator v1.0a

Here's a screen of our first software release, exclusively for Android:
This small app can calculate percentiles of weight and height for any child 72 months (6 years) or younger. It accepts both English and Metric units. Stay tuned for details on how to download!