So I got a bit more involved after my experiments last week.

This week I did the following:

  • Got the LED Toggler Ruby script from last week exposing a toggle-able LED object over the network with drb under MRI on the Raspberry Pi.
  • Built an Android app.
  • Inside of that Android app I embedded a JRuby ScriptingContainer.
  • In that ScriptingContainer I evaluated some ruby.
  • In that ruby script I connected to the aforementioned drb object.
  • On button press in the Android app, I call the #toggle method of the drb object.

This all combines to have the effect of an android app to toggle an LED on the network. This is, of course, extremely awesome and extensible. See the video above for proof.

The code for these things is available here:

I'll also just put the relevant bits of code in the post here:


require 'drb/drb'
require 'pi_piper'

# The URI for the server to connect to

class Toggler
  attr_accessor :pin, :state

  def initialize
    @pin = 15, direction: :out)
    @state = false

  def toggle
    state ? pin.on :
    @state = !state
    puts 'toggled'

# The object that handles requests on the server

$SAFE = 1   # disable eval() and friends

DRb.start_service(URI, FRONT_OBJECT)
# Wait for the drb server thread to finish before exiting.

package com.isotope11.ledclicker;

import java.util.ArrayList;
import java.util.List;

import org.apache.bsf.BSFException;
import org.jruby.embed.ScriptingContainer;

import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

  protected final String TAG = MainActivity.class.toString();
  protected ScriptingContainer mRubyContainer;
  protected String mDrbResult;

  protected void onCreate(Bundle savedInstanceState) {
    System.setProperty("jruby.bytecode.version", "1.5");
    mRubyContainer = new ScriptingContainer();
    List<String> loadPaths = new ArrayList<String>();

  public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(, menu);
    return true;

  public void onLEDClickerClick(View view) {
    RubyRunner rubyRunner = new RubyRunner();

  public void handleDrbResult() {
    Toast.makeText(this, mDrbResult, Toast.LENGTH_LONG).show();

  private class RubyRunner extends AsyncTask<Object, Void, String> {

    protected String doInBackground(Object... arg0) {
      String rubyDrbClient = "require 'drb/drb';SERVER_URI='druby://';DRb.start_service;toggler = DRbObject.new_with_uri(SERVER_URI);toggler.toggle";
      String result = (String) mRubyContainer.runScriptlet(rubyDrbClient);
      return result;

    protected void onPostExecute(String result){
      mDrbResult = result;


Josh Adams is a developer and architect with over eleven years of professional experience building production-quality software and managing projects. Josh is isotope|eleven's lead architect, and is responsible for overseeing architectural decisions and translating customer requirements into working software. Josh graduated from the University of Alabama at Birmingham (UAB) with Bachelor of Science degrees in both Mathematics and Philosophy. He runs the ElixirSips screencast series, teaching hundreds of developers Elixir. He also occasionally provides Technical Review for Apress Publishing, specifically regarding Arduino microprocessors. When he's not working, Josh enjoys spending time with his family.