While researching possible technologies for implementing a publish/subscribe-based task distribution system for long-running, semi-autonomous/intelligent agents (with Android as a supported platform), ZeroMQ emerged as a sensible choice of message transport, given the exploding complexity of AMQP (Pieter Hintjens' August 2008 steering committee missive sums up my misgivings).

ZeroMQ vs. JeroMQ

The ZeroMQ/jzmq Android build instructions look pretty onerous, particularly for pre-3.0 versions (due to a libuuid dependency)—JeroMQ (a pure Java implemention)—seemed like a natural choice. I haven't benchmarked anything like a real-world use case, though there are some promising numbers published by the JeroMQ authors.

Since the JeroMQ and jzmq (0.2.0 series) API structures are functionally identical, there shouldn't be any real cost associated with making a choice for exploratory reasons (barring showstopping bugs). The code snippets below adumbrate a minimal working example of a ZMQ client/server in request/response mode, running in a single process (an Android application). There are a dearth of Android-specific ZMQ examples around—I've endeavoured to use Android-specific concurrency abstractions where they seem idiomatic.

Note that the purpose of this example/tutorial is to provide examples of how to issue a request and process a response using a trivial message format with ZMQ—while all of the work is happening in a single process, the server & client threads can be viewed as separate applications; trivial adaptations of the Hello World request/response example applications (hwclient & hwserver) which are ubiquitous in ZMQ tutorials.

Code

Let's start with a Handler which takes an instance (conforming to a trivial interface) to which it dispatches message events, and a key name identifying the String datum within the corresponding Message's Bundle which holds the message payload.

Predictably, the interface isn't particularly jazzy.

The long-running server, which blocks on reads and instantly responds with a reversed version of the message payload is defined as a Runnable, taking a Handler which is used to communicate the content of incoming messages to interested parties.

The client/request-side is implemented as an AsyncTask which re-does all of its setup when run. AsyncTask.execute takes a String to use as the message body, and the constructor, as above, takes a Handler to which received messages are dispatched (after being bundled).

UI

The UI is incredibly simple, and the layout XML doesn't bear repeating. The three pieces of information required to make the Activity code intelligible are:

text_message is the EditText at the top.

is the EditText at the top. button_send_message is the Button beside it.

is the Button beside it. text_console is the large TextView console below.

Wiring Everything Together

Notes:

The static methods in Util aren't particularly useful - the implementations have been omitted to reduce clutter.

aren't particularly useful - the implementations have been omitted to reduce clutter. No Activity -lifecycle contingencies have been made in the above code.

-lifecycle contingencies have been made in the above code. From the AsyncTask documentation: “When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.” Both seem like strange choices to me. In any case, this example doesn't use THREAD_POOL_EXECUTOR , so client tasks won't run concurrently.

, so client tasks won't run concurrently. Your application's manifest ( AndroidManifest.xml ) will have to request android.permissions.INTERNET if you're using the TCP transport, as in this example.

Alternatives

MQTT makes sense on a couple of axes, though it may be a slightly curious choice given the heterogeneity of clients in this use-case (it'd be easier to defend if clients were exclusively Android, or mobile-only). It may well be the subject of a follow-up blog-post.

ZeroMQ is used more in the wild, and it may be more flexible in case any strange requirements emerge (for example, if we were to develop an in-browser Javascript task consumer which required the proxying of ZMQ messages over HTTP, then the existence of middleware-factories like Mule might make this easier). There's an example of what looks something like ZMQ over HTTP via Mule although I haven't looked at it (Mule, nor that example) in depth. The word “middleware” makes me a little queasy.