Chapter 33

Leveraging Java Libraries

Java has as many third-party libraries as any other modern programming language, if not more. These third-party libraries are the innumerable JARs that you can include in a server or desktop Java application—the things that the Java SDKs themselves do not provide.

In the case of Android, the Dalvik virtual machine (VM) at its heart is not precisely Java, and what it provides in its SDK is not precisely the same as what any traditional Java SDK provides. That being said, many Java third-party libraries provide capabilities that Android lacks natively, and therefore may be of use to you in your projects, if you can get them to work with Android's flavor of Java.

This chapter explains what it will take for you to leverage such libraries and describes the limitations of Android's support for arbitrary third-party code.

Ants and JARs

You have two choices for integrating third-party code into your project: use the source code or use prepackaged JARs.

If you choose to use the source code, all you need to do is copy it into your own source tree (under src/ in your project), so it can sit alongside your existing code, and then let the compiler perform its magic.

If you choose to use an existing JAR, perhaps one for which you do not have the source code, you will need to teach your build chain how to use the JAR. First, place the JAR in the libs/ directory in your Android project. Then, if you are using an IDE, you probably need to add the JAR to your build path (Ant will automatically pick up all JARs found in libs/). This is definitely required for Eclipse, where you will need to place a reference to your JARs under the Libraries tab of the Java Build Path page.

And that's it. Adding third-party code to your Android application is fairly easy. Getting it to actually work may be somewhat more complicated, however.

The Outer Limits

Not all available Java code will work well with Android. There are a number of factors to consider, including the following:

  • Expected platform APIs: Does the code assume a newer JVM than the one Android is based on? Or, does the code assume the existence of Java APIs that ship with Java 2 Platform, Standard Edition (J2SE), but not with Android, such as Swing?
  • Size: Existing Java code designed for use on desktops or servers does not need to be concerned much about on-disk size or, to some extent, even in-RAM size. Android, of course, is short on both. Using third-party Java code, particularly when prepackaged as JARs, may balloon the size of your application.
  • Performance: Does the Java code effectively assume a much more powerful CPU than what you may find on many Android devices? Just because a desktop can run it without issue does not mean your average mobile phone will handle it well.
  • Interface: Does the Java code assume a console interface? Or is it a pure API that you can wrap your own interface around?
  • Operating system: Does the Java code assume the existence of certain console programs? Does the Java code assume it can use a Windows DLL?
  • Language version: Was the JAR compiled with an older version of Java (1.4.2 or older)? Was the JAR compiled with a different compiler than the official one from Sun (e.g., GCJ)?
  • Dependencies: Does the Java code depend on other third-party JARs that might have some of these problems as well? Does the Java code depend on third-party libraries (e.g., the JSON library from http://json.org) that are built into Android, but expect a different version of those libraries?

One trick for addressing some of these concerns is to use open source Java code and actually work with the code to make it more Android-friendly. For example, if you are using only 10 percent of the third-party library, maybe it's worthwhile to recompile the subset of the project to be only what you need, or at least to remove the unnecessary classes from the JAR. The former approach is safer, in that you get compiler help to make sure you are not discarding some essential piece of code, although it may be more tedious to do.

Following the Script

Unlike other mobile device operating systems, Android has no restrictions on what you can run on it, as long as you can do it in Java using the Dalvik VM. This includes incorporating your own scripting language into your application, something that is expressly prohibited on some other devices.

One possible Java scripting language is BeanShell (www.beanshell.org/). BeanShell gives you Java-compatible syntax with implicit typing and no compilation required.

To add BeanShell scripting, you need to put the BeanShell interpreter's JAR file in your libs/ directory. Unfortunately, the 2.0b4 JAR available for download from the BeanShell site does not work out of the box with the Android 0.9 and newer SDKs, perhaps due to the compiler that was used to build it. Instead, you should probably check out the source code from Apache Subversion and execute ant jarcore to build it, and then copy the resulting JAR (in BeanShell's dist/ directory) to your own project's libs/. Or, just use the BeanShell JAR that accompanies the source code for this book in the Java/AndShell project.

From there, using BeanShell on Android is no different from using BeanShell in any other Java environment:

  1. Create an instance of the BeanShell Interpreter class.
  2. Set any globals for the script's use via Interpreter#set().
  3. Call Interpreter#eval() to run the script and, optionally, get the result of the last statement.

For example, here is the XML layout for the world's smallest BeanShell IDE:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<Button
    android:id="@+id/eval"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="Go!"
    android:onClick="go"
    />
<EditText
    android:id="@+id/script"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:singleLine="false"
    android:gravity="top"
    />
</LinearLayout>

Couple that with the following activity implementation:

packagecom.commonsware.android.andshell;

importandroid.app.Activity;
importandroid.app.AlertDialog;
importandroid.os.Bundle;
importandroid.view.View;
importandroid.widget.EditText;
importandroid.widget.Toast;
importbsh.Interpreter;

public class MainActivity extends Activity {
  private Interpreter i=new Interpreter();
  
  @Override
  public void onCreate(Bundle icicle) {
    super.onCreate(icicle);
    setContentView(R.layout.main);
}

public void go(View v) {
  EditText script=(EditText)findViewById(R.id.script);
  String src=script.getText().toString();
  
  try {
    i.set("context", MainActivity.this);
    i.eval(src);
  }
  catch (bsh.EvalError e) {
    AlertDialog.Builder builder=
              newAlertDialog.Builder(MainActivity.this);

    builder
      .setTitle("Exception!")
      .setMessage(e.toString())
      .setPositiveButton("OK", null)
      .show();
    }
  }
}

Compile and run it (including incorporating the BeanShell JAR as previously mentioned), and install it on the emulator. Fire it up, and you get a trivial IDE, with a large text area for your script and a big Go! button to execute it, as shown in Figure 33–1.

images

Figure 33–1. The AndShell BeanShell IDE

importandroid.widget.Toast;

Toast.makeText(context, "Hello, world!", Toast.LENGTH_LONG).show();

Note the use of context to refer to the activity when making the Toast. That is the global set by the activity to reference back to itself. You could call this global variable anything you want, as long as the set() call and the script code use the same name.

Click the Go! button, and you get the result shown in Figure 33–2.

images

Figure 33–2. The AndShell BeanShell IDE, executing some code

And now, some caveats:

  • Not all scripting languages will work. For example, those that implement their own form of just-in-time (JIT) compilation, generating Java bytecodes on-the-fly, would probably need to be augmented to generate Dalvik VM bytecodes instead of those for stock Java implementations. Simpler languages that execute from parsed scripts, calling Java reflection APIs to call back into compiled classes, will likely work better. Even there, though, not every feature of the language may work, if it relies on some facility in a traditional Java API that does not exist in Dalvik. For example, there could be stuff hidden inside BeanShell or the add-on JARs that does not work on today's Android.
  • Scripting languages without JIT will inevitably be slower than compiled Dalvik applications. Slower may mean users experience sluggishness. Slower definitely means more battery life is consumed for the same amount of work. So, building a whole Android application in BeanShell, simply because you feel it is easier to program in, may cause your users to be unhappy.
  • Scripting languages that expose the whole Java API, like BeanShell, can pretty much do anything the underlying Android security model allows. So, if your application has the READ_CONTACTS permission, expect any BeanShell scripts your application runs to have the same permission.
  • Last, but certainly not least, is that language interpreter JARs tend to be…portly. The BeanShell JAR used in this example is 200KB. That is not ridiculous, considering what it does, but it will make applications that use BeanShell that much bigger to download, take up that much more space on the device, and so on.

Reviewing the Script

Since this chapter covers scripting in Android, you may be interested to know that you have options beyond embedding BeanShell directly in your project.

Some experiments have been conducted with other JVM-based programming languages, such as JRuby and Jython. At present, their support for Android is not always 100 percent smooth, but progress is continually being made. Those interested in JRuby on Android, for instance, should investigate the Ruboto open source project, at http://ruboto.org.

Additionally, Scripting Layer for Android (SL4A), described at http://code.google.com/p/android-scripting/, allows you to write scripts in a wide range of scripting languages, beyond BeanShell, such as the following:

  • Perl
  • Python
  • JRuby
  • Lua
  • JavaScript (implemented via Rhino, the Mozilla JavaScript interpreter written in Java)
  • PHP

These scripts are not full-fledged applications, though the SL4A team is working on allowing you to turn them into APK files complete with basic UIs. For on-device development, SL4A is a fine choice. Notable projects developed with SL4A include the Nexus One sensor logging payload. If you're interested in further SL4A reading and development, an excellent book on the topic is Pro Android Python with SL4A, by Paul Ferrill (Apress, 2011).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.128.57