Tuesday, August 31, 2010

Turn your Android Phone Into a Remote Spy Camera with Ruby in 15 Minutes

Update 8/20/12: This project is over two years old at this point, and I am no longer working on it.  This was a proof of concept and, unfortunately, I am no longer able to provide support to readers with questions.

It's been a great year for Ruby on Android, but no one knows it.

Sinatra running on a Motorola Droid

You can start writing Ruby apps for Android devices TODAY.  You don't need to install any SDK, you don't need to install some giant Eclipse IDE, and you certainly don't need to write any Java.

Some of you may have heard of Ruboto, but Damon Kohler and the team at android-scripting have been quietly improving SL4A over the past year, adding tons of features and improving stability.
Scripting Layer for Android (SL4A, formerly known as Android Scripting Environment or ASE) brings scripting languages to Android by allowing you to edit and execute scripts and interactive interpreters directly on the Android device. These scripts have access to many of the APIs available to full-fledged Android applications, but with a greatly simplified interface that makes it easy to get things done...  Python, Perl, JRuby, Lua, BeanShell, JavaScript, Tcl, and shell are currently supported, and we're planning to add more.
There's even support for distributing  programs as APKs, so the implementation language and dependencies are totally transparent to users.

We'd love to run some simple Ruby scripts on Android, but what about running a complete, albeit simple, application?  Will it work?

Most Rubyists use Ruby to build web applications, so let's run with that.  Let's build a spy camera app, so I can figure out who's been stealing ink cartridges from our office.  The app should (a) show me a snapshot of what the camera currently sees and (b) update that snapshot on demand.

We need a simple, lightweight ruby framework to use. Sinatra is very easy to use and should even be able to run on older Android devices.

Similarly, we need a simple, lightweight, pure ruby web server.  WEBrick is pure ruby, part of the standard library, and fast enough to run on Android.  Works for me!

First, let's work from our development machine (i.e. laptop).  No need to touch the phone just yet.

Start a New Sinatra Project

But wait!  What about Sinatra itself?  We can't easily install rubygems on our Android phone, so we'll have to vendorize Sinatra and all dependencies and ship them with our application.  Since we'll be running JRuby on Android, we can't use any libraries that have native C extensions or are otherwise JRuby-incompatible.

Make Directories for Gems and Snapshots

Vendorize your Gems

Create the App

Create a file called spycamera.rb in the project directory.

First, let's set some constants for the important directories in our application. When running apps under SL4A, we need to be very explicit about directory paths.

Let's update our load path, so JRuby can find our vendorized gems.

Next, we'll load Sinatra.  We'll have to explicitly load rack first, to avoid uninitialized constant errors under SL4A.

Finally, we require the Android API interface, available under SL4A, and initialize an Android object.  This will allow us to make API calls, like one that tells the camera to take and store a picture.

Now, let's create a very simple HTML template.  The template should just display the latest snapshot, which we'll be saving to public/latest.png.  If I click on that snapshot, it should take a new snapshot and refresh the page.

Finally, create a tiny Sinatra app that takes a picture, saves it, and renders the template.

Install (Deploy) The App

Now you can finally use your phone!  Grab that Android device and install SL4A (r1 APK available here).  Run SL4A, go to the interpreters menu, and install JRuby.

Once JRuby is installed, it's time to deploy your application to the phone.

Connect your phone to your development machine via USB, and simply copy the contents of your app to SL4A's script directory on your phone.  There may be some sample ruby scripts left over from the SL4A install; you can delete them if you like.

Copying the project contents onto the deivice.

At this point, just run spycam.rb from SL4A and you're good to go!

Starting the Sinatra app from SL4A

Place your newly-activated spy camera somewhere, hide in your office/cube, start your web browser, and navigate to http://ip.address.of.phone:4567.  You can do this from inside your local network via wifi, or, carrier permitting, over 3G.

Happy spying!

Further Reading
Check out my open-source project, Broadcast, on Github.  It's a more refined, general-purpose embedded web app for Android.  It allows for further remote monitoring and control, such as location tracking, remote text-to-speech, and remote file management over HTTP.  

The source code for the spycam app is available on github here.

Check these out, too:


JOO said...

thanks for sweet script :)

connect via 3G network with ssh tunnel(using ConnectBot and my ssh server) - http://flic.kr/p/8xf3BG

Anonymous said...

Nice! BTW, Ruboto now supports creating .apks as well: ruboto-core

Jackson Broshear said...

Ooo, super fun! Thanks!

Unknown said...

It doesnt work, I get this error:

spycam.rb:6: syntax error, unexpected tCONSTANT, expecting '}'
...LOAD_PATH << File.join GEM_DIR, dir, 'lib'}
spycam.rb:6: syntax error, unexpected '}', expecting tCOLON2 or '[' or '.'
spycam.rb:44: syntax error, unexpected $end, expecting '}'

Mike Leone said...

Sigmar, thanks for the heads up. I fixed the error, and changes have been pushed here.

Anonymous said...

Great tutorial, thanks!
One problem however, I hear my phone taking the pictures, but they are completely black, any idea?
I'm on HTC Hero, Android 2.1

Mike Leone said...

Spint, if your camera normally works fine but isn't taking pictures properly with this app, it's probably an issue with SL4A and the HTC Hero in particular. You should file a bug here; the team is always improving support for more devices.

At first, camera support for my Motorola Droid was a bit spotty, but I filed a bug and they had it fixed and released within a week or two.

Anonymous said...

Ok Mike, apparently there was already a related issue (#400), tnx !

Anonymous said...

nice stuff! I knew about sl4a but didn't know it was this easy now

AJ said...


Doesn't work for me.

I get

Dalvik VM unable to locate class 'org/jruby/Main'
java.lang.NoClassDefFoundError: org.jruby.Main

Any ideas?

Jaime said...

Great! I tried it on my Nexus One and works! JRuby crashes from time to time, though.

I'll play a bit with this, thanks!

Patrick van Efferen said...


I get the same error on my HTC magic, after a few minutes webrick starts up. Because my phone is rather slow i suspect thats wat's causing the error, works later on.

Niranjan said...

This is really nice !


Amit Kumar said...

This is freaking kool... thanks dude !!

hexxamillion said...

I get to the part where I have successfully installed SL4A. Can you clarify the step to "go to the interpreters menu, and install JRuby"

I found the intepreters menu and ran the shell. What is the syntax for installing jruby?

hexxamillion said...

Nevermind..I'm new to this android scripting..I found JRuby now.

hexxamillion said...

/sdcard/sl4a/scripts/vendor/gems/sinatra-1.1.0/lib/sinatra/base.rb:7:in 'require': no such file to load -- tilt (LoadError) from /sdcard/sl4a/scripts/vendor/gems/sinatra-1.1.0/lib/sinatra/base.rb:7

Any suggestions? I saw tilt listed in the base.rb but not sure what path it's looking for the file at.

hexxamillion said...

Woohoo!! Finally. I got it. This is cool. I did not have a tilt.rb file and I also replaced the sinatra base.rb with what was on github. NOt sure which did the trick but I was able to see the snapshot through the wifi connection on my desktop.

Tom Belpasso said...

Great tutorial and program. I have been playing with Ruby on Rails for a couple of weeks but still tying to run my old app in Ruby192. This works after including the tilt gem into the vendor dir. Sinatra is really simple compared to rails.

One issue is that the Samsung Moment makes a shutter sound when it takes the picture. Kind of defeats the "spy" aspect. Also the server seems to stop running after a while.

PeuchereBike said...

Fantastique !, I ve successfully tested on sony Xperia mini, great, just get some issue with tilt, install with cygwin (windows xp)
$ gem install tilt
$ gem unpack tolt --target=vendor/gems

many merci!

CarlosJHR64 said...

Couple of pitfalls for me...
sl4a_r1 is now deprecated, and the latest version is sl4a_r4.
JRuby install has a second install step... the initial JRuby app is actually an installer which you need to run.
And you need to unpack into target the tilt gem, as described by the previous comment.
Works... very happy.

Anonymous said...

Thank you for a high quality tutorial!
Scriptable devices = future? A dream?
You revealed this is present.

Subhendu Sinha Chaudhuri said...

I want to use my android as a eye for the robot I have built. The android would be controlled via PC which will further control the micro controller. Now Web Cam app is perfect in one portion to deliver the video to the PC. But I need another utility in the Android which will run to accept commands from the PC. How that can be done?

Any help will be highly appreciated.
I am from India

mrthomas2012 said...

can someone explain how to do from create an app to next we load shana

loverboy said...

For us non-technical geeks can we not have a simple app that installs and is hidden and doing the same job. A covert camera/web cam monitor that can be viewed by connecting to phone's IP or IMEI?

Unknown said...

For some reasons, server stopped running after taking photo.
Anyways, it was a great tutorial and proved that Rails applications can run on limited environments like android OS.


Unknown said...

hi mike, nice code...i'm playing with this,..one question please:
how to increase the quality of the shot;
exiftool tell me the shot is maded at 480x640 and is a jpg old version...

my android camera is usually setted in maximum resolution,

and one other question; why if i save the file from the browser this is latest.png?...
and in ubuntu eog advise me...latest it's not a png....ok i rename in jpg and all is correct...thanks mike for your nice idea

Unknown said...

Hidden spy cameras can provide a great benefit to people if they use them properly. For many people, the reason that they use a hidden camera is to keep watch and monitor people, places and things they they're concerned.
Click Here

Unknown said...

The uses of a Spy Camera other than spying. Most people think that only government agencies and professional spies need a spy camera. This could not be further from the truth as they offer plenty of benefits.

Anonymous said...

so I can figure out who's been stealing ink cartridges from our office. Hidden Spy Camera